Author: jhb
Date: Mon Jun 24 17:09:28 2013
New Revision: 252164
URL: http://svnweb.freebsd.org/changeset/base/252164

Log:
  MFC 250223:
  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 ksem_info() to export the path of a semaphore via struct kinfo_file.
  - Teach fstat about semaphores and to display their path, mode, and value.

Modified:
  stable/8/sys/kern/kern_descrip.c
  stable/8/sys/kern/uipc_sem.c
  stable/8/sys/sys/ksem.h
  stable/8/usr.bin/fstat/fstat.1
  stable/8/usr.bin/fstat/fstat.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/kern/   (props changed)
  stable/8/sys/sys/   (props changed)
  stable/8/usr.bin/fstat/   (props changed)

Modified: stable/8/sys/kern/kern_descrip.c
==============================================================================
--- stable/8/sys/kern/kern_descrip.c    Mon Jun 24 16:04:59 2013        
(r252163)
+++ stable/8/sys/kern/kern_descrip.c    Mon Jun 24 17:09:28 2013        
(r252164)
@@ -52,6 +52,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/filio.h>
 #include <sys/jail.h>
 #include <sys/kernel.h>
+#include <sys/ksem.h>
 #include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/malloc.h>
@@ -96,6 +97,7 @@ MALLOC_DECLARE(M_FADVISE);
 
 static uma_zone_t file_zone;
 
+void   (*ksem_info)(struct ksem *ks, char *path, size_t size, uint32_t *value);
 
 /* Flags for do_dup() */
 #define DUP_FIXED      0x1     /* Force fixed allocation */
@@ -2764,6 +2766,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
        struct shmfd *shmfd;
        struct socket *so;
        struct vnode *vp;
+       struct ksem *ks;
        struct file *fp;
        struct proc *p;
        struct tty *tp;
@@ -2796,6 +2799,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
                        continue;
                bzero(kif, sizeof(*kif));
                kif->kf_structsize = sizeof(*kif);
+               ks = NULL;
                vp = NULL;
                so = NULL;
                tp = NULL;
@@ -2840,6 +2844,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
 
                case DTYPE_SEM:
                        kif->kf_type = KF_TYPE_SEM;
+                       ks = fp->f_data;
                        break;
 
                case DTYPE_PTS:
@@ -2945,6 +2950,8 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLE
                }
                if (shmfd != NULL)
                        shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path));
+               if (ks != NULL && ksem_info != NULL)
+                       ksem_info(ks, kif->kf_path, sizeof(kif->kf_path), NULL);
                error = SYSCTL_OUT(req, kif, sizeof(*kif));
                if (error)
                        break;
@@ -3022,6 +3029,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
        struct shmfd *shmfd;
        struct socket *so;
        struct vnode *vp;
+       struct ksem *ks;
        struct file *fp;
        struct proc *p;
        struct tty *tp;
@@ -3054,6 +3062,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
                if ((fp = fdp->fd_ofiles[i]) == NULL)
                        continue;
                bzero(kif, sizeof(*kif));
+               ks = NULL;
                vp = NULL;
                so = NULL;
                tp = NULL;
@@ -3098,6 +3107,7 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
 
                case DTYPE_SEM:
                        kif->kf_type = KF_TYPE_SEM;
+                       ks = fp->f_data;
                        break;
 
                case DTYPE_PTS:
@@ -3203,6 +3213,8 @@ sysctl_kern_proc_filedesc(SYSCTL_HANDLER
                }
                if (shmfd != NULL)
                        shm_path(shmfd, kif->kf_path, sizeof(kif->kf_path));
+               if (ks != NULL && ksem_info != NULL)
+                       ksem_info(ks, kif->kf_path, sizeof(kif->kf_path), NULL);
                /* Pack record size down */
                kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
                    strlen(kif->kf_path) + 1;

Modified: stable/8/sys/kern/uipc_sem.c
==============================================================================
--- stable/8/sys/kern/uipc_sem.c        Mon Jun 24 16:04:59 2013        
(r252163)
+++ stable/8/sys/kern/uipc_sem.c        Mon Jun 24 17:09:28 2013        
(r252164)
@@ -344,6 +344,7 @@ ksem_insert(char *path, Fnv32_t fnv, str
        map->km_path = path;
        map->km_fnv = fnv;
        map->km_ksem = ksem_hold(ks);
+       ks->ks_path = path;
        LIST_INSERT_HEAD(KSEM_HASH(fnv), map, km_link);
 }
 
@@ -365,6 +366,7 @@ ksem_remove(char *path, Fnv32_t fnv, str
                        error = ksem_access(map->km_ksem, ucred);
                        if (error)
                                return (error);
+                       map->km_ksem->ks_path = NULL;
                        LIST_REMOVE(map, km_link);
                        ksem_drop(map->km_ksem);
                        free(map->km_path, M_KSEM);
@@ -376,6 +378,20 @@ ksem_remove(char *path, Fnv32_t fnv, str
        return (ENOENT);
 }
 
+static void
+ksem_info_impl(struct ksem *ks, char *path, size_t size, uint32_t *value)
+{
+
+       if (ks->ks_path == NULL)
+               return;
+       sx_slock(&ksem_dict_lock);
+       if (ks->ks_path != NULL)
+               strlcpy(path, ks->ks_path, size);
+       if (value != NULL)
+               *value = ks->ks_value;
+       sx_sunlock(&ksem_dict_lock);
+}
+
 static int
 ksem_create_copyout_semid(struct thread *td, semid_t *semidp, int fd,
     int compat32)
@@ -953,6 +969,7 @@ ksem_module_init(void)
        p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 200112L);
        p31b_setcfg(CTL_P1003_1B_SEM_NSEMS_MAX, SEM_MAX);
        p31b_setcfg(CTL_P1003_1B_SEM_VALUE_MAX, SEM_VALUE_MAX);
