summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2013-05-03 21:11:57 +0000
committerjhb <jhb@FreeBSD.org>2013-05-03 21:11:57 +0000
commit679fa5ed4e91b1d9e2002d8da43d9c31056fe7a4 (patch)
tree4b4ec8c6d14c8986e2139b96edf75a870d996980 /lib
parent66bb8e0f75e5284e0b64916ea8295efb5ca1fff6 (diff)
downloadFreeBSD-src-679fa5ed4e91b1d9e2002d8da43d9c31056fe7a4.zip
FreeBSD-src-679fa5ed4e91b1d9e2002d8da43d9c31056fe7a4.tar.gz
Similar to 233760 and 236717, export some more useful info about the
kernel-based POSIX semaphore descriptors to userland via procstat(1) and fstat(1): - Change sem file descriptors to track the pathname they are associated with and add a ksem_info() method to copy the path out to a caller-supplied buffer. - Use the fo_stat() method of shared memory objects and ksem_info() to export the path, mode, and value of a semaphore via struct kinfo_file. - Add a struct semstat to the libprocstat(3) interface along with a procstat_get_sem_info() to export the mode and value of a semaphore. - Teach fstat about semaphores and to display their path, mode, and value. MFC after: 2 weeks
Diffstat (limited to 'lib')
-rw-r--r--lib/libprocstat/Symbol.map1
-rw-r--r--lib/libprocstat/libprocstat.314
-rw-r--r--lib/libprocstat/libprocstat.c90
-rw-r--r--lib/libprocstat/libprocstat.h6
4 files changed, 110 insertions, 1 deletions
diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index 085720c..1495bfc 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -22,6 +22,7 @@ FBSD_1.3 {
procstat_freegroups;
procstat_freekstack;
procstat_freevmmap;
+ procstat_get_sem_info;
procstat_get_shm_info;
procstat_getargv;
procstat_getauxv;
diff --git a/lib/libprocstat/libprocstat.3 b/lib/libprocstat/libprocstat.3
index 3312427..e82c30a 100644
--- a/lib/libprocstat/libprocstat.3
+++ b/lib/libprocstat/libprocstat.3
@@ -53,6 +53,7 @@
.Nm procstat_freevmmap ,
.Nm procstat_get_pipe_info ,
.Nm procstat_get_pts_info ,
+.Nm procstat_get_sem_info ,
.Nm procstat_get_shm_info ,
.Nm procstat_get_socket_info ,
.Nm procstat_get_vnode_info
@@ -115,6 +116,13 @@
.Fa "char *errbuf"
.Fc
.Ft int
+.Fo procstat_get_sem_info
+.Fa "struct procstat *procstat"
+.Fa "struct filestat *fst"
+.Fa "struct semstat *sem"
+.Fa "char *errbuf"
+.Fc
+.Ft int
.Fo procstat_get_shm_info
.Fa "struct procstat *procstat"
.Fa "struct filestat *fst"
@@ -463,12 +471,13 @@ function call.
The
.Fn procstat_get_pipe_info ,
.Fn procstat_get_pts_info ,
+.Fn procstat_get_sem_info ,
.Fn procstat_get_shm_info ,
.Fn procstat_get_socket_info
and
.Fn procstat_get_vnode_info
functions are used to retrieve information about pipes, pseudo-terminals,
-shared memory objects,
+semaphores, shared memory objects,
sockets, and vnodes, respectively.
Each of them have a similar interface API.
The
@@ -505,6 +514,8 @@ argument indicates an actual error message in case of failure.
.Nm procstat_get_pipe_info
.It Li PS_FST_TYPE_PTS
.Nm procstat_get_pts_info
+.It Li PS_FST_TYPE_SEM
+.Nm procstat_get_sem_info
.It Li PS_FST_TYPE_SHM
.Nm procstat_get_shm_info
.El
@@ -517,6 +528,7 @@ argument indicates an actual error message in case of failure.
.Xr elf 3 ,
.Xr kvm 3 ,
.Xr queue 3 ,
+.Xr sem_open 3 ,
.Xr sysctl 3 ,
.Xr pts 4 ,
.Xr core 5 ,
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index dd16c80..78eae9f 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#define _WANT_FILE
#include <sys/file.h>
#include <sys/conf.h>
+#include <sys/ksem.h>
#include <sys/mman.h>
#define _KERNEL
#include <sys/mount.h>
@@ -129,6 +130,10 @@ static int procstat_get_pts_info_sysctl(struct filestat *fst,
struct ptsstat *pts, char *errbuf);
static int procstat_get_pts_info_kvm(kvm_t *kd, struct filestat *fst,
struct ptsstat *pts, char *errbuf);
+static int procstat_get_sem_info_sysctl(struct filestat *fst,
+ struct semstat *sem, char *errbuf);
+static int procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
+ struct semstat *sem, char *errbuf);
static int procstat_get_shm_info_sysctl(struct filestat *fst,
struct shmstat *shm, char *errbuf);
static int procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
@@ -556,6 +561,10 @@ procstat_getfiles_kvm(struct procstat *procstat, struct kinfo_proc *kp, int mmap
data = file.f_data;
break;
#endif
+ case DTYPE_SEM:
+ type = PS_FST_TYPE_SEM;
+ data = file.f_data;
+ break;
case DTYPE_SHM:
type = PS_FST_TYPE_SHM;
data = file.f_data;
@@ -1003,6 +1012,87 @@ procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
}
int
+procstat_get_sem_info(struct procstat *procstat, struct filestat *fst,
+ struct semstat *sem, char *errbuf)
+{
+
+ assert(sem);
+ if (procstat->type == PROCSTAT_KVM) {
+ return (procstat_get_sem_info_kvm(procstat->kd, fst, sem,
+ errbuf));
+ } else if (procstat->type == PROCSTAT_SYSCTL ||
+ procstat->type == PROCSTAT_CORE) {
+ return (procstat_get_sem_info_sysctl(fst, sem, errbuf));
+ } else {
+ warnx("unknown access method: %d", procstat->type);
+ snprintf(errbuf, _POSIX2_LINE_MAX, "error");
+ return (1);
+ }
+}
+
+static int
+procstat_get_sem_info_kvm(kvm_t *kd, struct filestat *fst,
+ struct semstat *sem, char *errbuf)
+{
+ struct ksem ksem;
+ void *ksemp;
+ char *path;
+ int i;
+
+ assert(kd);
+ assert(sem);
+ assert(fst);
+ bzero(sem, sizeof(*sem));
+ ksemp = fst->fs_typedep;
+ if (ksemp == NULL)
+ goto fail;
+ if (!kvm_read_all(kd, (unsigned long)ksemp, &ksem,
+ sizeof(struct ksem))) {
+ warnx("can't read ksem at %p", (void *)ksemp);
+ goto fail;
+ }
+ sem->mode = S_IFREG | ksem.ks_mode;
+ sem->value = ksem.ks_value;
+ if (fst->fs_path == NULL && ksem.ks_path != NULL) {
+ path = malloc(MAXPATHLEN);
+ for (i = 0; i < MAXPATHLEN - 1; i++) {
+ if (!kvm_read_all(kd, (unsigned long)ksem.ks_path + i,
+ path + i, 1))
+ break;
+ if (path[i] == '\0')
+ break;
+ }
+ path[i] = '\0';
+ if (i == 0)
+ free(path);
+ else
+ fst->fs_path = path;
+ }
+ return (0);
+
+fail:
+ snprintf(errbuf, _POSIX2_LINE_MAX, "error");
+ return (1);
+}
+
+static int
+procstat_get_sem_info_sysctl(struct filestat *fst, struct semstat *sem,
+ char *errbuf __unused)
+{
+ struct kinfo_file *kif;
+
+ assert(sem);
+ assert(fst);
+ bzero(sem, sizeof(*sem));
+ kif = fst->fs_typedep;
+ if (kif == NULL)
+ return (0);
+ sem->value = kif->kf_un.kf_sem.kf_sem_value;
+ sem->mode = kif->kf_un.kf_sem.kf_sem_mode;
+ return (0);
+}
+
+int
procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
struct shmstat *shm, char *errbuf)
{
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 2c2662d..65a5eb9 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -133,6 +133,10 @@ struct pipestat {
uint64_t addr;
uint64_t peer;
};
+struct semstat {
+ uint32_t value;
+ uint16_t mode;
+};
struct shmstat {
uint64_t size;
uint16_t mode;
@@ -177,6 +181,8 @@ int procstat_get_pipe_info(struct procstat *procstat, struct filestat *fst,
struct pipestat *pipe, char *errbuf);
int procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
struct ptsstat *pts, char *errbuf);
+int procstat_get_sem_info(struct procstat *procstat, struct filestat *fst,
+ struct semstat *sem, char *errbuf);
int procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
struct shmstat *shm, char *errbuf);
int procstat_get_socket_info(struct procstat *procstat, struct filestat *fst,
OpenPOWER on IntegriCloud