diff options
Diffstat (limited to 'usr/src/lib/libproc/common')
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.c | 8 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcontrol.h | 12 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pcore.c | 24 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pfdinfo.c | 168 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/Pgcore.c | 28 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/libproc.h | 7 | ||||
-rw-r--r-- | usr/src/lib/libproc/common/mapfile-vers | 2 |
7 files changed, 249 insertions, 0 deletions
diff --git a/usr/src/lib/libproc/common/Pcontrol.c b/usr/src/lib/libproc/common/Pcontrol.c index 2a32522e0c..1e7ce1556e 100644 --- a/usr/src/lib/libproc/common/Pcontrol.c +++ b/usr/src/lib/libproc/common/Pcontrol.c @@ -24,6 +24,7 @@ * Use is subject to license terms. * * Portions Copyright 2007 Chad Mynhier + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ #include <assert.h> @@ -986,6 +987,13 @@ Pfree(struct ps_prochandle *P) } free(P->hashtab); } + + while (P->num_fd > 0) { + fd_info_t *fip = list_next(&P->fd_head); + list_unlink(fip); + free(fip); + P->num_fd--; + } (void) mutex_unlock(&P->proc_lock); (void) mutex_destroy(&P->proc_lock); diff --git a/usr/src/lib/libproc/common/Pcontrol.h b/usr/src/lib/libproc/common/Pcontrol.h index 192038b9b6..4774093b6d 100644 --- a/usr/src/lib/libproc/common/Pcontrol.h +++ b/usr/src/lib/libproc/common/Pcontrol.h @@ -22,6 +22,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #ifndef _PCONTROL_H #define _PCONTROL_H @@ -136,6 +139,11 @@ typedef struct lwp_info { /* per-lwp information from core file */ #endif } lwp_info_t; +typedef struct fd_info { + plist_t fd_list; /* linked list */ + prfdinfo_t fd_info; /* fd info */ +} fd_info_t; + typedef struct core_info { /* information specific to core files */ char core_dmodel; /* data model for core file */ int core_errno; /* error during initialization if != 0 */ @@ -223,6 +231,8 @@ struct ps_prochandle { uintptr_t *ucaddrs; /* ucontext-list addresses */ uint_t ucnelems; /* number of elements in the ucaddrs list */ char *zoneroot; /* cached path to zone root */ + plist_t fd_head; /* head of file desc info list */ + int num_fd; /* number of file descs in list */ }; /* flags */ @@ -269,6 +279,8 @@ extern char *Plofspath(const char *, char *, size_t); extern char *Pzoneroot(struct ps_prochandle *, char *, size_t); extern char *Pzonepath(struct ps_prochandle *, const char *, char *, size_t); +extern fd_info_t *Pfd2info(struct ps_prochandle *, int); + extern char *Pfindmap(struct ps_prochandle *, map_info_t *, char *, size_t); diff --git a/usr/src/lib/libproc/common/Pcore.c b/usr/src/lib/libproc/common/Pcore.c index de868725db..3e0350eb04 100644 --- a/usr/src/lib/libproc/common/Pcore.c +++ b/usr/src/lib/libproc/common/Pcore.c @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include <sys/types.h> #include <sys/utsname.h> @@ -300,6 +303,26 @@ err: } static int +note_fdinfo(struct ps_prochandle *P, size_t nbytes) +{ + prfdinfo_t prfd; + fd_info_t *fip; + + if ((nbytes < sizeof (prfd)) || + (read(P->asfd, &prfd, sizeof (prfd)) != sizeof (prfd))) { + dprintf("Pgrab_core: failed to read NT_FDINFO\n"); + return (-1); + } + + if ((fip = Pfd2info(P, prfd.pr_fd)) == NULL) { + dprintf("Pgrab_core: failed to add NT_FDINFO\n"); + return (-1); + } + (void) memcpy(&fip->fd_info, &prfd, sizeof (prfd)); + return (0); +} + +static int note_platform(struct ps_prochandle *P, size_t nbytes) { char *plat; @@ -701,6 +724,7 @@ static int (*nhdlrs[])(struct ps_prochandle *, size_t) = { note_priv_info, /* 19 NT_PRPRIVINFO */ note_content, /* 20 NT_CONTENT */ note_zonename, /* 21 NT_ZONENAME */ + note_fdinfo, /* 22 NT_FDINFO */ }; /* diff --git a/usr/src/lib/libproc/common/Pfdinfo.c b/usr/src/lib/libproc/common/Pfdinfo.c new file mode 100644 index 0000000000..0d41b5606d --- /dev/null +++ b/usr/src/lib/libproc/common/Pfdinfo.c @@ -0,0 +1,168 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ + +#include <limits.h> +#include <stdio.h> +#include <errno.h> +#include <unistd.h> +#include <dirent.h> +#include <ctype.h> +#include <string.h> +#include <sys/mkdev.h> + +#include "libproc.h" +#include "Pcontrol.h" + +/* + * Pfdinfo.c - obtain open file information. + */ + +/* + * Allocate an fd_info structure and stick it on the list. + * (Unless one already exists.) The list is sorted in + * reverse order. We will traverse it in that order later. + * This makes the usual ordered insert *fast*. + */ +fd_info_t * +Pfd2info(struct ps_prochandle *P, int fd) +{ + fd_info_t *fip = list_next(&P->fd_head); + fd_info_t *next; + int i; + + if (fip == NULL) { + list_link(&P->fd_head, NULL); + fip = list_next(&P->fd_head); + } + + for (i = 0; i < P->num_fd; i++, fip = list_next(fip)) { + if (fip->fd_info.pr_fd == fd) { + return (fip); + } + if (fip->fd_info.pr_fd < fd) { + break; + } + } + + next = fip; + if ((fip = calloc(1, sizeof (*fip))) == NULL) + return (NULL); + + fip->fd_info.pr_fd = fd; + list_link(fip, next ? next : (void *)&(P->fd_head)); + P->num_fd++; + return (fip); +} + +/* + * Attempt to load the open file information from a live process. + */ +static void +load_fdinfo(struct ps_prochandle *P) +{ + /* + * In the unlikely case there are *no* file descriptors open, + * we will keep rescanning the proc directory, which will be empty. + * This is an edge case it isn't worth adding additional state to + * to eliminate. + */ + if (P->num_fd > 0) { + return; + } + + if (P->state != PS_DEAD && P->state != PS_IDLE) { + char dir_name[PATH_MAX]; + char path[PATH_MAX]; + struct dirent *ent; + DIR *dirp; + int fd; + + /* + * Try to get the path information first. + */ + (void) snprintf(dir_name, sizeof (dir_name), + "%s/%d/path", procfs_path, (int)P->pid); + dirp = opendir(dir_name); + if (dirp == NULL) { + return; + } + ent = NULL; + while ((ent = readdir(dirp)) != NULL) { + fd_info_t *fip; + prfdinfo_t *info; + int len; + struct stat64 stat; + + if (!isdigit(ent->d_name[0])) + continue; + + fd = atoi(ent->d_name); + + fip = Pfd2info(P, fd); + info = &fip->fd_info; + info->pr_fd = fd; + + if (pr_fstat64(P, fd, &stat) == 0) { + info->pr_mode = stat.st_mode; + info->pr_uid = stat.st_uid; + info->pr_gid = stat.st_gid; + info->pr_major = major(stat.st_dev); + info->pr_minor = minor(stat.st_dev); + info->pr_rmajor = major(stat.st_rdev); + info->pr_rminor = minor(stat.st_rdev); + info->pr_size = stat.st_size; + info->pr_ino = stat.st_ino; + } + + info->pr_fileflags = pr_fcntl(P, fd, F_GETXFL, 0); + info->pr_fdflags = pr_fcntl(P, fd, F_GETFD, 0); + info->pr_offset = pr_llseek(P, fd, 0, SEEK_CUR); + + /* attempt to determine the path to it */ + (void) snprintf(path, sizeof (path), + "%s/%d/path/%d", procfs_path, (int)P->pid, fd); + len = readlink(path, info->pr_path, + sizeof (info->pr_path) - 1); + + if (len < 0) { + info->pr_path[0] = 0; + } else { + info->pr_path[len] = 0; + } + } + (void) closedir(dirp); + + } +} + +int +Pfdinfo_iter(struct ps_prochandle *P, proc_fdinfo_f *func, void *cd) +{ + fd_info_t *fip; + int rv; + + /* Make sure we have live data, if appropriate */ + load_fdinfo(P); + + /* NB: We walk the list backwards. */ + + for (fip = list_prev(&P->fd_head); + fip != (void *)&P->fd_head; + fip = list_prev(fip)) { + if ((rv = func(cd, &fip->fd_info)) != 0) + return (rv); + } + return (0); +} diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c index 590c55142a..f409e96259 100644 --- a/usr/src/lib/libproc/common/Pgcore.c +++ b/usr/src/lib/libproc/common/Pgcore.c @@ -23,6 +23,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #define _STRUCTURED_PROC 1 @@ -84,6 +87,11 @@ typedef struct { shstrtab_t pgc_shstrtab; } pgcore_t; +typedef struct { + int fd_fd; + off64_t *fd_doff; +} fditer_t; + static void shstrtab_init(shstrtab_t *s) { @@ -543,6 +551,17 @@ new_per_lwp(void *data, const lwpstatus_t *lsp, const lwpsinfo_t *lip) return (0); } +static int +iter_fd(void *data, prfdinfo_t *fdinfo) +{ + fditer_t *iter = data; + + if (write_note(iter->fd_fd, NT_FDINFO, fdinfo, + sizeof (*fdinfo), iter->fd_doff) != 0) + return (1); + return (0); +} + static uint_t count_sections(pgcore_t *pgc) { @@ -1341,6 +1360,15 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content) &doff) != 0) goto err; + { + fditer_t iter; + iter.fd_fd = fd; + iter.fd_doff = &doff; + + if (Pfdinfo_iter(P, iter_fd, &iter) != 0) + goto err; + } + #if defined(__i386) || defined(__amd64) /* CSTYLED */ { diff --git a/usr/src/lib/libproc/common/libproc.h b/usr/src/lib/libproc/common/libproc.h index b4374324a1..1e59b5089f 100644 --- a/usr/src/lib/libproc/common/libproc.h +++ b/usr/src/lib/libproc/common/libproc.h @@ -24,6 +24,7 @@ * Use is subject to license terms. * * Portions Copyright 2007 Chad Mynhier + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ /* @@ -713,6 +714,12 @@ extern int proc_initstdio(void); extern int proc_flushstdio(void); extern int proc_finistdio(void); +/* + * Iterate over all open files. + */ +typedef int proc_fdinfo_f(void *, prfdinfo_t *); +extern int Pfdinfo_iter(struct ps_prochandle *, proc_fdinfo_f *, void *); + #ifdef __cplusplus } #endif diff --git a/usr/src/lib/libproc/common/mapfile-vers b/usr/src/lib/libproc/common/mapfile-vers index c3e2eb2e8a..9482a53145 100644 --- a/usr/src/lib/libproc/common/mapfile-vers +++ b/usr/src/lib/libproc/common/mapfile-vers @@ -20,6 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012 DEY Storage Systems, Inc. All rights reserved. # # @@ -298,6 +299,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { Pzonename; Pzonepath; Pzoneroot; + Pfdinfo_iter; $if _x86 && _ELF32 Pldt; |