diff options
author | dchagin <dchagin@FreeBSD.org> | 2016-05-07 19:05:39 +0000 |
---|---|---|
committer | dchagin <dchagin@FreeBSD.org> | 2016-05-07 19:05:39 +0000 |
commit | 2bbf6b4b75457aadc05058cc03b671f3372b6eb2 (patch) | |
tree | 209c00ccf482e7ce79ada75189d4cc3da804f889 | |
parent | 5caad23a8a432db49f549d3e8e215f47f1ba89e6 (diff) | |
download | FreeBSD-src-2bbf6b4b75457aadc05058cc03b671f3372b6eb2.zip FreeBSD-src-2bbf6b4b75457aadc05058cc03b671f3372b6eb2.tar.gz |
MFC r295856 (by des@):
Implement /proc/$$/limits.
MFC r297781 (by dchagin@):
More complete implementation of /proc/self/limits.
Fix the way the code accesses process limits struct - pointed out by mjg@.
MFC r298318, 298319 (by cem@):
Don't print uninitialized values and initialize error return before use.
PR: 207386
-rw-r--r-- | sys/compat/linprocfs/linprocfs.c | 94 | ||||
-rw-r--r-- | sys/compat/linux/linux_misc.h | 7 |
2 files changed, 101 insertions, 0 deletions
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c index 8aac3ea..bf0610b 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$"); #include <sys/proc.h> #include <sys/ptrace.h> #include <sys/resourcevar.h> +#include <sys/resource.h> #include <sys/sbuf.h> #include <sys/sem.h> #include <sys/smp.h> @@ -1350,6 +1351,97 @@ linprocfs_dofdescfs(PFS_FILL_ARGS) return (0); } +/* + * Filler function for proc/pid/limits + */ +static const struct linux_rlimit_ident { + const char *desc; + const char *unit; + unsigned int rlim_id; +} linux_rlimits_ident[] = { + { "Max cpu time", "seconds", RLIMIT_CPU }, + { "Max file size", "bytes", RLIMIT_FSIZE }, + { "Max data size", "bytes", RLIMIT_DATA }, + { "Max stack size", "bytes", RLIMIT_STACK }, + { "Max core file size", "bytes", RLIMIT_CORE }, + { "Max resident set", "bytes", RLIMIT_RSS }, + { "Max processes", "processes", RLIMIT_NPROC }, + { "Max open files", "files", RLIMIT_NOFILE }, + { "Max locked memory", "bytes", RLIMIT_MEMLOCK }, + { "Max address space", "bytes", RLIMIT_AS }, + { "Max file locks", "locks", LINUX_RLIMIT_LOCKS }, + { "Max pending signals", "signals", LINUX_RLIMIT_SIGPENDING }, + { "Max msgqueue size", "bytes", LINUX_RLIMIT_MSGQUEUE }, + { "Max nice priority", "", LINUX_RLIMIT_NICE }, + { "Max realtime priority", "", LINUX_RLIMIT_RTPRIO }, + { "Max realtime timeout", "us", LINUX_RLIMIT_RTTIME }, + { 0, 0, 0 } +}; + +static int +linprocfs_doproclimits(PFS_FILL_ARGS) +{ + const struct linux_rlimit_ident *li; + struct plimit *limp; + struct rlimit rl; + ssize_t size; + int res, error; + + error = 0; + + PROC_LOCK(p); + limp = lim_hold(p->p_limit); + PROC_UNLOCK(p); + size = sizeof(res); + sbuf_printf(sb, "%-26s%-21s%-21s%-21s\n", "Limit", "Soft Limit", + "Hard Limit", "Units"); + for (li = linux_rlimits_ident; li->desc != NULL; ++li) { + switch (li->rlim_id) + { + case LINUX_RLIMIT_LOCKS: + /* FALLTHROUGH */ + case LINUX_RLIMIT_RTTIME: + rl.rlim_cur = RLIM_INFINITY; + break; + case LINUX_RLIMIT_SIGPENDING: + error = kernel_sysctlbyname(td, + "kern.sigqueue.max_pending_per_proc", + &res, &size, 0, 0, 0, 0); + if (error != 0) + goto out; + rl.rlim_cur = res; + rl.rlim_max = res; + break; + case LINUX_RLIMIT_MSGQUEUE: + error = kernel_sysctlbyname(td, + "kern.ipc.msgmnb", &res, &size, 0, 0, 0, 0); + if (error != 0) + goto out; + rl.rlim_cur = res; + rl.rlim_max = res; + break; + case LINUX_RLIMIT_NICE: + /* FALLTHROUGH */ + case LINUX_RLIMIT_RTPRIO: + rl.rlim_cur = 0; + rl.rlim_max = 0; + break; + default: + rl = limp->pl_rlimit[li->rlim_id]; + break; + } + if (rl.rlim_cur == RLIM_INFINITY) + sbuf_printf(sb, "%-26s%-21s%-21s%-10s\n", + li->desc, "unlimited", "unlimited", li->unit); + else + sbuf_printf(sb, "%-26s%-21llu%-21llu%-10s\n", + li->desc, (unsigned long long)rl.rlim_cur, + (unsigned long long)rl.rlim_max, li->unit); + } +out: + lim_free(limp); + return (error); +} /* * Filler function for proc/sys/kernel/random/uuid @@ -1488,6 +1580,8 @@ linprocfs_init(PFS_INIT_ARGS) NULL, NULL, NULL, 0); pfs_create_file(dir, "auxv", &linprocfs_doauxv, NULL, &procfs_candebug, NULL, PFS_RD|PFS_RAWRD); + pfs_create_file(dir, "limits", &linprocfs_doproclimits, + NULL, NULL, NULL, PFS_RD); /* /proc/scsi/... */ dir = pfs_create_dir(root, "scsi", NULL, NULL, NULL, 0); diff --git a/sys/compat/linux/linux_misc.h b/sys/compat/linux/linux_misc.h index f969c4d..d140c67 100644 --- a/sys/compat/linux/linux_misc.h +++ b/sys/compat/linux/linux_misc.h @@ -141,6 +141,13 @@ extern int stclohz; #define LINUX_P_PID 1 #define LINUX_P_PGID 2 +#define LINUX_RLIMIT_LOCKS RLIM_NLIMITS + 1 +#define LINUX_RLIMIT_SIGPENDING RLIM_NLIMITS + 2 +#define LINUX_RLIMIT_MSGQUEUE RLIM_NLIMITS + 3 +#define LINUX_RLIMIT_NICE RLIM_NLIMITS + 4 +#define LINUX_RLIMIT_RTPRIO RLIM_NLIMITS + 5 +#define LINUX_RLIMIT_RTTIME RLIM_NLIMITS + 6 + #define LINUX_RLIM_INFINITY (~0UL) int linux_common_wait(struct thread *td, int pid, int *status, |