+       ksem_info = ksem_info_impl;
 
        error = syscall_helper_register(ksem_syscalls);
        if (error)
@@ -974,6 +991,7 @@ ksem_module_destroy(void)
 #endif
        syscall_helper_unregister(ksem_syscalls);
 
+       ksem_info = NULL;
        p31b_setcfg(CTL_P1003_1B_SEMAPHORES, 0);
        hashdestroy(ksem_dictionary, M_KSEM, ksem_hash);
        sx_destroy(&ksem_dict_lock);

Modified: stable/8/sys/sys/ksem.h
==============================================================================
--- stable/8/sys/sys/ksem.h     Mon Jun 24 16:04:59 2013        (r252163)
+++ stable/8/sys/sys/ksem.h     Mon Jun 24 17:09:28 2013        (r252164)
@@ -29,7 +29,7 @@
 #ifndef _POSIX4_KSEM_H_
 #define        _POSIX4_KSEM_H_
 
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_WANT_FILE)
 #error "no user-servicable parts inside"
 #endif
 
@@ -57,9 +57,15 @@ struct ksem {
        struct timespec ks_birthtime;
 
        struct label    *ks_label;      /* MAC label */
+       const char      *ks_path;
 };
 
 #define        KS_ANONYMOUS    0x0001          /* Anonymous (unnamed) 
semaphore. */
 #define        KS_DEAD         0x0002          /* No new waiters allowed. */
 
+#ifdef _KERNEL
+extern void    (*ksem_info)(struct ksem *ks, char *path, size_t size,
+                   uint32_t *value);
+#endif
+
 #endif /* !_POSIX4_KSEM_H_ */

Modified: stable/8/usr.bin/fstat/fstat.1
==============================================================================
--- stable/8/usr.bin/fstat/fstat.1      Mon Jun 24 16:04:59 2013        
(r252163)
+++ stable/8/usr.bin/fstat/fstat.1      Mon Jun 24 17:09:28 2013        
(r252164)
@@ -159,6 +159,8 @@ using a symbolic format (see
 otherwise, the mode is printed
 as an octal number.
 .It Li SZ\&|DV
+If the file is a semaphore,
+prints the current value of the semaphore.
 If the file is not a character or block special, prints the size of
 the file in bytes.
 Otherwise, if the

Modified: stable/8/usr.bin/fstat/fstat.c
==============================================================================
--- stable/8/usr.bin/fstat/fstat.c      Mon Jun 24 16:04:59 2013        
(r252163)
+++ stable/8/usr.bin/fstat/fstat.c      Mon Jun 24 17:09:28 2013        
(r252164)
@@ -64,6 +64,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/pipe.h>
@@ -156,6 +157,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 semtrans(struct ksem *ksemp, int i, int flag);
 void shmtrans(struct shmfd *shmp, int i, int flag);
 void getinetproto(int number);
 int  getfname(const char *filename);
@@ -426,6 +428,12 @@ dofiles(struct kinfo_proc *kp)
                                shmtrans(file.f_data, i, file.f_flag);
                }
 #endif
+#ifdef DTYPE_SEM
+               else if (file.f_type == DTYPE_SEM) {
+                       if (checkfile == 0)
+                               semtrans(file.f_data, i, file.f_flag);
+               }
+#endif
                else {
                        dprintf(stderr,
                            "unknown file type %d for file %d of pid %d\n",
@@ -948,6 +956,55 @@ bad:
 }
 
 void
+semtrans(struct ksem *ksemp, int i, int flag)
+{
+       struct ksem ks;
+       char name[MAXPATHLEN];
+       char mode[15];
+       char rw[3];
+       unsigned j;
+
+       PREFIX(i);
+
+       if (!KVM_READ(ksemp, &ks, sizeof(struct ksem))) {
+               dprintf(stderr, "can't read sem at %p\n", ksemp);
+               goto bad;
+       }
+
+       if (ks.ks_path != NULL) {
+               for (j = 0; j < sizeof(name) - 1; j++) {
+                       if (!KVM_READ(ks.ks_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");
+
+       ks.ks_mode |= S_IFREG;
+       if (nflg) {
+               printf("             ");
+               (void)snprintf(mode, sizeof(mode), "%o", ks.ks_mode);
+       } else {
+               printf(" %-15s", name[0] != '\0' ? name : "-");
+               strmode(ks.ks_mode, mode);
+       }
+       printf(" %10s %6u", mode, ks.ks_value);
+       printf(" %2s\n", rw);
+
+       return;
+bad:
+       printf("* error\n");
+}
+
+void
 shmtrans(struct shmfd *shmp, int i, int flag)
 {
        struct shmfd shm;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to