kern/173723: commit references a PR

dfilter service dfilter at FreeBSD.ORG
Tue Apr 16 19:20:01 UTC 2013


The following reply was made to PR kern/173723; it has been noted by GNATS.

From: dfilter at FreeBSD.ORG (dfilter service)
To: bug-followup at FreeBSD.org
Cc:  
Subject: Re: kern/173723: commit references a PR
Date: Tue, 16 Apr 2013 19:19:29 +0000 (UTC)

 Author: trociny
 Date: Tue Apr 16 19:19:14 2013
 New Revision: 249558
 URL: http://svnweb.freebsd.org/changeset/base/249558
 
 Log:
   Add a new set of notes to a process core dump to store procstat data.
   
   The notes format is a header of sizeof(int), which stores the size of
   the corresponding data structure to provide some versioning, and data
   in the format as it is returned by a related sysctl call.
   
   The userland tools (procstat(1)) will be taught to extract this data,
   providing additional info for postmortem analysis.
   
   PR:		kern/173723
   Suggested by:	jhb
   Discussed with:	jhb, kib
   Reviewed by:	jhb (initial version), kib
   MFC after:	1 month
 
 Modified:
   head/sys/kern/imgact_elf.c
   head/sys/sys/elf_common.h
 
 Modified: head/sys/kern/imgact_elf.c
 ==============================================================================
 --- head/sys/kern/imgact_elf.c	Tue Apr 16 17:50:20 2013	(r249557)
 +++ head/sys/kern/imgact_elf.c	Tue Apr 16 19:19:14 2013	(r249558)
 @@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/vnode.h>
  #include <sys/syslog.h>
  #include <sys/eventhandler.h>
 +#include <sys/user.h>
  
  #include <net/zlib.h>
  
 @@ -1062,12 +1063,22 @@ static void __elfN(puthdr)(struct thread
  static void __elfN(putnote)(struct note_info *, struct sbuf *);
  static size_t register_note(struct note_info_list *, int, outfunc_t, void *);
  static int sbuf_drain_core_output(void *, const char *, int);
 +static int sbuf_drain_count(void *arg, const char *data, int len);
  
  static void __elfN(note_fpregset)(void *, struct sbuf *, size_t *);
  static void __elfN(note_prpsinfo)(void *, struct sbuf *, size_t *);
  static void __elfN(note_prstatus)(void *, struct sbuf *, size_t *);
  static void __elfN(note_threadmd)(void *, struct sbuf *, size_t *);
  static void __elfN(note_thrmisc)(void *, struct sbuf *, size_t *);
 +static void __elfN(note_procstat_auxv)(void *, struct sbuf *, size_t *);
 +static void __elfN(note_procstat_proc)(void *, struct sbuf *, size_t *);
 +static void __elfN(note_procstat_psstrings)(void *, struct sbuf *, size_t *);
 +static void note_procstat_files(void *, struct sbuf *, size_t *);
 +static void note_procstat_groups(void *, struct sbuf *, size_t *);
 +static void note_procstat_osrel(void *, struct sbuf *, size_t *);
 +static void note_procstat_rlimit(void *, struct sbuf *, size_t *);
 +static void note_procstat_umask(void *, struct sbuf *, size_t *);
 +static void note_procstat_vmmap(void *, struct sbuf *, size_t *);
  
  #ifdef COMPRESS_USER_CORES
  extern int compress_user_cores;
 @@ -1113,9 +1124,21 @@ static int
  sbuf_drain_core_output(void *arg, const char *data, int len)
  {
  	struct sbuf_drain_core_params *p;
 -	int error;
 +	int error, locked;
  
  	p = (struct sbuf_drain_core_params *)arg;
 +
 +	/*
 +	 * Some kern_proc out routines that print to this sbuf may
 +	 * call us with the process lock held. Draining with the
 +	 * non-sleepable lock held is unsafe. The lock is needed for
 +	 * those routines when dumping a live process. In our case we
 +	 * can safely release the lock before draining and acquire
 +	 * again after.
 +	 */
 +	locked = PROC_LOCKED(p->td->td_proc);
 +	if (locked)
 +		PROC_UNLOCK(p->td->td_proc);
  #ifdef COMPRESS_USER_CORES
  	if (p->gzfile != Z_NULL)
  		error = compress_core(p->gzfile, NULL, __DECONST(char *, data),
 @@ -1126,12 +1149,27 @@ sbuf_drain_core_output(void *arg, const 
  		    __DECONST(void *, data), len, p->offset, UIO_SYSSPACE,
  		    IO_UNIT | IO_DIRECT, p->active_cred, p->file_cred, NULL,
  		    p->td);
 +	if (locked)
 +		PROC_LOCK(p->td->td_proc);
  	if (error != 0)
  		return (-error);
  	p->offset += len;
  	return (len);
  }
  
 +/*
 + * Drain into a counter.
 + */
 +static int
 +sbuf_drain_count(void *arg, const char *data __unused, int len)
 +{
 +	size_t *sizep;
 +
 +	sizep = (size_t *)arg;
 +	*sizep += len;
 +	return (len);
 +}
 +
  int
  __elfN(coredump)(struct thread *td, struct vnode *vp, off_t limit, int flags)
  {
 @@ -1436,6 +1474,25 @@ __elfN(prepare_notes)(struct thread *td,
  			thr = TAILQ_NEXT(thr, td_plist);
  	}
  
 +	size += register_note(list, NT_PROCSTAT_PROC,
 +	    __elfN(note_procstat_proc), p);
 +	size += register_note(list, NT_PROCSTAT_FILES,
 +	    note_procstat_files, p);
 +	size += register_note(list, NT_PROCSTAT_VMMAP,
 +	    note_procstat_vmmap, p);
 +	size += register_note(list, NT_PROCSTAT_GROUPS,
 +	    note_procstat_groups, p);
 +	size += register_note(list, NT_PROCSTAT_UMASK,
 +	    note_procstat_umask, p);
 +	size += register_note(list, NT_PROCSTAT_RLIMIT,
 +	    note_procstat_rlimit, p);
 +	size += register_note(list, NT_PROCSTAT_OSREL,
 +	    note_procstat_osrel, p);
 +	size += register_note(list, NT_PROCSTAT_PSSTRINGS,
 +	    __elfN(note_procstat_psstrings), p);
 +	size += register_note(list, NT_PROCSTAT_AUXV,
 +	    __elfN(note_procstat_auxv), p);
 +
  	*sizep = size;
  }
  
 @@ -1562,6 +1619,9 @@ typedef struct fpreg32 elf_prfpregset_t;
  typedef struct fpreg32 elf_fpregset_t;
  typedef struct reg32 elf_gregset_t;
  typedef struct thrmisc32 elf_thrmisc_t;
 +#define ELF_KERN_PROC_MASK	KERN_PROC_MASK32
 +typedef struct kinfo_proc32 elf_kinfo_proc_t;
 +typedef uint32_t elf_ps_strings_t;
  #else
  typedef prstatus_t elf_prstatus_t;
  typedef prpsinfo_t elf_prpsinfo_t;
 @@ -1569,6 +1629,9 @@ typedef prfpregset_t elf_prfpregset_t;
  typedef prfpregset_t elf_fpregset_t;
  typedef gregset_t elf_gregset_t;
  typedef thrmisc_t elf_thrmisc_t;
 +#define ELF_KERN_PROC_MASK	0
 +typedef struct kinfo_proc elf_kinfo_proc_t;
 +typedef vm_offset_t elf_ps_strings_t;
  #endif
  
  static void
 @@ -1686,6 +1749,221 @@ __elfN(note_threadmd)(void *arg, struct 
  	*sizep = size;
  }
  
 +#ifdef KINFO_PROC_SIZE
 +CTASSERT(sizeof(struct kinfo_proc) == KINFO_PROC_SIZE);
 +#endif
 +
 +static void
 +__elfN(note_procstat_proc)(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + p->p_numthreads *
 +	    sizeof(elf_kinfo_proc_t);
 +
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(elf_kinfo_proc_t);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		kern_proc_out(p, sb, ELF_KERN_PROC_MASK);
 +	}
 +	*sizep = size;
 +}
 +
 +#ifdef KINFO_FILE_SIZE
 +CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
 +#endif
 +
 +static void
 +note_procstat_files(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	if (sb == NULL) {
 +		size = 0;
 +		sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
 +		sbuf_set_drain(sb, sbuf_drain_count, &size);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		kern_proc_filedesc_out(p, sb, -1);
 +		sbuf_finish(sb);
 +		sbuf_delete(sb);
 +		*sizep = size;
 +	} else {
 +		structsize = sizeof(struct kinfo_file);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		kern_proc_filedesc_out(p, sb, -1);
 +	}
 +}
 +
 +#ifdef KINFO_VMENTRY_SIZE
 +CTASSERT(sizeof(struct kinfo_vmentry) == KINFO_VMENTRY_SIZE);
 +#endif
 +
 +static void
 +note_procstat_vmmap(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	if (sb == NULL) {
 +		size = 0;
 +		sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
 +		sbuf_set_drain(sb, sbuf_drain_count, &size);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		kern_proc_vmmap_out(p, sb);
 +		sbuf_finish(sb);
 +		sbuf_delete(sb);
 +		*sizep = size;
 +	} else {
 +		structsize = sizeof(struct kinfo_vmentry);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		kern_proc_vmmap_out(p, sb);
 +	}
 +}
 +
 +static void
 +note_procstat_groups(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + p->p_ucred->cr_ngroups * sizeof(gid_t);
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(gid_t);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		sbuf_bcat(sb, p->p_ucred->cr_groups, p->p_ucred->cr_ngroups *
 +		    sizeof(gid_t));
 +	}
 +	*sizep = size;
 +}
 +
 +static void
 +note_procstat_umask(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + sizeof(p->p_fd->fd_cmask);
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(p->p_fd->fd_cmask);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		sbuf_bcat(sb, &p->p_fd->fd_cmask, sizeof(p->p_fd->fd_cmask));
 +	}
 +	*sizep = size;
 +}
 +
 +static void
 +note_procstat_rlimit(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	struct rlimit rlim[RLIM_NLIMITS];
 +	size_t size;
 +	int structsize, i;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + sizeof(rlim);
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(rlim);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PROC_LOCK(p);
 +		for (i = 0; i < RLIM_NLIMITS; i++)
 +			lim_rlimit(p, i, &rlim[i]);
 +		PROC_UNLOCK(p);
 +		sbuf_bcat(sb, rlim, sizeof(rlim));
 +	}
 +	*sizep = size;
 +}
 +
 +static void
 +note_procstat_osrel(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + sizeof(p->p_osrel);
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(p->p_osrel);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		sbuf_bcat(sb, &p->p_osrel, sizeof(p->p_osrel));
 +	}
 +	*sizep = size;
 +}
 +
 +static void
 +__elfN(note_procstat_psstrings)(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	elf_ps_strings_t ps_strings;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	size = sizeof(structsize) + sizeof(ps_strings);
 +	if (sb != NULL) {
 +		KASSERT(*sizep == size, ("invalid size"));
 +		structsize = sizeof(ps_strings);
 +#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
 +		ps_strings = PTROUT(p->p_sysent->sv_psstrings);
 +#else
 +		ps_strings = p->p_sysent->sv_psstrings;
 +#endif
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		sbuf_bcat(sb, &ps_strings, sizeof(ps_strings));
 +	}
 +	*sizep = size;
 +}
 +
 +static void
 +__elfN(note_procstat_auxv)(void *arg, struct sbuf *sb, size_t *sizep)
 +{
 +	struct proc *p;
 +	size_t size;
 +	int structsize;
 +
 +	p = (struct proc *)arg;
 +	if (sb == NULL) {
 +		size = 0;
 +		sb = sbuf_new(NULL, NULL, 128, SBUF_FIXEDLEN);
 +		sbuf_set_drain(sb, sbuf_drain_count, &size);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PHOLD(p);
 +		proc_getauxv(curthread, p, sb);
 +		PRELE(p);
 +		sbuf_finish(sb);
 +		sbuf_delete(sb);
 +		*sizep = size;
 +	} else {
 +		structsize = sizeof(Elf_Auxinfo);
 +		sbuf_bcat(sb, &structsize, sizeof(structsize));
 +		PHOLD(p);
 +		proc_getauxv(curthread, p, sb);
 +		PRELE(p);
 +	}
 +}
 +
  static boolean_t
  __elfN(parse_notes)(struct image_params *imgp, Elf_Brandnote *checknote,
      int32_t *osrel, const Elf_Phdr *pnote)
 
 Modified: head/sys/sys/elf_common.h
 ==============================================================================
 --- head/sys/sys/elf_common.h	Tue Apr 16 17:50:20 2013	(r249557)
 +++ head/sys/sys/elf_common.h	Tue Apr 16 19:19:14 2013	(r249558)
 @@ -487,6 +487,15 @@ typedef struct {
  #define	NT_FPREGSET	2	/* Floating point registers. */
  #define	NT_PRPSINFO	3	/* Process state info. */
  #define	NT_THRMISC	7	/* Thread miscellaneous info. */
 +#define	NT_PROCSTAT_PROC	8	/* Procstat proc data. */
 +#define	NT_PROCSTAT_FILES	9	/* Procstat files data. */
 +#define	NT_PROCSTAT_VMMAP	10	/* Procstat vmmap data. */
 +#define	NT_PROCSTAT_GROUPS	11	/* Procstat groups data. */
 +#define	NT_PROCSTAT_UMASK	12	/* Procstat umask data. */
 +#define	NT_PROCSTAT_RLIMIT	13	/* Procstat rlimit data. */
 +#define	NT_PROCSTAT_OSREL	14	/* Procstat osreldate data. */
 +#define	NT_PROCSTAT_PSSTRINGS	15	/* Procstat ps_strings data. */
 +#define	NT_PROCSTAT_AUXV	16	/* Procstat auxv data. */
  
  /* Symbol Binding - ELFNN_ST_BIND - st_info */
  #define	STB_LOCAL	0	/* Local symbol */
 _______________________________________________
 svn-src-all at freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe at freebsd.org"
 


More information about the freebsd-bugs mailing list