Author: jhb
Date: Sun Apr  1 18:22:48 2012
New Revision: 233760
URL: http://svn.freebsd.org/changeset/base/233760

Log:
  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 the fo_stat() method of shared memory objects and shm_path() to
    export the path, mode, and size of a shared memory object via
    struct kinfo_file.
  - Add a struct shmstat to the libprocstat(3) interface along with a
    procstat_get_shm_info() to export the mode and size of a shared memory
    object.
  - 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.
  
  MFC after:    2 weeks

Modified:
  head/lib/libprocstat/Symbol.map
  head/lib/libprocstat/Versions.def
  head/lib/libprocstat/libprocstat.3
  head/lib/libprocstat/libprocstat.c
  head/lib/libprocstat/libprocstat.h
  head/sys/kern/kern_descrip.c
  head/sys/kern/uipc_shm.c
  head/sys/sys/mman.h
  head/usr.bin/fstat/fstat.c
  head/usr.bin/procstat/procstat_files.c

Modified: head/lib/libprocstat/Symbol.map
==============================================================================
--- head/lib/libprocstat/Symbol.map     Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/lib/libprocstat/Symbol.map     Sun Apr  1 18:22:48 2012        
(r233760)
@@ -14,3 +14,7 @@ FBSD_1.2 {
        procstat_open_kvm;
        procstat_open_sysctl;
 };
+
+FBSD_1.3 {
+       procstat_get_shm_info;
+};

Modified: head/lib/libprocstat/Versions.def
==============================================================================
--- head/lib/libprocstat/Versions.def   Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/lib/libprocstat/Versions.def   Sun Apr  1 18:22:48 2012        
(r233760)
@@ -3,3 +3,8 @@
 # This version was first added to 9.0-current.
 FBSD_1.2 {
 };
+
+# This version was first added to 10.0-current.
+FBSD_1.3 {
+} FBSD_1.2;
+

Modified: head/lib/libprocstat/libprocstat.3
==============================================================================
--- head/lib/libprocstat/libprocstat.3  Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/lib/libprocstat/libprocstat.3  Sun Apr  1 18:22:48 2012        
(r233760)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd July 12, 2011
+.Dd April 1, 2012
 .Dt LIBPROCSTAT 3
 .Os
 .Sh NAME
@@ -37,6 +37,7 @@
 .Nm procstat_freeprocs ,
 .Nm procstat_get_pipe_info ,
 .Nm procstat_get_pts_info ,
+.Nm procstat_get_shm_info ,
 .Nm procstat_get_socket_info ,
 .Nm procstat_get_vnode_info
 .Nd library interface for file and process information retrieval
@@ -70,6 +71,13 @@
 .Fa "char *errbuf"
 .Fc
 .Ft int
+.Fo procstat_get_shm_info
+.Fa "struct procstat *procstat"
+.Fa "struct filestat *fst"
+.Fa "struct shmstat *shm"
+.Fa "char *errbuf"
+.Fc
+.Ft int
 .Fo procstat_get_socket_info
 .Fa "struct procstat *procstat"
 .Fa "struct filestat *fst"
@@ -191,10 +199,12 @@ function call.
 The
 .Fn procstat_get_pipe_info ,
 .Fn procstat_get_pts_info ,
+.Fn procstat_get_shm_info ,
 .Fn procstat_get_socket_info
 and
 .Fn procstat_get_vnode_info
 functions are used to retrive information about pipes, pseudo-terminals,
+shared memory objects,
 sockets, and vnodes, respectively.
 Each of them have a similar interface API.
 The
@@ -231,11 +241,14 @@ argument indicates an actual error messa
 .Nm procstat_get_pipe_info
 .It Li PS_FST_TYPE_PTS
 .Nm procstat_get_pts_info
+.It Li PS_FST_TYPE_SHM
+.Nm procstat_get_shm_info
 .El
 .Sh SEE ALSO
 .Xr fstat 1 ,
 .Xr fuser 1 ,
 .Xr pipe 2 ,
