From 7cc0ebfd10f73b2fdb7ef33a013ba38c4293d7ae Mon Sep 17 00:00:00 2001 From: Mikolaj Golub Date: Sat, 20 Apr 2013 07:59:44 +0000 Subject: [PATCH] Add procstat_getrlimit function to retrieve a process resource limits info. MFC after: 1 month --- lib/libprocstat/Symbol.map | 1 + lib/libprocstat/core.c | 4 +++ lib/libprocstat/core.h | 1 + lib/libprocstat/libprocstat.3 | 17 +++++++++ lib/libprocstat/libprocstat.c | 68 +++++++++++++++++++++++++++++++++++ lib/libprocstat/libprocstat.h | 3 ++ 6 files changed, 94 insertions(+) diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map index 1970a7a2d944..461d32058ba1 100644 --- a/lib/libprocstat/Symbol.map +++ b/lib/libprocstat/Symbol.map @@ -20,6 +20,7 @@ FBSD_1.3 { procstat_freevmmap; procstat_get_shm_info; procstat_getgroups; + procstat_getrlimit; procstat_getumask; procstat_getvmmap; procstat_open_core; diff --git a/lib/libprocstat/core.c b/lib/libprocstat/core.c index 5732f406643f..2ff3975f69b7 100644 --- a/lib/libprocstat/core.c +++ b/lib/libprocstat/core.c @@ -175,6 +175,10 @@ procstat_core_get(struct procstat_core *core, enum psc_type type, void *buf, n_type = NT_PROCSTAT_UMASK; structsize = sizeof(u_short); break; + case PSC_TYPE_RLIMIT: + n_type = NT_PROCSTAT_RLIMIT; + structsize = sizeof(struct rlimit) * RLIM_NLIMITS; + break; default: warnx("unknown core stat type: %d", type); return (NULL); diff --git a/lib/libprocstat/core.h b/lib/libprocstat/core.h index 6e7ed027b0c4..967c1930c084 100644 --- a/lib/libprocstat/core.h +++ b/lib/libprocstat/core.h @@ -35,6 +35,7 @@ enum psc_type { PSC_TYPE_VMMAP, PSC_TYPE_GROUPS, PSC_TYPE_UMASK, + PSC_TYPE_RLIMIT, }; struct procstat_core; diff --git a/lib/libprocstat/libprocstat.3 b/lib/libprocstat/libprocstat.3 index 06a66a06bca0..bc78d684d7db 100644 --- a/lib/libprocstat/libprocstat.3 +++ b/lib/libprocstat/libprocstat.3 @@ -128,6 +128,13 @@ .Fa "unsigned int *count" .Fc .Ft "int" +.Fo procstat_getrlimit +.Fa "struct procstat *procstat" +.Fa "struct kinfo_proc *kp" +.Fa "int which" +.Fa "struct rlimit* rlimit" +.Fc +.Ft "int" .Fo procstat_getumask .Fa "struct procstat *procstat" .Fa "struct kinfo_proc *kp" @@ -261,6 +268,16 @@ The caller is responsible to free the allocated memory with a subsequent function call. .Pp The +.Fn procstat_getrlimit +function gets a pointer to the +.Vt procstat +structure, a pointer to +.Vt kinfo_proc +structure, resource index +.Fa which , +and returns the actual resource limit in the 4th reference parameter. +.Pp +The .Fn procstat_getumask function gets a pointer to the .Vt procstat diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index 1ee0f973bebc..04c10580916b 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -135,6 +136,10 @@ static int procstat_get_vnode_info_sysctl(struct filestat *fst, static gid_t *procstat_getgroups_core(struct procstat_core *core, unsigned int *count); static gid_t *procstat_getgroups_sysctl(pid_t pid, unsigned int *count); +static int procstat_getrlimit_core(struct procstat_core *core, int which, + struct rlimit* rlimit); +static int procstat_getrlimit_sysctl(pid_t pid, int which, + struct rlimit* rlimit); static int procstat_getumask_core(struct procstat_core *core, unsigned short *maskp); static int procstat_getumask_sysctl(pid_t pid, unsigned short *maskp); @@ -1712,3 +1717,66 @@ procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp, return (-1); } } + +static int +procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit) +{ + int error, name[5]; + size_t len; + + name[0] = CTL_KERN; + name[1] = KERN_PROC; + name[2] = KERN_PROC_RLIMIT; + name[3] = pid; + name[4] = which; + len = sizeof(struct rlimit); + error = sysctl(name, 5, rlimit, &len, NULL, 0); + if (error < 0 && errno != ESRCH) { + warn("sysctl: kern.proc.rlimit: %d", pid); + return (-1); + } + if (error < 0 || len != sizeof(struct rlimit)) + return (-1); + return (0); +} + +static int +procstat_getrlimit_core(struct procstat_core *core, int which, + struct rlimit* rlimit) +{ + size_t len; + struct rlimit* rlimits; + + if (which < 0 || which >= RLIM_NLIMITS) { + errno = EINVAL; + warn("getrlimit: which"); + return (-1); + } + rlimits = procstat_core_get(core, PSC_TYPE_RLIMIT, NULL, &len); + if (rlimits == NULL) + return (-1); + if (len < sizeof(struct rlimit) * RLIM_NLIMITS) { + free(rlimits); + return (-1); + } + *rlimit = rlimits[which]; + return (0); +} + +int +procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, int which, + struct rlimit* rlimit) +{ + switch(procstat->type) { + case PROCSTAT_KVM: + warnx("kvm method is not supported"); + return (-1); + case PROCSTAT_SYSCTL: + return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit)); + case PROCSTAT_CORE: + return (procstat_getrlimit_core(procstat->core, which, rlimit)); + default: + warnx("unknown access method: %d", procstat->type); + return (-1); + } +} diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h index 8d14d0fa8936..05046af06373 100644 --- a/lib/libprocstat/libprocstat.h +++ b/lib/libprocstat/libprocstat.h @@ -91,6 +91,7 @@ struct kinfo_vmentry; struct procstat; +struct rlimit; struct filestat { int fs_type; /* Descriptor type. */ int fs_flags; /* filestat specific flags. */ @@ -170,6 +171,8 @@ gid_t *procstat_getgroups(struct procstat *procstat, struct kinfo_proc *kp, unsigned int *count); int procstat_getumask(struct procstat *procstat, struct kinfo_proc *kp, unsigned short* umask); +int procstat_getrlimit(struct procstat *procstat, struct kinfo_proc *kp, + int which, struct rlimit* rlimit); struct kinfo_vmentry *procstat_getvmmap(struct procstat *procstat, struct kinfo_proc *kp, unsigned int *count); struct procstat *procstat_open_core(const char *filename);