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
This commit is contained in:
parent
d5bc632dfb
commit
506e2f15b9
@ -14,3 +14,7 @@ FBSD_1.2 {
|
||||
procstat_open_kvm;
|
||||
procstat_open_sysctl;
|
||||
};
|
||||
|
||||
FBSD_1.3 {
|
||||
procstat_get_shm_info;
|
||||
};
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 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_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 ,
|
||||
|
@ -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 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_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 *procstat, struct kinfo_proc *kp, int mmap
|
||||
data = file.f_data;
|
||||
break;
|
||||
#endif
|
||||
case DTYPE_SHM:
|
||||
type = PS_FST_TYPE_SHM;
|
||||
data = file.f_data;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
@ -848,6 +857,69 @@ procstat_get_pts_info_sysctl(struct filestat *fst, struct ptsstat *pts,
|
||||
return (0);
|
||||
}
|
||||
|
||||
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)
|
||||
|
@ -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 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_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,
|
||||
|
@ -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, struct kinfo_file *kif);
|
||||
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_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;
|
||||
@ -2995,6 +2998,7 @@ sysctl_kern_proc_ofiledesc(SYSCTL_HANDLER_ARGS)
|
||||
vp = NULL;
|
||||
so = NULL;
|
||||
tp = NULL;
|
||||
shmfd = NULL;
|
||||
kif->kf_fd = i;
|
||||
|
||||
#ifdef CAPABILITIES
|
||||
@ -3046,6 +3050,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:
|
||||
@ -3159,6 +3164,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;
|
||||
@ -3229,6 +3236,9 @@ export_fd_for_sysctl(void *data, int type, int fd, int fflags, int refcnt,
|
||||
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_ARGS)
|
||||
|
||||
case DTYPE_SHM:
|
||||
type = KF_TYPE_SHM;
|
||||
data = fp;
|
||||
break;
|
||||
|
||||
case DTYPE_SEM:
|
||||
@ -3621,6 +3632,23 @@ fill_procdesc_info(struct procdesc *pdp, struct kinfo_file *kif)
|
||||
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");
|
||||
|
||||
|
@ -468,6 +468,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);
|
||||
}
|
||||
|
||||
@ -490,6 +491,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);
|
||||
@ -844,3 +846,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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -84,6 +84,8 @@ static void print_pipe_info(struct procstat *procstat,
|
||||
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 *procstat, struct filestat *fst,
|
||||
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,
|
||||
@ -418,6 +423,30 @@ print_pts_info(struct procstat *procstat, struct filestat *fst)
|
||||
print_access_flags(fst->fs_fflags);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -440,13 +440,6 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
|
||||
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, struct kinfo_proc *kipp)
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%-18s", "-");
|
||||
printf("%-3s ", "-");
|
||||
printf("%-18s", fst->fs_path != NULL ? fst->fs_path : "-");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
Loading…
Reference in New Issue
Block a user