+.Xr shm_open 2 ,
 .Xr socket 2 ,
 .Xr kvm 3 ,
 .Xr queue 3 ,

Modified: head/lib/libprocstat/libprocstat.c
==============================================================================
--- head/lib/libprocstat/libprocstat.c  Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/lib/libprocstat/libprocstat.c  Sun Apr  1 18:22:48 2012        
(r233760)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 #define        _WANT_FILE
 #include <sys/file.h>
 #include <sys/conf.h>
+#include <sys/mman.h>
 #define        _KERNEL
 #include <sys/mount.h>
 #include <sys/pipe.h>
@@ -114,6 +115,10 @@ static int procstat_get_pts_info_sysctl(
     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_shm_info_sysctl(struct filestat *fst,
+    struct shmstat *shm, char *errbuf);
+static int     procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
+    struct shmstat *shm, char *errbuf);
 static int     procstat_get_socket_info_sysctl(struct filestat *fst,
     struct sockstat *sock, char *errbuf);
 static int     procstat_get_socket_info_kvm(kvm_t *kd, struct filestat *fst,
@@ -469,6 +474,10 @@ procstat_getfiles_kvm(struct procstat *p
                        data = file.f_data;
                        break;
 #endif
+               case DTYPE_SHM:
+                       type = PS_FST_TYPE_SHM;
+                       data = file.f_data;
+                       break;
                default:
                        continue;
                }
@@ -849,6 +858,69 @@ procstat_get_pts_info_sysctl(struct file
 }
 
 int
+procstat_get_shm_info(struct procstat *procstat, struct filestat *fst,
+    struct shmstat *shm, char *errbuf)
+{
+
+       assert(shm);
+       if (procstat->type == PROCSTAT_KVM) {
+               return (procstat_get_shm_info_kvm(procstat->kd, fst, shm,
+                   errbuf));
+       } else if (procstat->type == PROCSTAT_SYSCTL) {
+               return (procstat_get_shm_info_sysctl(fst, shm, errbuf));
+       } else {
+               warnx("unknown access method: %d", procstat->type);
+               snprintf(errbuf, _POSIX2_LINE_MAX, "error");
+               return (1);
+       }
+}
+
+static int
+procstat_get_shm_info_kvm(kvm_t *kd, struct filestat *fst,
+    struct shmstat *shm, char *errbuf)
+{
+       struct shmfd shmfd;
+       void *shmfdp;
+
+       assert(kd);
+       assert(shm);
+       assert(fst);
+       bzero(shm, sizeof(*shm));
+       shmfdp = fst->fs_typedep;
+       if (shmfdp == NULL)
+               goto fail;
+       if (!kvm_read_all(kd, (unsigned long)shmfdp, &shmfd,
+           sizeof(struct shmfd))) {
+               warnx("can't read shmfd at %p", (void *)shmfdp);
+               goto fail;
+       }
+       shm->mode = S_IFREG | shmfd.shm_mode;
+       shm->size = shmfd.shm_size;
+       return (0);
+
+fail:
+       snprintf(errbuf, _POSIX2_LINE_MAX, "error");
+       return (1);
+}
+
+static int
+procstat_get_shm_info_sysctl(struct filestat *fst, struct shmstat *shm,
+    char *errbuf __unused)
+{
+       struct kinfo_file *kif;
+
+       assert(shm);
+       assert(fst);
+       bzero(shm, sizeof(*shm));
+       kif = fst->fs_typedep;
+       if (kif == NULL)
+               return (0);
+       shm->size = kif->kf_un.kf_file.kf_file_size;
+       shm->mode = kif->kf_un.kf_file.kf_file_mode;
+       return (0);
+}
+
+int
 procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,
     struct vnstat *vn, char *errbuf)
 {

Modified: head/lib/libprocstat/libprocstat.h
==============================================================================
--- head/lib/libprocstat/libprocstat.h  Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/lib/libprocstat/libprocstat.h  Sun Apr  1 18:22:48 2012        
(r233760)
@@ -123,6 +123,10 @@ struct pipestat {
        uint64_t        addr;
        uint64_t        peer;
 };
+struct shmstat {
+       uint64_t        size;
+       uint16_t        mode;
+};
 struct sockstat {
        uint64_t        inp_ppcb;
        uint64_t        so_addr;
@@ -152,6 +156,8 @@ int procstat_get_pipe_info(struct procst
     struct pipestat *pipe, char *errbuf);
 int    procstat_get_pts_info(struct procstat *procstat, struct filestat *fst,
     struct ptsstat *pts, 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,
     struct sockstat *sock, char *errbuf);
 int    procstat_get_vnode_info(struct procstat *procstat, struct filestat *fst,

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c        Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/sys/kern/kern_descrip.c        Sun Apr  1 18:22:48 2012        
(r233760)
@@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
+#include <sys/mman.h>
 #include <sys/mount.h>
 #include <sys/mqueue.h>
 #include <sys/mutex.h>
@@ -126,6 +127,7 @@ static int  fill_pts_info(struct tty *tp,
 static int     fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
 static int     fill_procdesc_info(struct procdesc *pdp,
     struct kinfo_file *kif);
+static int     fill_shm_info(struct file *fp, struct kinfo_file *kif);
 
 /*
  * A process is initially started out with NDFILE descriptors stored within
@@ -2958,6 +2960,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
        struct kinfo_ofile *kif;
        struct filedesc *fdp;
        int error, i, *name;
+       struct shmfd *shmfd;
        struct socket *so;
        struct vnode *vp;
        struct file *fp;
@@ -2995,6 +2998,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
                vp = NULL;
                so = NULL;
                tp = NULL;
+               shmfd = NULL;
                kif->kf_fd = i;
 
 #ifdef CAPABILITIES
@@ -3046,6 +3050,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
 
                case DTYPE_SHM:
                        kif->kf_type = KF_TYPE_SHM;
+                       shmfd = fp->f_data;
                        break;
 
                case DTYPE_SEM:
@@ -3159,6 +3164,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
                        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;
@@ -3229,6 +3236,9 @@ export_fd_for_sysctl(void *data, int typ
        case KF_TYPE_PROCDESC:
                error = fill_procdesc_info((struct procdesc *)data, kif);
                break;
+       case KF_TYPE_SHM:
+               error = fill_shm_info((struct file *)data, kif);
+               break;
        default:
                error = 0;
        }
@@ -3398,6 +3408,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 
                case DTYPE_SHM:
                        type = KF_TYPE_SHM;
+                       data = fp;
                        break;
 
                case DTYPE_SEM:
@@ -3621,6 +3632,23 @@ fill_procdesc_info(struct procdesc *pdp,
        return (0);
 }
 
+static int
+fill_shm_info(struct file *fp, struct kinfo_file *kif)
+{
+       struct thread *td;
+       struct stat sb;
+
+       td = curthread;
+       if (fp->f_data == NULL)
+               return (1);
+       if (fo_stat(fp, &sb, td->td_ucred, td) != 0)
+               return (1);
+       shm_path(fp->f_data, kif->kf_path, sizeof(kif->kf_path));
+       kif->kf_un.kf_file.kf_file_mode = sb.st_mode;
+       kif->kf_un.kf_file.kf_file_size = sb.st_size;
+       return (0);
+}
+
 static SYSCTL_NODE(_kern_proc, KERN_PROC_FILEDESC, filedesc, CTLFLAG_RD,
     sysctl_kern_proc_filedesc, "Process filedesc entries");
 

Modified: head/sys/kern/uipc_shm.c
==============================================================================
--- head/sys/kern/uipc_shm.c    Sun Apr  1 15:05:15 2012        (r233759)
+++ head/sys/kern/uipc_shm.c    Sun Apr  1 18:22:48 2012        (r233760)
@@ -468,6 +468,7 @@ shm_insert(char *path, Fnv32_t fnv, stru
        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);
 }
 
@@ -490,6 +491,7 @@ shm_remove(char *path, Fnv32_t fnv, stru
                            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);
@@ -844,3 +846,15 @@ shm_unmap(struct file *fp, void *mem, si
        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);
+}

Modified: head/sys/sys/mman.h
==============================================================================
--- head/sys/sys/mman.h Sun Apr  1 15:05:15 2012        (r233759)
+++ head/sys/sys/mman.h Sun Apr  1 18:22:48 2012        (r233760)
@@ -178,7 +178,7 @@ typedef     __size_t        size_t;
 #define        _SIZE_T_DECLARED
 #endif
 
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_WANT_FILE)
 #include <vm/vm.h>
 
 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 */
 

Modified: head/usr.bin/fstat/fstat.c
==============================================================================
--- head/usr.bin/fstat/fstat.c  Sun Apr  1 15:05:15 2012        (r233759)
+++ head/usr.bin/fstat/fstat.c  Sun Apr  1 18:22:48 2012        (r233760)
@@ -84,6 +84,8 @@ static void   print_pipe_info(struct procs
     struct filestat *fst);
 static void    print_pts_info(struct procstat *procstat,
     struct filestat *fst);
+static void    print_shm_info(struct procstat *procstat,
+    struct filestat *fst);
 static void    print_socket_info(struct procstat *procstat,
     struct filestat *fst);
 static void    print_vnode_info(struct procstat *procstat,
@@ -289,6 +291,9 @@ print_file_info(struct procstat *procsta
        case PS_FST_TYPE_PTS:
                print_pts_info(procstat, fst);
                break;
+       case PS_FST_TYPE_SHM:
+               print_shm_info(procstat, fst);
+               break;
        default:        
                if (vflg)
                        fprintf(stderr,
@@ -419,6 +424,30 @@ print_pts_info(struct procstat *procstat
 }
 
 static void
+print_shm_info(struct procstat *procstat, struct filestat *fst)
+{
+       struct shmstat shm;
+       char errbuf[_POSIX2_LINE_MAX];
+       char mode[15];
+       int error;
+
+       error = procstat_get_shm_info(procstat, fst, &shm, errbuf);
+       if (error != 0) {
+               printf("* error");
+               return;
+       }
+       if (nflg) {
+               printf("             ");
+               (void)snprintf(mode, sizeof(mode), "%o", shm.mode);
+       } else {
+               printf(" %-15s", fst->fs_path != NULL ? fst->fs_path : "-");
+               strmode(shm.mode, mode);
+       }
+       printf(" %10s %6ju", mode, shm.size);
+       print_access_flags(fst->fs_fflags);
+}
+
+static void
 print_vnode_info(struct procstat *procstat, struct filestat *fst)
 {
        struct vnstat vn;

Modified: head/usr.bin/procstat/procstat_files.c
==============================================================================
--- head/usr.bin/procstat/procstat_files.c      Sun Apr  1 15:05:15 2012        
(r233759)
+++ head/usr.bin/procstat/procstat_files.c      Sun Apr  1 18:22:48 2012        
(r233760)
@@ -440,13 +440,6 @@ procstat_files(struct procstat *procstat
                        printf(" ");
                }
                switch (fst->fs_type) {
-               case PS_FST_TYPE_VNODE:
-               case PS_FST_TYPE_FIFO:
-               case PS_FST_TYPE_PTS:
-                       printf("%-3s ", "-");
-                       printf("%-18s", fst->fs_path != NULL ? fst->fs_path : 
"-");
-                       break;
-
                case PS_FST_TYPE_SOCKET:
                        error = procstat_get_socket_info(procstat, fst, &sock, 
NULL);
                        if (error != 0)
@@ -477,7 +470,8 @@ procstat_files(struct procstat *procstat
                        break;
 
                default:
-                       printf("%-18s", "-");
+                       printf("%-3s ", "-");
+                       printf("%-18s", fst->fs_path != NULL ? fst->fs_path : 
"-");
                }
 
                printf("\n");
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to