summaryrefslogtreecommitdiff
path: root/usr/src/lib/libproc/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libproc/common')
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.c8
-rw-r--r--usr/src/lib/libproc/common/Pcontrol.h12
-rw-r--r--usr/src/lib/libproc/common/Pcore.c24
-rw-r--r--usr/src/lib/libproc/common/Pfdinfo.c168
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c28
-rw-r--r--usr/src/lib/libproc/common/libproc.h7
-rw-r--r--usr/src/lib/libproc/common/mapfile-vers2
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;