# HG changeset patch # User Garrett D'Amore # Date 1351874922 25200 # Node ID f128a109e6d2586834b71be90b6fb0918d9703c4 # Parent cab67b95c26b3d61f5aaf5937b14152271d37794 3294 pfiles postmortem support Reviewed by: Robert Mustacchi Reviewed by: Richard Lowe Approved by: Eric Schrock diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/ptools/pfiles/pfiles.c --- a/usr/src/cmd/ptools/pfiles/pfiles.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/ptools/pfiles/pfiles.c Fri Nov 02 09:48:42 2012 -0700 @@ -21,6 +21,7 @@ /* * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ #include @@ -61,7 +62,7 @@ static boolean_t nflag = B_FALSE; static void intr(int); -static void dofcntl(struct ps_prochandle *, int, int, int); +static void dofcntl(struct ps_prochandle *, prfdinfo_t *, int, int); static void dosocket(struct ps_prochandle *, int); static void dofifo(struct ps_prochandle *, int); static void dotli(struct ps_prochandle *, int); @@ -102,7 +103,7 @@ argv += optind; if (errflg || argc <= 0) { - (void) fprintf(stderr, "usage:\t%s [-F] pid ...\n", + (void) fprintf(stderr, "usage:\t%s [-F] { pid | core } ...\n", command); (void) fprintf(stderr, " (report open files of each process)\n"); @@ -132,12 +133,35 @@ (void) proc_flushstdio(); + arg = *argv++; + /* get the specified pid and the psinfo struct */ - if ((pid = proc_arg_psinfo(arg = *argv++, PR_ARG_PIDS, + if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gret)) == -1) { - (void) fprintf(stderr, "%s: cannot examine %s: %s\n", - command, arg, Pgrab_error(gret)); - retc++; + + if ((Pr = proc_arg_xgrab(arg, NULL, PR_ARG_CORES, + Fflag, &gret, NULL)) == NULL) { + (void) fprintf(stderr, + "%s: cannot examine %s: %s\n", + command, arg, Pgrab_error(gret)); + retc++; + continue; + } + if (proc_arg_psinfo(arg, PR_ARG_ANY, &psinfo, + &gret) < 0) { + (void) fprintf(stderr, + "%s: cannot examine %s: %s\n", + command, arg, Pgrab_error(gret)); + retc++; + Prelease(Pr, 0); + continue; + } + (void) printf("core '%s' of %d:\t%.70s\n", + arg, (int)psinfo.pr_pid, psinfo.pr_psargs); + + show_files(Pr); + Prelease(Pr, 0); + } else if ((Pr = Pgrab(pid, Fflag, &gret)) != NULL) { if (Pcreate_agent(Pr) == 0) { proc_unctrl_psinfo(&psinfo); @@ -190,20 +214,109 @@ /* ------ begin specific code ------ */ +static int +show_file(void *data, prfdinfo_t *info) +{ + struct ps_prochandle *Pr = data; + char unknown[12]; + char *s; + mode_t mode; + + if (interrupt) + return (1); + + mode = info->pr_mode; + + switch (mode & S_IFMT) { + case S_IFCHR: s = "S_IFCHR"; break; + case S_IFBLK: s = "S_IFBLK"; break; + case S_IFIFO: s = "S_IFIFO"; break; + case S_IFDIR: s = "S_IFDIR"; break; + case S_IFREG: s = "S_IFREG"; break; + case S_IFLNK: s = "S_IFLNK"; break; + case S_IFSOCK: s = "S_IFSOCK"; break; + case S_IFDOOR: s = "S_IFDOOR"; break; + case S_IFPORT: s = "S_IFPORT"; break; + default: + s = unknown; + (void) sprintf(s, "0x%.4x ", (int)mode & S_IFMT); + break; + } + + (void) printf("%4d: %s mode:0%.3o", info->pr_fd, s, + (int)mode & ~S_IFMT); + + (void) printf(" dev:%u,%u", + (unsigned)info->pr_major, (unsigned)info->pr_minor); + + if ((mode & S_IFMT) == S_IFPORT) { + (void) printf(" uid:%d gid:%d", + (int)info->pr_uid, (int)info->pr_gid); + (void) printf(" size:%lld\n", (longlong_t)info->pr_size); + return (0); + } + + (void) printf(" ino:%llu uid:%d gid:%d", + (u_longlong_t)info->pr_ino, (int)info->pr_uid, (int)info->pr_gid); + + if ((info->pr_rmajor == (major_t)NODEV) && + (info->pr_rminor == (minor_t)NODEV)) + (void) printf(" size:%lld\n", (longlong_t)info->pr_size); + else + (void) printf(" rdev:%u,%u\n", + (unsigned)info->pr_rmajor, (unsigned)info->pr_rminor); + + if (!nflag) { + dofcntl(Pr, info, + (mode & (S_IFMT|S_ENFMT|S_IXGRP)) == (S_IFREG|S_ENFMT), + (mode & S_IFMT) == S_IFDOOR); + + if (Pstate(Pr) != PS_DEAD) { + char *dev; + + if ((mode & S_IFMT) == S_IFSOCK) + dosocket(Pr, info->pr_fd); + else if ((mode & S_IFMT) == S_IFIFO) + dofifo(Pr, info->pr_fd); + + if ((mode & S_IFMT) == S_IFCHR && + (dev = strrchr(info->pr_path, ':')) != NULL) { + /* + * There's no elegant way to determine + * if a character device supports TLI, + * so we lame out and just check a + * hardcoded list of known TLI devices. + */ + int i; + const char *tlidevs[] = { + "tcp", "tcp6", "udp", "udp6", NULL + }; + + dev++; /* skip past the `:' */ + for (i = 0; tlidevs[i] != NULL; i++) { + if (strcmp(dev, tlidevs[i]) == 0) { + dotli(Pr, info->pr_fd); + break; + } + } + } + } + + if (info->pr_path[0] != '\0') + (void) printf(" %s\n", info->pr_path); + + if (info->pr_offset != -1) { + (void) printf(" offset:%lld\n", + (long long)info->pr_offset); + } + } + return (0); +} + static void show_files(struct ps_prochandle *Pr) { - DIR *dirp; - struct dirent *dentp; - const char *dev; - char pname[100]; - char fname[PATH_MAX]; - struct stat64 statb; struct rlimit rlim; - pid_t pid; - int fd; - char *s; - int ret; if (pr_getrlimit(Pr, RLIMIT_NOFILE, &rlim) == 0) { ulong_t nfd = rlim.rlim_cur; @@ -215,135 +328,7 @@ " Current rlimit: %lu file descriptors\n", nfd); } - /* in case we are doing this to ourself */ - pid = (Pr == NULL)? getpid() : Pstatus(Pr)->pr_pid; - - (void) sprintf(pname, "/proc/%d/fd", (int)pid); - if ((dirp = opendir(pname)) == NULL) { - (void) fprintf(stderr, "%s: cannot open directory %s\n", - command, pname); - return; - } - - /* for each open file --- */ - while ((dentp = readdir(dirp)) != NULL && !interrupt) { - char unknown[12]; - dev_t rdev; - - /* skip '.' and '..' */ - if (!isdigit(dentp->d_name[0])) - continue; - - fd = atoi(dentp->d_name); - if (pr_fstat64(Pr, fd, &statb) == -1) { - s = unknown; - (void) sprintf(s, "%4d", fd); - perror(s); - continue; - } - - rdev = NODEV; - switch (statb.st_mode & S_IFMT) { - case S_IFCHR: s = "S_IFCHR"; rdev = statb.st_rdev; break; - case S_IFBLK: s = "S_IFBLK"; rdev = statb.st_rdev; break; - case S_IFIFO: s = "S_IFIFO"; break; - case S_IFDIR: s = "S_IFDIR"; break; - case S_IFREG: s = "S_IFREG"; break; - case S_IFLNK: s = "S_IFLNK"; break; - case S_IFSOCK: s = "S_IFSOCK"; break; - case S_IFDOOR: s = "S_IFDOOR"; break; - case S_IFPORT: s = "S_IFPORT"; break; - default: - s = unknown; - (void) sprintf(s, "0x%.4x ", - (int)statb.st_mode & S_IFMT); - break; - } - - (void) printf("%4d: %s mode:0%.3o", fd, s, - (int)statb.st_mode & ~S_IFMT); - - if (major(statb.st_dev) != (major_t)NODEV && - minor(statb.st_dev) != (minor_t)NODEV) - (void) printf(" dev:%lu,%lu", - (ulong_t)major(statb.st_dev), - (ulong_t)minor(statb.st_dev)); - else - (void) printf(" dev:0x%.8lX", (long)statb.st_dev); - - if ((statb.st_mode & S_IFMT) == S_IFPORT) { - (void) printf(" uid:%d gid:%d", - (int)statb.st_uid, - (int)statb.st_gid); - (void) printf(" size:%lld\n", - (longlong_t)statb.st_size); - continue; - } - - (void) printf(" ino:%llu uid:%d gid:%d", - (u_longlong_t)statb.st_ino, - (int)statb.st_uid, (int)statb.st_gid); - - if (rdev == NODEV) - (void) printf(" size:%lld\n", - (longlong_t)statb.st_size); - else if (major(rdev) != (major_t)NODEV && - minor(rdev) != (minor_t)NODEV) - (void) printf(" rdev:%lu,%lu\n", - (ulong_t)major(rdev), (ulong_t)minor(rdev)); - else - (void) printf(" rdev:0x%.8lX\n", (long)rdev); - - if (!nflag) { - off_t offset; - - dofcntl(Pr, fd, - (statb.st_mode & (S_IFMT|S_ENFMT|S_IXGRP)) - == (S_IFREG|S_ENFMT), - (statb.st_mode & S_IFMT) == S_IFDOOR); - - if ((statb.st_mode & S_IFMT) == S_IFSOCK) - dosocket(Pr, fd); - else if ((statb.st_mode & S_IFMT) == S_IFIFO) - dofifo(Pr, fd); - - (void) sprintf(pname, "/proc/%d/path/%d", (int)pid, fd); - - if ((ret = readlink(pname, fname, PATH_MAX - 1)) <= 0) - continue; - - fname[ret] = '\0'; - - if ((statb.st_mode & S_IFMT) == S_IFCHR && - (dev = strrchr(fname, ':')) != NULL) { - /* - * There's no elegant way to determine if a - * character device supports TLI, so we lame - * out and just check a hardcoded list of - * known TLI devices. - */ - int i; - const char *tlidevs[] = - { "tcp", "tcp6", "udp", "udp6", NULL }; - - dev++; /* skip past the `:' */ - for (i = 0; tlidevs[i] != NULL; i++) { - if (strcmp(dev, tlidevs[i]) == 0) { - dotli(Pr, fd); - break; - } - } - } - (void) printf(" %s\n", fname); - - offset = pr_lseek(Pr, fd, 0, SEEK_CUR); - if (offset != -1) { - (void) printf(" offset:%ld\n", offset); - } - - } - } - (void) closedir(dirp); + (void) Pfdinfo_iter(Pr, show_file, Pr); } @@ -371,14 +356,17 @@ /* examine open file with fcntl() */ static void -dofcntl(struct ps_prochandle *Pr, int fd, int mandatory, int isdoor) +dofcntl(struct ps_prochandle *Pr, prfdinfo_t *info, int mandatory, int isdoor) { struct flock flock; int fileflags; int fdflags; + int fd; - fileflags = pr_fcntl(Pr, fd, F_GETXFL, 0); - fdflags = pr_fcntl(Pr, fd, F_GETFD, 0); + fd = info->pr_fd; + + fileflags = info->pr_fileflags; + fdflags = info->pr_fdflags; if (fileflags != -1 || fdflags != -1) { (void) printf(" "); @@ -386,10 +374,10 @@ show_fileflags(fileflags); if (fdflags != -1 && (fdflags & FD_CLOEXEC)) (void) printf(" FD_CLOEXEC"); - if (isdoor) + if (isdoor && (Pstate(Pr) != PS_DEAD)) show_door(Pr, fd); (void) fputc('\n', stdout); - } else if (isdoor) { + } else if (isdoor && (Pstate(Pr) != PS_DEAD)) { (void) printf(" "); show_door(Pr, fd); (void) fputc('\n', stdout); @@ -401,7 +389,7 @@ flock.l_len = 0; flock.l_sysid = 0; flock.l_pid = 0; - if (getflock(Pr, fd, &flock) != -1) { + if ((Pstate(Pr) != PS_DEAD) && (getflock(Pr, fd, &flock) != -1)) { if (flock.l_type != F_UNLCK && (flock.l_sysid || flock.l_pid)) { unsigned long sysid = flock.l_sysid; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/corenote.c --- a/usr/src/cmd/sgs/elfdump/common/corenote.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/corenote.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,7 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include #include @@ -1545,6 +1547,45 @@ indent_exit(state); } +static void +dump_prfdinfo(note_state_t *state, const char *title) +{ + const sl_prfdinfo_layout_t *layout = state->ns_arch->prfdinfo; + char buf[1024]; + uint32_t fileflags, mode; + + indent_enter(state, title, &layout->pr_fd); + + PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_FD), pr_fd); + mode = extract_as_word(state, &layout->pr_mode); + + print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_MODE), + conv_cnote_filemode(mode, 0, buf, sizeof (buf))); + + PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_UID), pr_uid, + MSG_ORIG(MSG_CNOTE_T_PR_GID), pr_gid); + + PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_MAJOR), pr_major, + MSG_ORIG(MSG_CNOTE_T_PR_MINOR), pr_minor); + PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_RMAJOR), pr_rmajor, + MSG_ORIG(MSG_CNOTE_T_PR_RMINOR), pr_rminor); + + PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_INO), pr_ino); + + PRINT_DEC_2UP(MSG_ORIG(MSG_CNOTE_T_PR_SIZE), pr_size, + MSG_ORIG(MSG_CNOTE_T_PR_OFFSET), pr_offset); + + fileflags = extract_as_word(state, &layout->pr_fileflags); + + print_str(state, MSG_ORIG(MSG_CNOTE_T_PR_FILEFLAGS), + conv_cnote_fileflags(fileflags, 0, buf, sizeof (buf))); + + PRINT_DEC(MSG_ORIG(MSG_CNOTE_T_PR_FDFLAGS), pr_fdflags); + + PRINT_STRBUF(MSG_ORIG(MSG_CNOTE_T_PR_PATH), pr_path); + + indent_exit(state); +} /* * Output information from priv_impl_info_t structure. @@ -1777,6 +1818,14 @@ dbg_print(0, MSG_ORIG(MSG_NOTE_DESC)); dbg_print(0, MSG_ORIG(MSG_FMT_INDENT), safe_str(desc, descsz)); return (CORENOTE_R_OK); + + + case NT_FDINFO: + state.ns_vcol = 22; + state.ns_t2col = 41; + state.ns_v2col = 54; + dump_prfdinfo(&state, MSG_ORIG(MSG_CNOTE_DESC_PRFDINFO_T)); + return (CORENOTE_R_OK); } return (CORENOTE_R_BADTYPE); diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/elfdump.msg --- a/usr/src/cmd/sgs/elfdump/common/elfdump.msg Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/elfdump.msg Fri Nov 02 09:48:42 2012 -0700 @@ -21,6 +21,7 @@ # # Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012 DEY Storage Systems, Inc. All rights reserved. # @ _START_ @@ -457,6 +458,7 @@ @ MSG_CNOTE_DESC_PSINFO_T "desc: (psinfo_t)" @ MSG_CNOTE_DESC_PSTATUS_T "desc: (pstatus_t)" @ MSG_CNOTE_DESC_STRUCT_UTSNAME "desc: (struct utsname)" +@ MSG_CNOTE_DESC_PRFDINFO_T "desc: (prfdinfo_t)" @ MSG_CNOTE_FMT_LINE "%*s%-*s%s" @@ -615,6 +617,17 @@ @ MSG_CNOTE_T_UTS_RELEASE "release:" @ MSG_CNOTE_T_UTS_SYSNAME "sysname:" @ MSG_CNOTE_T_UTS_VERSION "version:" +@ MSG_CNOTE_T_PR_FD "pr_fd:" +@ MSG_CNOTE_T_PR_MODE "pr_mode:" +@ MSG_CNOTE_T_PR_PATH "pr_path:" +@ MSG_CNOTE_T_PR_MAJOR "pr_major:" +@ MSG_CNOTE_T_PR_MINOR "pr_minor:" +@ MSG_CNOTE_T_PR_RMAJOR "pr_rmajor:" +@ MSG_CNOTE_T_PR_RMINOR "pr_rminor:" +@ MSG_CNOTE_T_PR_OFFSET "pr_offset:" +@ MSG_CNOTE_T_PR_INO "pr_ino:" +@ MSG_CNOTE_T_PR_FILEFLAGS "pr_fileflags:" +@ MSG_CNOTE_T_PR_FDFLAGS "pr_fdflags:" # Names of fake sections generated from program header data diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/struct_layout.h --- a/usr/src/cmd/sgs/elfdump/common/struct_layout.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout.h Fri Nov 02 09:48:42 2012 -0700 @@ -24,6 +24,10 @@ * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ + #ifndef _STRUCT_LAYOUT_H #define _STRUCT_LAYOUT_H @@ -88,7 +92,7 @@ } sl_field_t; /* - * This type is used to extract and manipuate data described by + * This type is used to extract and manipulate data described by * sl_field_t. We rely on the C guarantee that all the fields in * a union have offset 0. */ @@ -502,6 +506,27 @@ } sl_utsname_layout_t; /* + * Layout description of prdinfo_t, from . + */ +typedef struct { + sl_field_t sizeof_struct; + sl_field_t pr_fd; + sl_field_t pr_mode; + sl_field_t pr_uid; + sl_field_t pr_gid; + sl_field_t pr_major; + sl_field_t pr_minor; + sl_field_t pr_rmajor; + sl_field_t pr_rminor; + sl_field_t pr_ino; + sl_field_t pr_offset; + sl_field_t pr_size; + sl_field_t pr_fileflags; + sl_field_t pr_fdflags; + sl_field_t pr_path; +} sl_prfdinfo_layout_t; + +/* * This type collects all of the layout definitions for * a given architecture. */ @@ -525,6 +550,7 @@ const sl_sysset_layout_t *sysset; /* sysset_t */ const sl_timestruc_layout_t *timestruc; /* timestruc_t */ const sl_utsname_layout_t *utsname; /* struct utsname */ + const sl_prfdinfo_layout_t *prfdinfo; /* prdinfo_t */ } sl_arch_layout_t; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_amd64.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,7 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include @@ -356,6 +358,23 @@ }; +static const sl_prfdinfo_layout_t prfdinfo_layout = { + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 4, 0, 0 }, /* pr_fd */ + { 4, 4, 0, 0 }, /* pr_mode */ + { 8, 4, 0, 0 }, /* pr_uid */ + { 12, 4, 0, 0 }, /* pr_gid */ + { 16, 4, 0, 0 }, /* pr_major */ + { 20, 4, 0, 0 }, /* pr_minor */ + { 24, 4, 0, 0 }, /* pr_rmajor */ + { 28, 4, 0, 0 }, /* pr_rminor */ + { 32, 8, 0, 0 }, /* pr_ino */ + { 40, 8, 0, 0 }, /* pr_offset */ + { 48, 8, 0, 0 }, /* pr_size */ + { 56, 4, 0, 0 }, /* pr_filefags */ + { 60, 4, 0, 0 }, /* pr_fdflags */ + { 64, 1, 1024, 0 }, /* pr_path */ +}; static const sl_arch_layout_t layout_amd64 = { @@ -378,6 +397,7 @@ &sysset_layout, ×truc_layout, &utsname_layout, + &prfdinfo_layout, }; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,7 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include @@ -356,6 +358,23 @@ }; +static const sl_prfdinfo_layout_t prfdinfo_layout = { + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 4, 0, 0 }, /* pr_fd */ + { 4, 4, 0, 0 }, /* pr_mode */ + { 8, 4, 0, 0 }, /* pr_uid */ + { 12, 4, 0, 0 }, /* pr_gid */ + { 16, 4, 0, 0 }, /* pr_major */ + { 20, 4, 0, 0 }, /* pr_minor */ + { 24, 4, 0, 0 }, /* pr_rmajor */ + { 28, 4, 0, 0 }, /* pr_rminor */ + { 32, 8, 0, 0 }, /* pr_ino */ + { 40, 8, 0, 0 }, /* pr_offset */ + { 48, 8, 0, 0 }, /* pr_size */ + { 56, 4, 0, 0 }, /* pr_filefags */ + { 60, 4, 0, 0 }, /* pr_fdflags */ + { 64, 1, 1024, 0 }, /* pr_path */ +}; static const sl_arch_layout_t layout_i386 = { @@ -378,6 +397,7 @@ &sysset_layout, ×truc_layout, &utsname_layout, + &prfdinfo_layout, }; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparc.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,8 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include @@ -356,6 +357,23 @@ }; +static const sl_prfdinfo_layout_t prfdinfo_layout = { + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 4, 0, 0 }, /* pr_fd */ + { 4, 4, 0, 0 }, /* pr_mode */ + { 8, 4, 0, 0 }, /* pr_uid */ + { 12, 4, 0, 0 }, /* pr_gid */ + { 16, 4, 0, 0 }, /* pr_major */ + { 20, 4, 0, 0 }, /* pr_minor */ + { 24, 4, 0, 0 }, /* pr_rmajor */ + { 28, 4, 0, 0 }, /* pr_rminor */ + { 32, 8, 0, 0 }, /* pr_ino */ + { 40, 8, 0, 0 }, /* pr_offset */ + { 48, 8, 0, 0 }, /* pr_size */ + { 56, 4, 0, 0 }, /* pr_filefags */ + { 60, 4, 0, 0 }, /* pr_fdflags */ + { 64, 1, 1024, 0 }, /* pr_path */ +}; static const sl_arch_layout_t layout_sparc = { @@ -378,6 +396,7 @@ &sysset_layout, ×truc_layout, &utsname_layout, + &prfdinfo_layout, }; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c --- a/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/elfdump/common/struct_layout_sparcv9.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,7 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include @@ -356,6 +358,23 @@ }; +static const sl_prfdinfo_layout_t prfdinfo_layout = { + { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */ + { 0, 4, 0, 0 }, /* pr_fd */ + { 4, 4, 0, 0 }, /* pr_mode */ + { 8, 4, 0, 0 }, /* pr_uid */ + { 12, 4, 0, 0 }, /* pr_gid */ + { 16, 4, 0, 0 }, /* pr_major */ + { 20, 4, 0, 0 }, /* pr_minor */ + { 24, 4, 0, 0 }, /* pr_rmajor */ + { 28, 4, 0, 0 }, /* pr_rminor */ + { 32, 8, 0, 0 }, /* pr_ino */ + { 40, 8, 0, 0 }, /* pr_offset */ + { 48, 8, 0, 0 }, /* pr_size */ + { 56, 4, 0, 0 }, /* pr_filefags */ + { 60, 4, 0, 0 }, /* pr_fdflags */ + { 64, 1, 1024, 0 }, /* pr_path */ +}; static const sl_arch_layout_t layout_sparcv9 = { @@ -378,6 +397,7 @@ &sysset_layout, ×truc_layout, &utsname_layout, + &prfdinfo_layout, }; diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/include/conv.h --- a/usr/src/cmd/sgs/include/conv.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/include/conv.h Fri Nov 02 09:48:42 2012 -0700 @@ -24,6 +24,7 @@ * All Rights Reserved * * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ #ifndef _CONV_H @@ -837,6 +838,10 @@ Conv_inv_buf_t *); extern const char *conv_cnote_sysset(uint32_t *, int, Conv_fmt_flags_t, Conv_cnote_sysset_buf_t *); +extern const char *conv_cnote_fileflags(uint32_t, Conv_fmt_flags_t, + char *, size_t); +extern const char *conv_cnote_filemode(uint32_t, Conv_fmt_flags_t, + char *, size_t); extern const char *conv_cnote_type(Word, Conv_fmt_flags_t, Conv_inv_buf_t *); extern const char *conv_def_tag(Symref, Conv_inv_buf_t *); diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/libconv/common/corenote.c --- a/usr/src/cmd/sgs/libconv/common/corenote.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/libconv/common/corenote.c Fri Nov 02 09:48:42 2012 -0700 @@ -23,6 +23,9 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ /* * String conversion routines the system structs found in @@ -52,9 +55,9 @@ MSG_NT_UTSNAME, MSG_NT_LWPSTATUS, MSG_NT_LWPSINFO, MSG_NT_PRPRIV, MSG_NT_PRPRIVINFO, MSG_NT_CONTENT, - MSG_NT_ZONENAME + MSG_NT_ZONENAME, MSG_NT_FDINFO }; -#if NT_NUM != NT_ZONENAME +#if NT_NUM != NT_FDINFO #error "NT_NUM has grown. Update core note types[]" #endif static const conv_ds_msg_t ds_types = { @@ -2442,3 +2445,138 @@ #undef N_MASK } + +const char * +conv_cnote_fileflags(uint32_t fileflags, Conv_fmt_flags_t fmt_flags, + char *buf, size_t bufsize) +{ + CONV_EXPN_FIELD_ARG arg = { 0 }; + + Val_desc vda[] = { + { 0x0001, MSG_PR_O_WRONLY }, + { 0x0002, MSG_PR_O_RDONLY }, + { 0x200000, MSG_PR_O_SEARCH }, + { 0x400000, MSG_PR_O_EXEC }, + { 0x0004, MSG_PR_O_NDELAY }, + { 0x0008, MSG_PR_O_APPEND }, + { 0x0010, MSG_PR_O_SYNC }, + { 0x0040, MSG_PR_O_DSYNC }, + { 0x0080, MSG_PR_O_NONBLOCK }, + { 0x0100, MSG_PR_O_CREAT }, + { 0x0200, MSG_PR_O_TRUNC }, + { 0x0400, MSG_PR_O_EXCL }, + { 0x0800, MSG_PR_O_NOCTTY }, + { 0x4000, MSG_PR_O_XATTR }, + { 0x8000, MSG_PR_O_RSYNC }, + { 0x2000, MSG_PR_O_LARGEFILE }, + { 0x20000, MSG_PR_O_NOFOLLOW }, + { 0x40000, MSG_PR_O_NOLINKS }, + { 0, NULL }, + }; + + arg.oflags = arg.rflags = fileflags; + arg.buf = buf; + arg.bufsize = bufsize; + + switch (fileflags & (0x600003)) { + case 0: /* RDONLY */ + vda[0].v_msg = MSG_PR_O_RDONLY; + arg.oflags |= 1; + arg.rflags |= 1; + break; + case 1: /* WRONLY */ + case 2: /* RDWR */ + case 0x200000: /* SEARCH */ + case 0x400000: + /* In isolate, treat these as normal bits */ + break; + default: + /* More than one bit set in this group, emit numerically */ + arg.oflags &= ~(fileflags & 0x600003); + } + + if (fileflags == 0) + return (MSG_ORIG(MSG_GBL_ZERO)); + + (void) conv_expn_field(&arg, vda, fmt_flags); + return (buf); +} + +const char * +conv_cnote_filemode(uint32_t mode, Conv_fmt_flags_t fmt_flags, + char *buf, size_t bufsize) +{ + CONV_EXPN_FIELD_ARG arg = { 0 }; + Msg s; + + Val_desc vda[] = { + { 0x1000, MSG_S_IFIFO }, + { 0x800, MSG_S_ISUID }, + { 0x400, MSG_S_ISGID }, + { 0x200, MSG_S_ISVTX }, + { 0400, MSG_S_IRUSR }, + { 0200, MSG_S_IWUSR }, + { 0100, MSG_S_IXUSR }, + { 0040, MSG_S_IRGRP }, + { 0020, MSG_S_IWGRP }, + { 0010, MSG_S_IXGRP }, + { 0004, MSG_S_IROTH }, + { 0002, MSG_S_IWOTH }, + { 0001, MSG_S_IXOTH }, + { 0, NULL }, + }; + + arg.oflags = arg.rflags = mode & ~(0xf000); + arg.buf = buf; + arg.bufsize = bufsize; + + switch (mode & (0xf000)) { + case 0x1000: + s = MSG_S_IFIFO; + break; + case 0x2000: + s = MSG_S_IFCHR; + break; + case 0x4000: + s = MSG_S_IFDIR; + break; + case 0x5000: + s = MSG_S_IFNAM; + break; + case 0x6000: + s = MSG_S_IFBLK; + break; + case 0x8000: + s = MSG_S_IFREG; + break; + case 0xA000: + s = MSG_S_IFLNK; + break; + case 0xc000: + s = MSG_S_IFSOCK; + break; + case 0xd000: + s = MSG_S_IFDOOR; + break; + case 0xe000: + s = MSG_S_IFPORT; + break; + default: + s = NULL; + break; + } + + if (s) { + arg.oflags |= 0x1000; + arg.rflags |= 0x1000; + vda[0].v_msg = s; + } else { + arg.rflags = mode; + } + + if (mode == 0) + return (MSG_ORIG(MSG_GBL_ZERO)); + + (void) conv_expn_field(&arg, vda, fmt_flags); + return (buf); +} diff -r cab67b95c26b -r f128a109e6d2 usr/src/cmd/sgs/libconv/common/corenote.msg --- a/usr/src/cmd/sgs/libconv/common/corenote.msg Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/cmd/sgs/libconv/common/corenote.msg Fri Nov 02 09:48:42 2012 -0700 @@ -23,6 +23,8 @@ # Copyright 2010 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright 2012 DEY Storage Systems, Inc. All rights reserved. +# @ MSG_NT_PRSTATUS "[ NT_PRSTATUS ]" @ MSG_NT_PRFPREG "[ NT_PRFPREG ]" @@ -43,6 +45,7 @@ @ MSG_NT_PRPRIVINFO "[ NT_PRPRIVINFO ]" @ MSG_NT_CONTENT "[ NT_CONTENT ]" @ MSG_NT_ZONENAME "[ NT_ZONENAME ]" +@ MSG_NT_FDINFO "[ NT_FDINFO ]" @ MSG_AUXV_AF_SUN_SETUGID "AF_SUN_SETUGID" @@ -1067,6 +1070,48 @@ @ MSG_SYS_UMOUNT2 "[ umount2 ]" # 255 @ MSG_SYS_UMOUNT2_ALT "umount2" +@ MSG_PR_O_RDONLY "O_RDONLY" +@ MSG_PR_O_WRONLY "O_WRONLY" +@ MSG_PR_O_RDWR "O_RDWR" +@ MSG_PR_O_SEARCH "O_SEARCH" +@ MSG_PR_O_EXEC "O_EXEC" +@ MSG_PR_O_NDELAY "O_NDELAY" +@ MSG_PR_O_NONBLOCK "O_NONBLOCK" +@ MSG_PR_O_APPEND "O_APPEND" +@ MSG_PR_O_SYNC "O_SYNC" +@ MSG_PR_O_DSYNC "O_DSYNC" +@ MSG_PR_O_RSYNC "O_RSYNC" +@ MSG_PR_O_CREAT "O_CREAT" +@ MSG_PR_O_TRUNC "O_TRUNC" +@ MSG_PR_O_EXCL "O_EXCL" +@ MSG_PR_O_NOCTTY "O_NOCTTY" +@ MSG_PR_O_LARGEFILE "O_LARGEFILE" +@ MSG_PR_O_XATTR "O_XATTR" +@ MSG_PR_O_NOFOLLOW "O_NOFOLLOW" +@ MSG_PR_O_NOLINKS "O_NOLINKS" + +@ MSG_S_IFIFO "S_IFIFO" +@ MSG_S_IFCHR "S_IFCHR" +@ MSG_S_IFDIR "S_IFDIR" +@ MSG_S_IFNAM "S_IFNAM" +@ MSG_S_IFBLK "S_IFBLK" +@ MSG_S_IFREG "S_IFREG" +@ MSG_S_IFLNK "S_IFLNK" +@ MSG_S_IFSOCK "S_IFSOCK" +@ MSG_S_IFDOOR "S_IFDOOR" +@ MSG_S_IFPORT "S_IFPORT" +@ MSG_S_ISUID "S_ISUID" +@ MSG_S_ISGID "S_ISGID" +@ MSG_S_ISVTX "S_ISVTX" +@ MSG_S_IRUSR "S_IRUSR" +@ MSG_S_IWUSR "S_IWUSR" +@ MSG_S_IXUSR "S_IXUSR" +@ MSG_S_IRGRP "S_IRGRP" +@ MSG_S_IWGRP "S_IWGRP" +@ MSG_S_IXGRP "S_IXGRP" +@ MSG_S_IROTH "S_IROTH" +@ MSG_S_IWOTH "S_IWOTH" +@ MSG_S_IXOTH "S_IXOTH" @ MSG_GBL_ZERO "0" diff -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/Makefile.com --- a/usr/src/lib/libproc/Makefile.com Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/Makefile.com Fri Nov 02 09:48:42 2012 -0700 @@ -20,6 +20,7 @@ # # # Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2012 DEY Storage Systems, Inc. All rights reserved. # LIBRARY = libproc.a @@ -30,6 +31,7 @@ Pcontrol.o \ Pcore.o \ Pexecname.o \ + Pfdinfo.o \ Pgcore.o \ Pidle.o \ Pisprocdir.o \ diff -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/Pcontrol.c --- a/usr/src/lib/libproc/common/Pcontrol.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/Pcontrol.c Fri Nov 02 09:48:42 2012 -0700 @@ -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 @@ -986,6 +987,13 @@ } 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 -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/Pcontrol.h --- a/usr/src/lib/libproc/common/Pcontrol.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/Pcontrol.h Fri Nov 02 09:48:42 2012 -0700 @@ -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 @@ #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 @@ 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 *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 -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/Pcore.c --- a/usr/src/lib/libproc/common/Pcore.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/Pcore.c Fri Nov 02 09:48:42 2012 -0700 @@ -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 #include @@ -300,6 +303,26 @@ } 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 @@ note_priv_info, /* 19 NT_PRPRIVINFO */ note_content, /* 20 NT_CONTENT */ note_zonename, /* 21 NT_ZONENAME */ + note_fdinfo, /* 22 NT_FDINFO */ }; /* diff -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/Pfdinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libproc/common/Pfdinfo.c Fri Nov 02 09:48:42 2012 -0700 @@ -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 +#include +#include +#include +#include +#include +#include +#include + +#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 -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/Pgcore.c --- a/usr/src/lib/libproc/common/Pgcore.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/Pgcore.c Fri Nov 02 09:48:42 2012 -0700 @@ -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 @@ 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 @@ 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 @@ &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 -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/libproc.h --- a/usr/src/lib/libproc/common/libproc.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/libproc.h Fri Nov 02 09:48:42 2012 -0700 @@ -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_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 -r cab67b95c26b -r f128a109e6d2 usr/src/lib/libproc/common/mapfile-vers --- a/usr/src/lib/libproc/common/mapfile-vers Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/lib/libproc/common/mapfile-vers Fri Nov 02 09:48:42 2012 -0700 @@ -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 @@ Pzonename; Pzonepath; Pzoneroot; + Pfdinfo_iter; $if _x86 && _ELF32 Pldt; diff -r cab67b95c26b -r f128a109e6d2 usr/src/man/man1/proc.1 --- a/usr/src/man/man1/proc.1 Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/man/man1/proc.1 Fri Nov 02 09:48:42 2012 -0700 @@ -1,10 +1,11 @@ '\" te .\" Copyright (c) 2008, Sun Microsystems, Inc. All Rights Reserved .\" Portions Copyright 2008 Chad Mynhier +.\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved. .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH PROC 1 "Dec 10, 2008" +.TH PROC 1 "Oct 23, 2012" .SH NAME proc, pflags, pcred, pldd, psig, pstack, pfiles, pwdx, pstop, prun, pwait, ptime \- proc tools @@ -46,7 +47,7 @@ .LP .nf -\fB/usr/bin/pfiles\fR [\fB-Fn\fR] \fIpid\fR... +\fB/usr/bin/pfiles\fR [\fB-Fn\fR] \fIpid\fR | \fIcore\fR... .fi .LP diff -r cab67b95c26b -r f128a109e6d2 usr/src/man/man4/core.4 --- a/usr/src/man/man4/core.4 Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/man/man4/core.4 Fri Nov 02 09:48:42 2012 -0700 @@ -1,10 +1,11 @@ '\" te .\" Copyright (C) 2008, Sun Microsystems, Inc. All Rights Reserved. +.\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved. .\" Copyright 1989 AT&T .\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License. .\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License. .\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner] -.TH CORE 4 "May 13, 2008" +.TH CORE 4 "Oct 23, 2012" .SH NAME core \- process core file .SH DESCRIPTION @@ -307,7 +308,7 @@ .RS 20n \fBn_type\fR: \fBNT_PRCRED\fR. This structure contains the process credentials, including the real, saved, and effective user and group IDs. The \fBprcred_t\fR -structure is defined in <\fBaasys/procfs.h\fR>. Following the structure is an +structure is defined in <\fBsys/procfs.h\fR>. Following the structure is an optional array of supplementary group IDs. The total number of supplementary group IDs is given by the \fBpr_ngroups\fR member of the \fBprcred_t\fR structure, and the structure includes space for one supplementary group. If @@ -330,6 +331,18 @@ .sp .ne 2 .na +\fB\fBprfdinfo_t\fR\fR +.ad +.RS 20n +\fBn_type\fR: \fBNT_FDINFO\fR. This structure contains information about +any open file descriptors, including the path, flags, and +\fBstat\fR(2) information. The \fBprfdinfo_t\fR structure is defined in +<\fBsys/procfs.h\fR>. +.RE + +.sp +.ne 2 +.na \fB\fBstruct ssd\fR array\fR .ad .RS 20n diff -r cab67b95c26b -r f128a109e6d2 usr/src/uts/common/exec/elf/elf_notes.c --- a/usr/src/uts/common/exec/elf/elf_notes.c Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/uts/common/exec/elf/elf_notes.c Fri Nov 02 09:48:42 2012 -0700 @@ -24,7 +24,9 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #include #include @@ -34,8 +36,11 @@ #include #include #include +#include #include #include +#include +#include #include #include #include @@ -57,6 +62,7 @@ #include #include #include +#include #include "elf_impl.h" #if defined(__i386) || defined(__i386_COMPAT) #include @@ -67,12 +73,27 @@ { int nlwp = p->p_lwpcnt; int nzomb = p->p_zombcnt; + int nfd; size_t size; prcred_t *pcrp; + uf_info_t *fip; + uf_entry_t *ufp; + int fd; + + fip = P_FINFO(p); + nfd = 0; + mutex_enter(&fip->fi_lock); + for (fd = 0; fd < fip->fi_nfiles; fd++) { + UF_ENTER(ufp, fip, fd); + if ((ufp->uf_file != NULL) && (ufp->uf_file->f_count > 0)) + nfd++; + UF_EXIT(ufp); + } + mutex_exit(&fip->fi_lock); v[0].p_type = PT_NOTE; v[0].p_flags = PF_R; - v[0].p_filesz = (sizeof (Note) * (9 + 2 * nlwp + nzomb)) + v[0].p_filesz = (sizeof (Note) * (9 + 2 * nlwp + nzomb + nfd)) + roundup(sizeof (psinfo_t), sizeof (Word)) + roundup(sizeof (pstatus_t), sizeof (Word)) + roundup(prgetprivsize(), sizeof (Word)) @@ -83,7 +104,8 @@ + roundup(sizeof (utsname), sizeof (Word)) + roundup(sizeof (core_content_t), sizeof (Word)) + (nlwp + nzomb) * roundup(sizeof (lwpsinfo_t), sizeof (Word)) - + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)); + + nlwp * roundup(sizeof (lwpstatus_t), sizeof (Word)) + + nfd * roundup(sizeof (prfdinfo_t), sizeof (Word)); size = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); pcrp = kmem_alloc(size, KM_SLEEP); @@ -97,6 +119,7 @@ } kmem_free(pcrp, size); + #if defined(__i386) || defined(__i386_COMPAT) mutex_enter(&p->p_ldtlock); size = prnldt(p) * sizeof (struct ssd); @@ -159,7 +182,7 @@ size_t crsize = sizeof (prcred_t) + sizeof (gid_t) * (ngroups_max - 1); size_t psize = prgetprivsize(); size_t bigsize = MAX(psize, MAX(sizeof (*bigwad), - MAX(xregsize, crsize))); + MAX(xregsize, crsize))); priv_impl_info_t *prii; @@ -173,6 +196,10 @@ int nzomb; int error; uchar_t oldsig; + uf_info_t *fip; + int fd; + vnode_t *vroot; + #if defined(__i386) || defined(__i386_COMPAT) struct ssd *ssd; size_t ssdsize; @@ -293,6 +320,89 @@ if (error) goto done; + + /* open file table */ + vroot = PTOU(p)->u_rdir; + if (vroot == NULL) + vroot = rootdir; + + VN_HOLD(vroot); + + fip = P_FINFO(p); + + for (fd = 0; fd < fip->fi_nfiles; fd++) { + uf_entry_t *ufp; + vnode_t *fvp; + struct file *fp; + vattr_t vattr; + prfdinfo_t fdinfo; + + bzero(&fdinfo, sizeof (fdinfo)); + + mutex_enter(&fip->fi_lock); + UF_ENTER(ufp, fip, fd); + if (((fp = ufp->uf_file) == NULL) || (fp->f_count < 1)) { + UF_EXIT(ufp); + mutex_exit(&fip->fi_lock); + continue; + } + + fdinfo.pr_fd = fd; + fdinfo.pr_fdflags = ufp->uf_flag; + fdinfo.pr_fileflags = fp->f_flag2; + fdinfo.pr_fileflags <<= 16; + fdinfo.pr_fileflags |= fp->f_flag; + if ((fdinfo.pr_fileflags & (FSEARCH | FEXEC)) == 0) + fdinfo.pr_fileflags += FOPEN; + fdinfo.pr_offset = fp->f_offset; + + + fvp = fp->f_vnode; + VN_HOLD(fvp); + UF_EXIT(ufp); + mutex_exit(&fip->fi_lock); + + /* + * There are some vnodes that have no corresponding + * path. Its reasonable for this to fail, in which + * case the path will remain an empty string. + */ + (void) vnodetopath(vroot, fvp, fdinfo.pr_path, + sizeof (fdinfo.pr_path), credp); + + error = VOP_GETATTR(fvp, &vattr, 0, credp, NULL); + if (error != 0) { + VN_RELE(fvp); + VN_RELE(vroot); + goto done; + } + + if (fvp->v_type == VSOCK) + fdinfo.pr_fileflags |= sock_getfasync(fvp); + + VN_RELE(fvp); + + /* + * This logic mirrors fstat(), which we cannot use + * directly, as it calls copyout(). + */ + fdinfo.pr_major = getmajor(vattr.va_fsid); + fdinfo.pr_minor = getminor(vattr.va_fsid); + fdinfo.pr_ino = (ino64_t)vattr.va_nodeid; + fdinfo.pr_mode = VTTOIF(vattr.va_type) | vattr.va_mode; + fdinfo.pr_uid = vattr.va_uid; + fdinfo.pr_gid = vattr.va_gid; + fdinfo.pr_rmajor = getmajor(vattr.va_rdev); + fdinfo.pr_rminor = getminor(vattr.va_rdev); + fdinfo.pr_size = (off64_t)vattr.va_size; + + error = elfnote(vp, &offset, NT_FDINFO, + sizeof (fdinfo), &fdinfo, rlimit, credp); + if (error) { + goto done; + } + } + #if defined(__i386) || defined(__i386_COMPAT) mutex_enter(&p->p_ldtlock); ssdsize = prnldt(p) * sizeof (struct ssd); diff -r cab67b95c26b -r f128a109e6d2 usr/src/uts/common/sys/elf.h --- a/usr/src/uts/common/sys/elf.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/uts/common/sys/elf.h Fri Nov 02 09:48:42 2012 -0700 @@ -19,6 +19,9 @@ * CDDL HEADER END */ /* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ +/* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -812,7 +815,8 @@ #define NT_PRPRIVINFO 19 /* priv_impl_info_t */ #define NT_CONTENT 20 /* core_content_t */ #define NT_ZONENAME 21 /* string from getzonenamebyid(3C) */ -#define NT_NUM 21 +#define NT_FDINFO 22 /* open fd info */ +#define NT_NUM 22 #ifdef _KERNEL diff -r cab67b95c26b -r f128a109e6d2 usr/src/uts/common/sys/procfs.h --- a/usr/src/uts/common/sys/procfs.h Tue Oct 23 12:58:35 2012 -0400 +++ b/usr/src/uts/common/sys/procfs.h Fri Nov 02 09:48:42 2012 -0700 @@ -23,12 +23,13 @@ * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. + */ #ifndef _SYS_PROCFS_H #define _SYS_PROCFS_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -61,6 +62,8 @@ #include #include #include +#include +#include #if !defined(_LP64) && _FILE_OFFSET_BITS == 64 #error "Cannot use procfs in the large file compilation environment" @@ -492,6 +495,38 @@ #define PG_HWMAPPED 0x04 /* page is present and mapped */ /* + * Open files. Only in core files (for now). Note that we'd like to use + * the stat or stat64 structure, but both of these structures are unfortunately + * not consistent between 32 and 64 bit modes. To keep our lives simpler, we + * just define our own structure with types that are not sensitive to this + * difference. Also, it turns out that pfiles omits a lot of info from the + * struct stat (e.g. times, device sizes, etc.) so we don't bother adding those + * here. + */ +typedef struct prfdinfo { + int pr_fd; + mode_t pr_mode; + + uid_t pr_uid; + gid_t pr_gid; + + major_t pr_major; /* think stat.st_dev */ + minor_t pr_minor; + + major_t pr_rmajor; /* think stat.st_rdev */ + minor_t pr_rminor; + + ino64_t pr_ino; + off64_t pr_offset; + off64_t pr_size; + + int pr_fileflags; /* fcntl(F_GETXFL), etc */ + int pr_fdflags; /* fcntl(F_GETFD), etc. */ + + char pr_path[MAXPATHLEN]; +} prfdinfo_t; + +/* * Header for /proc//lstatus /proc//lpsinfo /proc//lusage */ typedef struct prheader {