Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Apr 2012 18:22:49 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233760 - in head: lib/libprocstat sys/kern sys/sys usr.bin/fstat usr.bin/procstat
Message-ID:  <201204011822.q31IMnVN060925@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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");



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204011822.q31IMnVN060925>