diff options
Diffstat (limited to 'usr/src')
| -rw-r--r-- | usr/src/uts/common/fs/mntfs/mntvnops.c | 84 | ||||
| -rw-r--r-- | usr/src/uts/common/sys/fs/mntdata.h | 10 |
2 files changed, 73 insertions, 21 deletions
diff --git a/usr/src/uts/common/fs/mntfs/mntvnops.c b/usr/src/uts/common/fs/mntfs/mntvnops.c index dcfce13ab5..33a9561ee2 100644 --- a/usr/src/uts/common/fs/mntfs/mntvnops.c +++ b/usr/src/uts/common/fs/mntfs/mntvnops.c @@ -23,8 +23,6 @@ * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/file.h> #include <sys/stat.h> #include <sys/atomic.h> @@ -722,9 +720,11 @@ mntread(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cred, caller_context_t *ct) size_t len = uio->uio_resid; mntnode_t *mnp = VTOM(vp); char *buf; - mntsnap_t *snap = &mnp->mnt_read; + mntsnap_t *snap; int datamodel; + rw_enter(&mnp->mnt_contents, RW_READER); + snap = &mnp->mnt_read; if (off == (off_t)0 || snap->mnts_count == 0) { /* * It is assumed that any kernel callers wishing @@ -738,17 +738,28 @@ mntread(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cred, caller_context_t *ct) datamodel = DATAMODEL_LP64; else datamodel = get_udatamodel(); - if ((error = mntfs_snapshot(mnp, 1, datamodel)) != 0) + if (!rw_tryupgrade(&mnp->mnt_contents)) { + rw_exit(&mnp->mnt_contents); + rw_enter(&mnp->mnt_contents, RW_WRITER); + } + if ((error = mntfs_snapshot(mnp, 1, datamodel)) != 0) { + rw_exit(&mnp->mnt_contents); return (error); + } + rw_downgrade(&mnp->mnt_contents); } if ((size_t)(off + len) > snap->mnts_textsize) len = snap->mnts_textsize - off; - if (off < 0 || len > snap->mnts_textsize) + if (off < 0 || len > snap->mnts_textsize) { + rw_exit(&mnp->mnt_contents); return (EFAULT); + } - if (len == 0) + if (len == 0) { + rw_exit(&mnp->mnt_contents); return (0); + } /* * The mnttab image is stored in the user's address space, @@ -763,6 +774,7 @@ mntread(vnode_t *vp, uio_t *uio, int ioflag, cred_t *cred, caller_context_t *ct) } kmem_free(buf, len); vfs_mnttab_readop(); + rw_exit(&mnp->mnt_contents); return (error); } @@ -776,9 +788,10 @@ mntgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, vnode_t *rvp; extern timespec_t vfs_mnttab_ctime; mntdata_t *mntdata = MTOD(VTOM(vp)); - mntsnap_t *snap = mnp->mnt_read.mnts_count ? - &mnp->mnt_read : &mnp->mnt_ioctl; + mntsnap_t *snap; + rw_enter(&mnp->mnt_contents, RW_READER); + snap = mnp->mnt_read.mnts_count ? &mnp->mnt_read : &mnp->mnt_ioctl; /* * Return all the attributes. Should be refined * so that it returns only those asked for. @@ -814,6 +827,7 @@ mntgetattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, */ vap->va_size = snap->mnts_textsize ? snap->mnts_textsize : mntdata->mnt_size; + rw_exit(&mnp->mnt_contents); /* * Fetch mtime from the vfs mnttab timestamp */ @@ -859,6 +873,7 @@ mntgetnode(vnode_t *dp) mnp = kmem_zalloc(sizeof (mntnode_t), KM_SLEEP); mnp->mnt_vnode = vn_alloc(KM_SLEEP); mnp->mnt_mountvp = VTOM(dp)->mnt_mountvp; + rw_init(&mnp->mnt_contents, NULL, RW_DEFAULT, NULL); vp = MTOV(mnp); vp->v_flag = VNOCACHE|VNOMAP|VNOSWAP|VNOMOUNT; vn_setops(vp, mntvnodeops); @@ -877,6 +892,7 @@ mntfreenode(mntnode_t *mnp) { vnode_t *vp = MTOV(mnp); + rw_destroy(&mnp->mnt_contents); vn_invalid(vp); vn_free(vp); kmem_free(mnp, sizeof (*mnp)); @@ -904,8 +920,13 @@ static int mntseek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) { - if (*noffp == 0) + mntnode_t *mnp = VTOM(vp); + + if (*noffp == 0) { + rw_enter(&mnp->mnt_contents, RW_WRITER); VTOM(vp)->mnt_offset = 0; + rw_exit(&mnp->mnt_contents); + } return (0); } @@ -921,8 +942,10 @@ mntpoll(vnode_t *vp, short ev, int any, short *revp, pollhead_t **phpp, caller_context_t *ct) { mntnode_t *mnp = VTOM(vp); - mntsnap_t *snap = &mnp->mnt_read; + mntsnap_t *snap; + rw_enter(&mnp->mnt_contents, RW_READER); + snap = &mnp->mnt_read; if (mnp->mnt_ioctl.mnts_time.tv_sec > snap->mnts_time.tv_sec || (mnp->mnt_ioctl.mnts_time.tv_sec == snap->mnts_time.tv_sec && mnp->mnt_ioctl.mnts_time.tv_nsec > snap->mnts_time.tv_nsec)) @@ -941,6 +964,8 @@ mntpoll(vnode_t *vp, short ev, int any, short *revp, pollhead_t **phpp, if (*phpp == (pollhead_t *)NULL) *revp |= POLLRDBAND; } + rw_exit(&mnp->mnt_contents); + if (*revp || *phpp != NULL || any) { return (0); } @@ -960,17 +985,27 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, { uint_t *up = (uint_t *)arg; mntnode_t *mnp = VTOM(vp); - mntsnap_t *snap = &mnp->mnt_ioctl; + mntsnap_t *snap; int error; error = 0; + rw_enter(&mnp->mnt_contents, RW_READER); + snap = &mnp->mnt_ioctl; switch (cmd) { case MNTIOC_NMNTS: { /* get no. of mounted resources */ if (snap->mnts_count == 0) { + if (!rw_tryupgrade(&mnp->mnt_contents)) { + rw_exit(&mnp->mnt_contents); + rw_enter(&mnp->mnt_contents, RW_WRITER); + } if ((error = - mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) != 0) + mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) + != 0) { + rw_exit(&mnp->mnt_contents); return (error); + } + rw_downgrade(&mnp->mnt_contents); } if (suword32(up, snap->mnts_count) != 0) error = EFAULT; @@ -983,9 +1018,17 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, size_t len; if (snap->mnts_count == 0) { + if (!rw_tryupgrade(&mnp->mnt_contents)) { + rw_exit(&mnp->mnt_contents); + rw_enter(&mnp->mnt_contents, RW_WRITER); + } if ((error = - mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) != 0) + mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) + != 0) { + rw_exit(&mnp->mnt_contents); return (error); + } + rw_downgrade(&mnp->mnt_contents); } len = 2 * snap->mnts_count * sizeof (uint_t); @@ -1090,11 +1133,18 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, size_t idx; uintptr_t addr; + if (!rw_tryupgrade(&mnp->mnt_contents)) { + rw_exit(&mnp->mnt_contents); + rw_enter(&mnp->mnt_contents, RW_WRITER); + } idx = mnp->mnt_offset; if (snap->mnts_count == 0 || idx == 0) { if ((error = - mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) != 0) + mntfs_snapshot(mnp, 0, flag & DATAMODEL_MASK)) + != 0) { + rw_exit(&mnp->mnt_contents); return (error); + } } /* * If the next index is beyond the end of the current mnttab, @@ -1102,6 +1152,7 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, */ if (idx >= snap->mnts_count) { *rvalp = 1; + rw_exit(&mnp->mnt_contents); return (0); } @@ -1119,8 +1170,10 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, } #endif - if (error != 0) + if (error != 0) { + rw_exit(&mnp->mnt_contents); return (error); + } mnp->mnt_offset++; break; @@ -1131,6 +1184,7 @@ mntioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, break; } + rw_exit(&mnp->mnt_contents); return (error); } diff --git a/usr/src/uts/common/sys/fs/mntdata.h b/usr/src/uts/common/sys/fs/mntdata.h index d15c64d1b4..1536b6c712 100644 --- a/usr/src/uts/common/sys/fs/mntdata.h +++ b/usr/src/uts/common/sys/fs/mntdata.h @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * 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. @@ -20,15 +19,13 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _SYS_MNTFS_MNTDATA_H #define _SYS_MNTFS_MNTDATA_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/vnode.h> #include <sys/poll.h> @@ -52,6 +49,7 @@ typedef struct mntnode { mntsnap_t mnt_read; /* Data for read() */ mntsnap_t mnt_ioctl; /* Data for ioctl() */ uint_t mnt_offset; /* offset within ioctl() snapshot */ + krwlock_t mnt_contents; /* protects mnt_read, mnt_ioctl, mnt_offset */ } mntnode_t; struct zone; |
