From 4e0cb4b2a0a123023678b5d04848efe8ca87652d Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 6 Jun 2012 21:57:03 +0000 Subject: [PATCH] MFC 233760: Export some more useful info about shared memory objects to userland via procstat(1) and fstat(1): - Change shm file descriptors to track the pathname they are associated with and add a shm_path() method to copy the path out to a caller-supplied buffer. - Use shm_path() to export the path of a shared memory object via struct kinfo_file. - Change procstat to always print out the path for a given object if it is valid. - Teach fstat about shared memory objects and to display their path, mode, and size. git-svn-id: svn://svn.freebsd.org/base/stable/8@236699 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/kern/kern_descrip.c | 11 ++++++ sys/kern/uipc_shm.c | 14 ++++++++ sys/sys/mman.h | 6 +++- usr.bin/fstat/fstat.c | 57 +++++++++++++++++++++++++++++++ usr.bin/procstat/procstat_files.c | 10 ++---- 5 files changed, 89 insertions(+), 9 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c27358297..81faa4e15 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -55,6 +55,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -2742,6 +2743,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) struct kinfo_ofile *kif; struct filedesc *fdp; int error, i, *name; + struct shmfd *shmfd; struct socket *so; struct vnode *vp; struct file *fp; @@ -2779,6 +2781,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) vp = NULL; so = NULL; tp = NULL; + shmfd = NULL; kif->kf_fd = i; switch (fp->f_type) { case DTYPE_VNODE: @@ -2814,6 +2817,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) case DTYPE_SHM: kif->kf_type = KF_TYPE_SHM; + shmfd = fp->f_data; break; case DTYPE_SEM: @@ -2921,6 +2925,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS) strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); } + if (shmfd != NULL) + shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path)); error = SYSCTL_OUT(req, kif, sizeof(*kif)); if (error) break; @@ -2995,6 +3001,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) struct kinfo_file *kif; struct filedesc *fdp; int error, i, *name; + struct shmfd *shmfd; struct socket *so; struct vnode *vp; struct file *fp; @@ -3032,6 +3039,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) vp = NULL; so = NULL; tp = NULL; + shmfd = NULL; kif->kf_fd = i; switch (fp->f_type) { case DTYPE_VNODE: @@ -3067,6 +3075,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) case DTYPE_SHM: kif->kf_type = KF_TYPE_SHM; + shmfd = fp->f_data; break; case DTYPE_SEM: @@ -3174,6 +3183,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER_ARGS) strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path)); } + if (shmfd != NULL) + shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path)); /* Pack record size down */ kif->kf_structsize = offsetof(struct kinfo_file, kf_path) + strlen(kif->kf_path) + 1; diff --git a/sys/kern/uipc_shm.c b/sys/kern/uipc_shm.c index b2a28840b..ec67a8009 100644 --- a/sys/kern/uipc_shm.c +++ b/sys/kern/uipc_shm.c @@ -453,6 +453,7 @@ shm_insert(char *path, Fnv32_t fnv, struct shmfd *shmfd) map->sm_path = path; map->sm_fnv = fnv; map->sm_shmfd = shm_hold(shmfd); + shmfd->shm_path = path; LIST_INSERT_HEAD(SHM_HASH(fnv), map, sm_link); } @@ -475,6 +476,7 @@ shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred) FREAD | FWRITE); if (error) return (error); + map->sm_shmfd->shm_path = NULL; LIST_REMOVE(map, sm_link); shm_drop(map->sm_shmfd); free(map->sm_path, M_SHMFD); @@ -754,3 +756,15 @@ shm_unmap(struct file *fp, void *mem, size_t size) VM_OBJECT_UNLOCK(obj); return (0); } + +void +shm_path(struct shmfd *shmfd, char *path, size_t size) +{ + + if (shmfd->shm_path == NULL) + return; + sx_slock(&shm_dict_lock); + if (shmfd->shm_path != NULL) + strlcpy(path, shmfd->shm_path, size); + sx_sunlock(&shm_dict_lock); +} diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 403302314..a178d7cb3 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -178,7 +178,7 @@ typedef __size_t size_t; #define _SIZE_T_DECLARED #endif -#ifdef _KERNEL +#if defined(_KERNEL) || defined(_WANT_FILE) #include struct file; @@ -202,12 +202,16 @@ struct shmfd { struct timespec shm_birthtime; struct label *shm_label; /* MAC label */ + const char *shm_path; }; +#endif +#ifdef _KERNEL int shm_mmap(struct shmfd *shmfd, vm_size_t objsize, vm_ooffset_t foff, vm_object_t *obj); int shm_map(struct file *fp, size_t size, off_t offset, void **memp); int shm_unmap(struct file *fp, void *mem, size_t size); +void shm_path(struct shmfd *shmfd, char *path, size_t size); #else /* !_KERNEL */ diff --git a/usr.bin/fstat/fstat.c b/usr.bin/fstat/fstat.c index f82e96439..f693302b5 100644 --- a/usr.bin/fstat/fstat.c +++ b/usr.bin/fstat/fstat.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #define _WANT_FILE #include #include +#include #define _KERNEL #include #include @@ -155,6 +156,7 @@ char *getmnton(struct mount *m); void pipetrans(struct pipe *pi, int i, int flag); void socktrans(struct socket *sock, int i); void ptstrans(struct tty *tp, int i, int flag); +void shmtrans(struct shmfd *shmp, int i, int flag); void getinetproto(int number); int getfname(const char *filename); void usage(void); @@ -417,6 +419,12 @@ dofiles(struct kinfo_proc *kp) if (checkfile == 0) ptstrans(file.f_data, i, file.f_flag); } +#endif +#ifdef DTYPE_SHM + else if (file.f_type == DTYPE_SHM) { + if (checkfile == 0) + shmtrans(file.f_data, i, file.f_flag); + } #endif else { dprintf(stderr, @@ -939,6 +947,55 @@ bad: printf("* error\n"); } +void +shmtrans(struct shmfd *shmp, int i, int flag) +{ + struct shmfd shm; + char name[MAXPATHLEN]; + char mode[15]; + char rw[3]; + unsigned j; + + PREFIX(i); + + if (!KVM_READ(shmp, &shm, sizeof(struct shmfd))) { + dprintf(stderr, "can't read shm at %p\n", shmp); + goto bad; + } + + if (shm.shm_path != NULL) { + for (j = 0; j < sizeof(name) - 1; j++) { + if (!KVM_READ(shm.shm_path + j, name + j, 1)) + break; + if (name[j] == '\0') + break; + } + name[j] = '\0'; + } else + name[0] = '\0'; + + rw[0] = '\0'; + if (flag & FREAD) + strcat(rw, "r"); + if (flag & FWRITE) + strcat(rw, "w"); + + shm.shm_mode |= S_IFREG; + if (nflg) { + printf(" "); + (void)snprintf(mode, sizeof(mode), "%o", shm.shm_mode); + } else { + printf(" %-15s", name[0] != '\0' ? name : "-"); + strmode(shm.shm_mode, mode); + } + printf(" %10s %6ju", mode, shm.shm_size); + printf(" %2s\n", rw); + + return; +bad: + printf("* error\n"); +} + /* * Read the cdev structure in the kernel in order to work out the * associated dev_t diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c index debb0e44a..e54aa5620 100644 --- a/usr.bin/procstat/procstat_files.c +++ b/usr.bin/procstat/procstat_files.c @@ -277,13 +277,6 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) printf("%7c ", '-'); switch (kif->kf_type) { - case KF_TYPE_VNODE: - case KF_TYPE_FIFO: - case KF_TYPE_PTS: - printf("%-3s ", "-"); - printf("%-18s", kif->kf_path); - break; - case KF_TYPE_SOCKET: printf("%-3s ", protocol_to_string(kif->kf_sock_domain, @@ -312,7 +305,8 @@ procstat_files(pid_t pid, struct kinfo_proc *kipp) default: printf("%-3s ", "-"); - printf("%-18s", "-"); + printf("%-18s", kif->kf_path[0] != '\0' ? + kif->kf_path : "-"); } printf("\n"); -- 2.45.0