From: Matthew Dillon Date: Sat, 19 Aug 2006 17:27:25 +0000 (+0000) Subject: VNode sequencing and locking - part 4/4 - subpart 1 of many. X-Git-Tag: v2.0.1~4513 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/885ecb13c6155e9cc7d79ce185ad65c4efdb6aa5?hp=87884535f830fdda0318c97049c7eb85b5e7c1be VNode sequencing and locking - part 4/4 - subpart 1 of many. Move the vnode lock for VOP_READDIR out of the kernel upper layers and into the filesystem. --- diff --git a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c index e87b5e5787..1acb49b5bf 100644 --- a/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c +++ b/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c @@ -39,7 +39,7 @@ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/i386/linux/linprocfs/linprocfs_vnops.c,v 1.3.2.5 2001/08/12 14:29:19 rwatson Exp $ - * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.33 2006/08/12 00:26:19 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/i386/linprocfs/linprocfs_vnops.c,v 1.34 2006/08/19 17:27:22 dillon Exp $ */ /* @@ -788,31 +788,31 @@ linprocfs_readdir(struct vop_readdir_args *ap) return (EINVAL); pfs = VTOPFS(ap->a_vp); + if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); switch (pfs->pfs_type) { - /* - * this is for the process-specific sub-directories. - * all that is needed to is copy out all the entries - * from the procent[] table (top of this file). - */ case Pproc: + /* + * This is for the process-specific sub-directories. + * all that is needed to is copy out all the entries + * from the procent[] table (top of this file). + */ error = linprocfs_readdir_proc(ap); break; - - /* - * this is for the root of the procfs filesystem - * what is needed is a special entry for "self" - * followed by an entry for each process on allproc - */ - case Proot: + /* + * This is for the root of the procfs filesystem + * what is needed is a special entry for "self" + * followed by an entry for each process on allproc + */ error = linprocfs_readdir_root(ap); break; - default: error = ENOTDIR; break; } + vn_unlock(ap->a_vp); return (error); } diff --git a/sys/emulation/linux/linux_file.c b/sys/emulation/linux/linux_file.c index 48fc75943c..1a5d021a8a 100644 --- a/sys/emulation/linux/linux_file.c +++ b/sys/emulation/linux/linux_file.c @@ -26,7 +26,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/compat/linux/linux_file.c,v 1.41.2.6 2003/01/06 09:19:43 fjoe Exp $ - * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.34 2006/08/12 00:26:19 dillon Exp $ + * $DragonFly: src/sys/emulation/linux/linux_file.c,v 1.35 2006/08/19 17:27:20 dillon Exp $ */ #include "opt_compat.h" @@ -296,7 +296,6 @@ getdents_common(struct linux_getdents64_args *args, int is64bit) buflen = max(LINUX_DIRBLKSIZ, nbytes); buflen = min(buflen, MAXBSIZE); buf = malloc(buflen, M_TEMP, M_WAITOK); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); again: aiov.iov_base = buf; @@ -435,7 +434,6 @@ out: if (cookies) free(cookies, M_TEMP); - vn_unlock(vp); free(buf, M_TEMP); done: fdrop(fp); diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index 8fbf6bc2b8..68cda72d3c 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -67,7 +67,7 @@ * * @(#)vfs_cache.c 8.5 (Berkeley) 3/22/95 * $FreeBSD: src/sys/kern/vfs_cache.c,v 1.42.2.6 2001/10/05 20:07:03 dillon Exp $ - * $DragonFly: src/sys/kern/vfs_cache.c,v 1.74 2006/08/12 00:26:20 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_cache.c,v 1.75 2006/08/19 17:27:23 dillon Exp $ */ #include @@ -1238,7 +1238,7 @@ cache_inefficient_scan(struct namecache *ncp, struct ucred *cred, vat.va_blocksize = 0; if ((error = VOP_GETATTR(dvp, &vat)) != 0) return (error); - if ((error = cache_vget(ncp, cred, LK_SHARED, &pvp)) != 0) + if ((error = cache_vref(ncp, cred, &pvp)) != 0) return (error); if (ncvp_debug) printf("inefficient_scan: directory iosize %ld vattr fileid = %ld\n", vat.va_blocksize, (long)vat.va_fileid); @@ -1283,7 +1283,6 @@ again: } nlc.nlc_nameptr = den->d_name; nlc.nlc_namelen = den->d_namlen; - vn_unlock(pvp); rncp = cache_nlookup(ncp, &nlc); KKASSERT(rncp != NULL); break; @@ -1294,8 +1293,8 @@ again: if (rncp == NULL && eofflag == 0 && uio.uio_resid != blksize) goto again; } + vrele(pvp); if (rncp) { - vrele(pvp); if (rncp->nc_flag & NCF_UNRESOLVED) { cache_setvp(rncp, dvp); if (ncvp_debug >= 2) { @@ -1315,7 +1314,6 @@ again: } else { printf("cache_inefficient_scan: dvp %p NOT FOUND in %s\n", dvp, ncp->nc_name); - vput(pvp); error = ENOENT; } free(rbuf, M_TEMP); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 9b86e84d2b..24bf88d434 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -37,7 +37,7 @@ * * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 * $FreeBSD: src/sys/kern/vfs_syscalls.c,v 1.151.2.18 2003/04/04 20:35:58 tegge Exp $ - * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.100 2006/08/12 00:26:20 dillon Exp $ + * $DragonFly: src/sys/kern/vfs_syscalls.c,v 1.101 2006/08/19 17:27:23 dillon Exp $ */ #include @@ -2951,12 +2951,9 @@ unionread: auio.uio_segflg = direction; auio.uio_td = td; auio.uio_resid = count; - /* vn_lock(vp, LK_SHARED | LK_RETRY); */ - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); loff = auio.uio_offset = fp->f_offset; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); fp->f_offset = auio.uio_offset; - vn_unlock(vp); if (error) goto done; if (count == auio.uio_resid) { diff --git a/sys/vfs/gnu/ext2fs/ext2_lookup.c b/sys/vfs/gnu/ext2fs/ext2_lookup.c index fd42278bad..6e30176c1e 100644 --- a/sys/vfs/gnu/ext2fs/ext2_lookup.c +++ b/sys/vfs/gnu/ext2fs/ext2_lookup.c @@ -5,7 +5,7 @@ * University of Utah, Department of Computer Science * * $FreeBSD: src/sys/gnu/ext2fs/ext2_lookup.c,v 1.21.2.3 2002/11/17 02:02:42 bde Exp $ - * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v 1.24 2006/08/12 00:26:20 dillon Exp $ + * $DragonFly: src/sys/vfs/gnu/ext2fs/ext2_lookup.c,v 1.25 2006/08/19 17:27:24 dillon Exp $ */ /* * Copyright (c) 1989, 1993 @@ -137,7 +137,6 @@ ext2_readdir(struct vop_readdir_args *ap) { struct uio *uio = ap->a_uio; int count, error; - struct ext2_dir_entry_2 *edp, *dp; int ncookies; struct uio auio; @@ -147,6 +146,9 @@ ext2_readdir(struct vop_readdir_args *ap) int readcnt, retval; off_t startoffset = uio->uio_offset; + if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return(error); + count = uio->uio_resid; /* * Avoid complications for partial directory entries by adjusting @@ -244,6 +246,7 @@ ext2_readdir(struct vop_readdir_args *ap) FREE(dirbuf, M_TEMP); if (ap->a_eofflag) *ap->a_eofflag = VTOI(ap->a_vp)->i_size <= uio->uio_offset; + vn_unlock(ap->a_vp); return (error); } diff --git a/sys/vfs/hpfs/hpfs_vnops.c b/sys/vfs/hpfs/hpfs_vnops.c index fd23e4941a..76f6aa6cda 100644 --- a/sys/vfs/hpfs/hpfs_vnops.c +++ b/sys/vfs/hpfs/hpfs_vnops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/hpfs/hpfs_vnops.c,v 1.2.2.2 2002/01/15 18:35:09 semenu Exp $ - * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.37 2006/08/12 00:26:20 dillon Exp $ + * $DragonFly: src/sys/vfs/hpfs/hpfs_vnops.c,v 1.38 2006/08/19 17:27:24 dillon Exp $ */ #include @@ -848,16 +848,18 @@ hpfs_readdir(struct vop_readdir_args *ap) */ if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return(EINVAL); + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); + num = uio->uio_offset; cnum = 0; if( num <= cnum ) { dprintf((". faked, ")); if (vop_write_dirent(&error, uio, hp->h_no, DT_DIR, 1, ".")) - return (0); - if(error) - return (error); - + goto done; + if (error) + goto done; ncookies ++; } cnum++; @@ -866,9 +868,8 @@ hpfs_readdir(struct vop_readdir_args *ap) dprintf((".. faked, ")); if (vop_write_dirent(&error, uio, hp->h_fn.fn_parent, DT_DIR, 2, "..")) goto readdone; - if(error) - return (error); - + if (error) + goto done; ncookies ++; } cnum++; @@ -883,14 +884,15 @@ dive: error = bread(hp->h_devvp, dbtodoff(lsn), D_BSIZE, &bp); if (error) { brelse(bp); - return (error); + goto done; } dp = (struct dirblk *) bp->b_data; if (dp->d_magic != D_MAGIC) { printf("hpfs_readdir: MAGIC DOESN'T MATCH\n"); brelse(bp); - return (EINVAL); + error = EINVAL; + goto done; } dep = D_DIRENT(dp); @@ -918,7 +920,7 @@ dive: } if (error) { brelse (bp); - return (error); + goto done; } ncookies++; } @@ -929,7 +931,8 @@ dive: } else { printf("hpfs_readdir: ERROR! oLSN not found\n"); brelse(bp); - return (EINVAL); + error = EINVAL; + goto done; } } @@ -952,7 +955,7 @@ dive: } if (error) { brelse (bp); - return (error); + goto done; } ncookies++; } @@ -1016,7 +1019,9 @@ readdone: *ap->a_cookies = cookies; } - return (0); +done: + vn_unlock(ap->a_vp); + return (error); } /* diff --git a/sys/vfs/isofs/cd9660/cd9660_vnops.c b/sys/vfs/isofs/cd9660/cd9660_vnops.c index 65ae8bdf7c..14087f141d 100644 --- a/sys/vfs/isofs/cd9660/cd9660_vnops.c +++ b/sys/vfs/isofs/cd9660/cd9660_vnops.c @@ -37,7 +37,7 @@ * * @(#)cd9660_vnops.c 8.19 (Berkeley) 5/27/95 * $FreeBSD: src/sys/isofs/cd9660/cd9660_vnops.c,v 1.62 1999/12/15 23:01:51 eivind Exp $ - * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vnops.c,v 1.30 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/isofs/cd9660/cd9660_vnops.c,v 1.31 2006/08/19 17:27:24 dillon Exp $ */ #include @@ -481,6 +481,9 @@ cd9660_readdir(struct vop_readdir_args *ap) imp = dp->i_mnt; bmask = imp->im_bmask; + if ((error = vn_lock(vdp, LK_EXCLUSIVE|LK_RETRY)) != 0) + return (error); + MALLOC(idp, struct isoreaddir *, sizeof(*idp), M_TEMP, M_WAITOK); idp->saveent.de.d_namlen = idp->assocent.de.d_namlen = 0; /* @@ -513,7 +516,7 @@ cd9660_readdir(struct vop_readdir_args *ap) if ((entryoffsetinblock = idp->curroff & bmask) && (error = cd9660_devblkatoff(vdp, (off_t)idp->curroff, NULL, &bp))) { FREE(idp, M_TEMP); - return (error); + goto done; } endsearch = dp->i_size; @@ -639,6 +642,8 @@ cd9660_readdir(struct vop_readdir_args *ap) FREE(idp, M_TEMP); +done: + vn_unlock(vdp); return (error); } diff --git a/sys/vfs/msdosfs/msdosfs_vnops.c b/sys/vfs/msdosfs/msdosfs_vnops.c index 0d927fbb2e..ed5b5916ad 100644 --- a/sys/vfs/msdosfs/msdosfs_vnops.c +++ b/sys/vfs/msdosfs/msdosfs_vnops.c @@ -1,5 +1,5 @@ /* $FreeBSD: src/sys/msdosfs/msdosfs_vnops.c,v 1.95.2.4 2003/06/13 15:05:47 trhodes Exp $ */ -/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.40 2006/08/12 00:26:21 dillon Exp $ */ +/* $DragonFly: src/sys/vfs/msdosfs/msdosfs_vnops.c,v 1.41 2006/08/19 17:27:24 dillon Exp $ */ /* $NetBSD: msdosfs_vnops.c,v 1.68 1998/02/10 14:10:04 mrg Exp $ */ /*- @@ -1557,8 +1557,8 @@ msdosfs_readdir(struct vop_readdir_args *ap) long bias = 0; daddr_t bn, lbn; struct buf *bp; - struct denode *dep = VTODE(ap->a_vp); - struct msdosfsmount *pmp = dep->de_pmp; + struct denode *dep; + struct msdosfsmount *pmp; struct direntry *dentp; struct uio *uio = ap->a_uio; u_long *cookies = NULL; @@ -1571,6 +1571,12 @@ msdosfs_readdir(struct vop_readdir_args *ap) char *d_name_storage = NULL; char *d_name; + if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); + + dep = VTODE(ap->a_vp); + pmp = dep->de_pmp; + #ifdef MSDOSFS_DEBUG printf("msdosfs_readdir(): vp %p, uio %p, cred %p, eofflagp %p\n", ap->a_vp, uio, ap->a_cred, ap->a_eofflag); @@ -1582,8 +1588,10 @@ msdosfs_readdir(struct vop_readdir_args *ap) * retrieve the wrong block from the buffer cache for a plain file. * So, fail attempts to readdir() on a plain file. */ - if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) - return (ENOTDIR); + if ((dep->de_Attributes & ATTR_DIRECTORY) == 0) { + error = ENOTDIR; + goto done; + } /* * If the user buffer is smaller than the size of one dos directory @@ -1592,8 +1600,10 @@ msdosfs_readdir(struct vop_readdir_args *ap) */ off = offset = uio->uio_offset; if (uio->uio_resid < sizeof(struct direntry) || - (offset & (sizeof(struct direntry) - 1))) - return (EINVAL); + (offset & (sizeof(struct direntry) - 1))) { + error = EINVAL; + goto done; + } if (ap->a_ncookies) { ncookies = uio->uio_resid / 16 + 1; @@ -1671,7 +1681,7 @@ msdosfs_readdir(struct vop_readdir_args *ap) if (error) { brelse(bp); free(d_name_storage, M_TEMP); - return (error); + goto done; } n = min(n, blsize - bp->b_resid); @@ -1796,6 +1806,8 @@ out: else *ap->a_eofflag = 0; } +done: + vn_unlock(ap->a_vp); return (error); } diff --git a/sys/vfs/nfs/nfs_serv.c b/sys/vfs/nfs/nfs_serv.c index 884245bc1a..7fad6875ad 100644 --- a/sys/vfs/nfs/nfs_serv.c +++ b/sys/vfs/nfs/nfs_serv.c @@ -35,7 +35,7 @@ * * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95 * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.37 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.38 2006/08/19 17:27:24 dillon Exp $ */ /* @@ -2869,7 +2869,6 @@ again: io.uio_rw = UIO_READ; io.uio_td = NULL; eofflag = 0; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (cookies) { free((caddr_t)cookies, M_TEMP); cookies = NULL; @@ -2883,7 +2882,6 @@ again: if (!error) error = getret; } - vn_unlock(vp); if (error) { vrele(vp); vp = NULL; @@ -3146,7 +3144,6 @@ again: io.uio_rw = UIO_READ; io.uio_td = NULL; eofflag = 0; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); if (cookies) { free((caddr_t)cookies, M_TEMP); cookies = NULL; @@ -3154,7 +3151,6 @@ again: error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); off = (u_quad_t)io.uio_offset; getret = VOP_GETATTR(vp, &at); - vn_unlock(vp); if (!cookies && !error) error = NFSERR_PERM; if (!error) diff --git a/sys/vfs/nfs/nfs_vnops.c b/sys/vfs/nfs/nfs_vnops.c index 1e52afc755..197391f506 100644 --- a/sys/vfs/nfs/nfs_vnops.c +++ b/sys/vfs/nfs/nfs_vnops.c @@ -35,7 +35,7 @@ * * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $ - * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.64 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.65 2006/08/19 17:27:24 dillon Exp $ */ @@ -2091,6 +2091,9 @@ nfs_readdir(struct vop_readdir_args *ap) if (vp->v_type != VDIR) return (EPERM); + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); + /* * If we have a valid EOF offset cache we must call VOP_GETATTR() * and then check that is still valid, or if this is an NQNFS mount @@ -2103,7 +2106,7 @@ nfs_readdir(struct vop_readdir_args *ap) (np->n_flag & (NLMODIFIED|NRMODIFIED)) == 0 ) { nfsstats.direofcache_hits++; - return (0); + goto done; } } @@ -2116,6 +2119,8 @@ nfs_readdir(struct vop_readdir_args *ap) if (!error && uio->uio_resid == tresid) nfsstats.direofcache_misses++; +done: + vn_unlock(vp); return (error); } diff --git a/sys/vfs/ntfs/ntfs_vnops.c b/sys/vfs/ntfs/ntfs_vnops.c index 38e4b90d35..f5b15a9615 100644 --- a/sys/vfs/ntfs/ntfs_vnops.c +++ b/sys/vfs/ntfs/ntfs_vnops.c @@ -36,7 +36,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/ntfs/ntfs_vnops.c,v 1.9.2.4 2002/08/06 19:35:18 semenu Exp $ - * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.36 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/ntfs/ntfs_vnops.c,v 1.37 2006/08/19 17:27:24 dillon Exp $ * */ @@ -570,6 +570,8 @@ ntfs_readdir(struct vop_readdir_args *ap) if (uio->uio_offset < 0 || uio->uio_offset > INT_MAX) return (EINVAL); + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); /* * uio->uio_offset carries the number of the entry @@ -589,9 +591,9 @@ ntfs_readdir(struct vop_readdir_args *ap) if (ip->i_number != NTFS_ROOTINO && num == 0) { if (vop_write_dirent(&error, uio, ip->i_number, DT_DIR, 1, ".")) - return (0); + goto done; if (error) - return (error); + goto done; num++; ncookies++; @@ -603,8 +605,8 @@ ntfs_readdir(struct vop_readdir_args *ap) if (vop_write_dirent(&error, uio, NTFS_ROOTINO, DT_DIR, 2, "..")) goto readdone; - if(error) - return (error); + if (error) + goto done; num++; ncookies++; @@ -621,8 +623,8 @@ ntfs_readdir(struct vop_readdir_args *ap) */ error = ntfs_ntreaddir(ntmp, fp, num - faked, &iep); - if(error) - return (error); + if (error) + goto done; if( NULL == iep ) break; @@ -649,8 +651,8 @@ ntfs_readdir(struct vop_readdir_args *ap) (iep->ie_fflag & NTFS_FFLAG_DIR) ? "dir" : "reg")); - if(error) - return (error); + if (error) + goto done; ncookies++; num++; @@ -693,8 +695,10 @@ readdone: } /* if (ap->a_eofflag) - *ap->a_eofflag = VTONT(ap->a_vp)->i_size <= uio->uio_offset; + *ap->a_eofflag = VTONT(vp)->i_size <= uio->uio_offset; */ +done: + vn_unlock(vp); return (error); } diff --git a/sys/vfs/nwfs/nwfs_vnops.c b/sys/vfs/nwfs/nwfs_vnops.c index f179486747..fdfb8ff328 100644 --- a/sys/vfs/nwfs/nwfs_vnops.c +++ b/sys/vfs/nwfs/nwfs_vnops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/nwfs/nwfs_vnops.c,v 1.6.2.3 2001/03/14 11:26:59 bp Exp $ - * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.32 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/nwfs/nwfs_vnops.c,v 1.33 2006/08/19 17:27:24 dillon Exp $ */ #include #include @@ -677,8 +677,10 @@ nwfs_readdir(struct vop_readdir_args *ap) printf("nwfs_readdir: no support for cookies now..."); return (EOPNOTSUPP); } - + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); error = nwfs_readvnode(vp, uio, ap->a_cred); + vn_unlock(vp); return error; } diff --git a/sys/vfs/procfs/procfs_vnops.c b/sys/vfs/procfs/procfs_vnops.c index a3f56ce651..c9d8ca2fa8 100644 --- a/sys/vfs/procfs/procfs_vnops.c +++ b/sys/vfs/procfs/procfs_vnops.c @@ -37,7 +37,7 @@ * @(#)procfs_vnops.c 8.18 (Berkeley) 5/21/95 * * $FreeBSD: src/sys/miscfs/procfs/procfs_vnops.c,v 1.76.2.7 2002/01/22 17:22:59 nectar Exp $ - * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.35 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/procfs/procfs_vnops.c,v 1.36 2006/08/19 17:27:24 dillon Exp $ */ /* @@ -832,34 +832,33 @@ procfs_readdir(struct vop_readdir_args *ap) if (ap->a_uio->uio_offset < 0 || ap->a_uio->uio_offset > INT_MAX) return (EINVAL); - + if ((error = vn_lock(ap->a_vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); pfs = VTOPFS(ap->a_vp); switch (pfs->pfs_type) { - /* - * this is for the process-specific sub-directories. - * all that is needed to is copy out all the entries - * from the procent[] table (top of this file). - */ case Pproc: + /* + * this is for the process-specific sub-directories. + * all that is needed to is copy out all the entries + * from the procent[] table (top of this file). + */ error = procfs_readdir_proc(ap); break; - - /* - * this is for the root of the procfs filesystem - * what is needed is a special entry for "curproc" - * followed by an entry for each process on allproc - */ - case Proot: + /* + * this is for the root of the procfs filesystem + * what is needed is a special entry for "curproc" + * followed by an entry for each process on allproc + */ error = procfs_readdir_root(ap); break; - default: error = ENOTDIR; break; } + vn_unlock(ap->a_vp); return (error); } diff --git a/sys/vfs/smbfs/smbfs_vnops.c b/sys/vfs/smbfs/smbfs_vnops.c index 257d4f9571..a58ad26894 100644 --- a/sys/vfs/smbfs/smbfs_vnops.c +++ b/sys/vfs/smbfs/smbfs_vnops.c @@ -30,7 +30,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/smbfs/smbfs_vnops.c,v 1.2.2.8 2003/04/04 08:57:23 tjr Exp $ - * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.34 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/smbfs/smbfs_vnops.c,v 1.35 2006/08/19 17:27:24 dillon Exp $ */ #include #include @@ -726,7 +726,10 @@ smbfs_readdir(struct vop_readdir_args *ap) return (EOPNOTSUPP); } #endif - error = smbfs_readvnode(vp, uio, ap->a_cred); + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) == 0) { + error = smbfs_readvnode(vp, uio, ap->a_cred); + vn_unlock(vp); + } return error; } diff --git a/sys/vfs/udf/udf_vnops.c b/sys/vfs/udf/udf_vnops.c index d17f083a82..c3ccef6de2 100644 --- a/sys/vfs/udf/udf_vnops.c +++ b/sys/vfs/udf/udf_vnops.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/fs/udf/udf_vnops.c,v 1.33 2003/12/07 05:04:49 scottl Exp $ - * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.24 2006/08/12 00:26:21 dillon Exp $ + * $DragonFly: src/sys/vfs/udf/udf_vnops.c,v 1.25 2006/08/19 17:27:25 dillon Exp $ */ /* udf_vnops.c */ @@ -696,6 +696,10 @@ udf_readdir(struct vop_readdir_args *a) char *name; vp = a->a_vp; + + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); + uio = a->a_uio; node = VTON(vp); udfmp = node->udfmp; @@ -826,6 +830,7 @@ udf_readdir(struct vop_readdir_args *a) } } + vn_unlock(vp); return(error); } diff --git a/sys/vfs/ufs/ufs_vnops.c b/sys/vfs/ufs/ufs_vnops.c index 57d915bf03..c25033060b 100644 --- a/sys/vfs/ufs/ufs_vnops.c +++ b/sys/vfs/ufs/ufs_vnops.c @@ -37,7 +37,7 @@ * * @(#)ufs_vnops.c 8.27 (Berkeley) 5/27/95 * $FreeBSD: src/sys/ufs/ufs/ufs_vnops.c,v 1.131.2.8 2003/01/02 17:26:19 bde Exp $ - * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.54 2006/08/12 00:26:22 dillon Exp $ + * $DragonFly: src/sys/vfs/ufs/ufs_vnops.c,v 1.55 2006/08/19 17:27:25 dillon Exp $ */ #include "opt_quota.h" @@ -1674,6 +1674,9 @@ ufs_readdir(struct vop_readdir_args *ap) } cookie_index = 0; + if ((error = vn_lock(vp, LK_EXCLUSIVE | LK_RETRY)) != 0) + return (error); + /* * Past or at EOF */ @@ -1684,7 +1687,7 @@ ufs_readdir(struct vop_readdir_args *ap) *ap->a_ncookies = cookie_index; *ap->a_cookies = cookies; } - return(0); + goto done; } /* @@ -1773,6 +1776,8 @@ ufs_readdir(struct vop_readdir_args *ap) *ap->a_cookies = cookies; } } +done: + vn_unlock(vp); return (error); } diff --git a/sys/vfs/union/union_vnops.c b/sys/vfs/union/union_vnops.c index 5d9c696ef8..502d7aab95 100644 --- a/sys/vfs/union/union_vnops.c +++ b/sys/vfs/union/union_vnops.c @@ -36,7 +36,7 @@ * * @(#)union_vnops.c 8.32 (Berkeley) 6/23/95 * $FreeBSD: src/sys/miscfs/union/union_vnops.c,v 1.72 1999/12/15 23:02:14 eivind Exp $ - * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.33 2006/08/12 00:26:22 dillon Exp $ + * $DragonFly: src/sys/vfs/union/union_vnops.c,v 1.34 2006/08/19 17:27:25 dillon Exp $ */ #include @@ -119,6 +119,22 @@ union_lock_upper(struct union_node *un, struct thread *td) return(uppervp); } +static __inline +struct vnode * +union_ref_upper(struct union_node *un) +{ + struct vnode *uppervp; + + if ((uppervp = un->un_uppervp) != NULL) { + vref(uppervp); + if (uppervp->v_flag & VRECLAIMED) { + vrele(uppervp); + return (NULLVP); + } + } + return (uppervp); +} + static __inline void union_unlock_upper(struct vnode *uppervp, struct thread *td) @@ -1567,11 +1583,11 @@ union_readdir(struct vop_readdir_args *ap) struct vnode *uvp; int error = 0; - if ((uvp = union_lock_upper(un, td)) != NULLVP) { + if ((uvp = union_ref_upper(un)) != NULLVP) { ap->a_head.a_ops = *uvp->v_ops; ap->a_vp = uvp; error = vop_readdir_ap(ap); - union_unlock_upper(uvp, td); + vrele(uvp); } return(error); }