svn commit: r252829 - stable/9/sys/kern
Mikolaj Golub
trociny at FreeBSD.org
Fri Jul 5 19:38:58 UTC 2013
Author: trociny
Date: Fri Jul 5 19:38:57 2013
New Revision: 252829
URL: http://svnweb.freebsd.org/changeset/base/252829
Log:
MFC r252313, r252349, 252436:
To avoid LOR, drop the filedesc lock in export_fd_to_sb(), before
writing to sbuf.
MFC r252351 (mjg):
Remove duplicate NULL check in kern_proc_filedesc_out.
No functional changes.
Modified:
stable/9/sys/kern/kern_descrip.c
Directory Properties:
stable/9/sys/ (props changed)
Modified: stable/9/sys/kern/kern_descrip.c
==============================================================================
--- stable/9/sys/kern/kern_descrip.c Fri Jul 5 19:36:34 2013 (r252828)
+++ stable/9/sys/kern/kern_descrip.c Fri Jul 5 19:38:57 2013 (r252829)
@@ -3262,10 +3262,17 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC
CTASSERT(sizeof(struct kinfo_file) == KINFO_FILE_SIZE);
#endif
+struct export_fd_buf {
+ struct filedesc *fdp;
+ struct sbuf *sb;
+ ssize_t remainder;
+ struct kinfo_file kif;
+};
+
static int
export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
int64_t offset, int fd_is_cap, cap_rights_t fd_cap_rights,
- struct kinfo_file *kif, struct sbuf *sb, ssize_t *remainder)
+ struct export_fd_buf *efbuf)
{
struct {
int fflag;
@@ -3288,16 +3295,23 @@ export_fd_to_sb(void *data, int type, in
{ O_TRUNC, KF_FLAG_TRUNC }
};
#define NFFLAGS (sizeof(fflags_table) / sizeof(*fflags_table))
+ struct kinfo_file *kif;
struct vnode *vp;
- int error, vfslocked;
+ int error, locked, vfslocked;
unsigned int i;
- if (*remainder == 0)
+ if (efbuf->remainder == 0)
return (0);
+ kif = &efbuf->kif;
bzero(kif, sizeof(*kif));
+ locked = efbuf->fdp != NULL;
switch (type) {
case KF_TYPE_FIFO:
case KF_TYPE_VNODE:
+ if (locked) {
+ FILEDESC_SUNLOCK(efbuf->fdp);
+ locked = 0;
+ }
vp = (struct vnode *)data;
error = fill_vnode_info(vp, kif);
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
@@ -3346,15 +3360,21 @@ export_fd_to_sb(void *data, int type, in
kif->kf_structsize = offsetof(struct kinfo_file, kf_path) +
strlen(kif->kf_path) + 1;
kif->kf_structsize = roundup(kif->kf_structsize, sizeof(uint64_t));
- if (*remainder != -1) {
- if (*remainder < kif->kf_structsize) {
+ if (efbuf->remainder != -1) {
+ if (efbuf->remainder < kif->kf_structsize) {
/* Terminate export. */
- *remainder = 0;
+ efbuf->remainder = 0;
+ if (efbuf->fdp != NULL && !locked)
+ FILEDESC_SLOCK(efbuf->fdp);
return (0);
}
- *remainder -= kif->kf_structsize;
+ efbuf->remainder -= kif->kf_structsize;
}
- error = sbuf_bcat(sb, kif, kif->kf_structsize);
+ if (locked)
+ FILEDESC_SUNLOCK(efbuf->fdp);
+ error = sbuf_bcat(efbuf->sb, kif, kif->kf_structsize);
+ if (efbuf->fdp != NULL)
+ FILEDESC_SLOCK(efbuf->fdp);
return (error);
}
@@ -3368,18 +3388,16 @@ kern_proc_filedesc_out(struct proc *p,
{
struct file *fp;
struct filedesc *fdp;
- struct kinfo_file *kif;
+ struct export_fd_buf *efbuf;
struct vnode *cttyvp, *textvp, *tracevp;
int64_t offset;
void *data;
- ssize_t remainder;
int error, i;
int fd_is_cap, type, refcnt, fflags;
cap_rights_t fd_cap_rights;
PROC_LOCK_ASSERT(p, MA_OWNED);
- remainder = maxlen;
/* ktrace vnode */
tracevp = p->p_tracevp;
if (tracevp != NULL)
@@ -3397,46 +3415,44 @@ kern_proc_filedesc_out(struct proc *p,
}
fdp = fdhold(p);
PROC_UNLOCK(p);
- kif = malloc(sizeof(*kif), M_TEMP, M_WAITOK);
+ efbuf = malloc(sizeof(*efbuf), M_TEMP, M_WAITOK);
+ efbuf->fdp = NULL;
+ efbuf->sb = sb;
+ efbuf->remainder = maxlen;
if (tracevp != NULL)
export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
- FREAD | FWRITE, -1, -1, 0, 0, kif, sb, &remainder);
+ FREAD | FWRITE, -1, -1, 0, 0, efbuf);
if (textvp != NULL)
export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
- FREAD, -1, -1, 0, 0, kif, sb, &remainder);
+ FREAD, -1, -1, 0, 0, efbuf);
if (cttyvp != NULL)
export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
- FREAD | FWRITE, -1, -1, 0, 0, kif, sb, &remainder);
+ FREAD | FWRITE, -1, -1, 0, 0, efbuf);
error = 0;
if (fdp == NULL)
goto fail;
+ efbuf->fdp = fdp;
FILEDESC_SLOCK(fdp);
/* working directory */
if (fdp->fd_cdir != NULL) {
vref(fdp->fd_cdir);
data = fdp->fd_cdir;
- FILEDESC_SUNLOCK(fdp);
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
- FREAD, -1, -1, 0, 0, kif, sb, &remainder);
- FILEDESC_SLOCK(fdp);
+ FREAD, -1, -1, 0, 0, efbuf);
}
/* root directory */
if (fdp->fd_rdir != NULL) {
vref(fdp->fd_rdir);
data = fdp->fd_rdir;
- FILEDESC_SUNLOCK(fdp);
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
- FREAD, -1, -1, 0, 0, kif, sb, &remainder);
- FILEDESC_SLOCK(fdp);
+ FREAD, -1, -1, 0, 0, efbuf);
}
/* jail directory */
if (fdp->fd_jdir != NULL) {
vref(fdp->fd_jdir);
data = fdp->fd_jdir;
- FILEDESC_SUNLOCK(fdp);
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
- FREAD, -1, -1, 0, 0, kif, sb, &remainder);
- FILEDESC_SLOCK(fdp);
+ FREAD, -1, -1, 0, 0, efbuf);
}
for (i = 0; i < fdp->fd_nfiles; i++) {
if ((fp = fdp->fd_ofiles[i]) == NULL)
@@ -3531,20 +3547,15 @@ kern_proc_filedesc_out(struct proc *p,
* re-validate and re-evaluate its properties when
* the loop continues.
*/
- if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
- FILEDESC_SUNLOCK(fdp);
error = export_fd_to_sb(data, type, i, fflags, refcnt,
- offset, fd_is_cap, fd_cap_rights, kif, sb, &remainder);
- if (type == KF_TYPE_VNODE || type == KF_TYPE_FIFO)
- FILEDESC_SLOCK(fdp);
+ offset, fd_is_cap, fd_cap_rights, efbuf);
if (error)
break;
}
FILEDESC_SUNLOCK(fdp);
+ fddrop(fdp);
fail:
- if (fdp != NULL)
- fddrop(fdp);
- free(kif, M_TEMP);
+ free(efbuf, M_TEMP);
return (error);
}
More information about the svn-src-stable-9
mailing list