Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/fs/msdosfs/msdosfs_vnops.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.61.4.6 retrieving revision 1.69 diff -u -p -r1.61.4.6 -r1.69 --- src/sys/fs/msdosfs/msdosfs_vnops.c 2011/05/31 03:04:59 1.61.4.6 +++ src/sys/fs/msdosfs/msdosfs_vnops.c 2010/11/30 10:29:59 1.69 @@ -1,4 +1,4 @@ -/* $NetBSD: msdosfs_vnops.c,v 1.61.4.6 2011/05/31 03:04:59 rmind Exp $ */ +/* $NetBSD: msdosfs_vnops.c,v 1.69 2010/11/30 10:29:59 dholland Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.61.4.6 2011/05/31 03:04:59 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.69 2010/11/30 10:29:59 dholland Exp $"); #include #include @@ -138,6 +138,10 @@ msdosfs_create(void *v) * use the absence of the owner write bit to make the file * readonly. */ +#ifdef DIAGNOSTIC + if ((cnp->cn_flags & HASBUF) == 0) + panic("msdosfs_create: no name"); +#endif memset(&ndirent, 0, sizeof(ndirent)); if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) goto bad; @@ -177,10 +181,10 @@ msdosfs_close(void *v) struct denode *dep = VTODE(vp); fstrans_start(vp->v_mount, FSTRANS_SHARED); - mutex_enter(vp->v_interlock); + mutex_enter(&vp->v_interlock); if (vp->v_usecount > 1) DETIMES(dep, NULL, NULL, NULL, dep->de_pmp->pm_gmtoff); - mutex_exit(vp->v_interlock); + mutex_exit(&vp->v_interlock); fstrans_done(vp->v_mount); return (0); } @@ -554,7 +558,6 @@ msdosfs_write(void *v) u_long count; vsize_t bytelen; off_t oldoff; - size_t rem; struct uio *uio = ap->a_uio; struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); @@ -624,10 +627,6 @@ msdosfs_write(void *v) dep->de_FileSize = uio->uio_offset + resid; /* hint uvm to not read in extended part */ uvm_vnp_setwritesize(vp, dep->de_FileSize); - /* zero out the remainder of the last page */ - rem = round_page(dep->de_FileSize) - dep->de_FileSize; - if (rem > 0) - uvm_vnp_zerorange(vp, (off_t)dep->de_FileSize, rem); extended = 1; } @@ -646,7 +645,7 @@ msdosfs_write(void *v) */ if (!async && oldoff >> 16 != uio->uio_offset >> 16) { - mutex_enter(vp->v_interlock); + mutex_enter(&vp->v_interlock); error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, (uio->uio_offset >> 16) << 16, PGO_CLEANIT); } @@ -655,7 +654,7 @@ msdosfs_write(void *v) /* set final size */ uvm_vnp_setsize(vp, dep->de_FileSize); if (error == 0 && ioflag & IO_SYNC) { - mutex_enter(vp->v_interlock); + mutex_enter(&vp->v_interlock); error = VOP_PUTPAGES(vp, trunc_page(oldoff), round_page(oldoff + bytelen), PGO_CLEANIT | PGO_SYNCIO); } @@ -824,7 +823,7 @@ msdosfs_rename(void *v) struct componentname *tcnp = ap->a_tcnp; struct componentname *fcnp = ap->a_fcnp; struct denode *ip, *xp, *dp, *zp; - u_char toname[12], oldname[12]; + u_char toname[11], oldname[11]; u_long from_diroffset, to_diroffset; u_char to_count; int doingdirectory = 0, newparent = 0; @@ -834,9 +833,15 @@ msdosfs_rename(void *v) struct msdosfsmount *pmp; struct direntry *dotdotp; struct buf *bp; + int fdvp_dorele = 0; pmp = VFSTOMSDOSFS(fdvp->v_mount); +#ifdef DIAGNOSTIC + if ((tcnp->cn_flags & HASBUF) == 0 || + (fcnp->cn_flags & HASBUF) == 0) + panic("msdosfs_rename: no name"); +#endif /* * Check for cross-device rename. */ @@ -926,6 +931,16 @@ abortit: if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) newparent = 1; + /* + * XXX: We can do this here because rename uses SAVEFART and + * therefore fdvp has at least two references (one doesn't + * belong to us, though, and that's evil). We'll get + * another "extra" reference when we do relookup(), so we + * need to compensate. We should *NOT* be doing this, but + * it works, so whatever. + */ + vrele(fdvp); + if (doingdirectory && newparent) { if (error) /* write access check above */ goto tdvpbad; @@ -933,19 +948,22 @@ abortit: vput(tvp); tvp = NULL; /* - * doscheckpath() vput()'s tdvp (dp == VTODE(tdvp)), - * so we have to get an extra ref to it first, and - * because it's been unlocked we need to do a relookup - * afterwards in case tvp has changed. + * doscheckpath() vput()'s dp, + * so we have to do a relookup afterwards */ - vref(tdvp); if ((error = doscheckpath(ip, dp)) != 0) - goto bad; + goto out; + if ((tcnp->cn_flags & SAVESTART) == 0) + panic("msdosfs_rename: lost to startdir"); vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); - if ((error = relookup(tdvp, &tvp, tcnp, 0)) != 0) { + if ((error = relookup(tdvp, &tvp, tcnp)) != 0) { VOP_UNLOCK(tdvp); - goto bad; + goto out; } + /* + * XXX: SAVESTART causes us to get a reference, but + * that's released already above in doscheckpath() + */ dp = VTODE(tdvp); xp = tvp ? VTODE(tvp) : NULL; } @@ -995,9 +1013,11 @@ abortit: */ fcnp->cn_flags &= ~MODMASK; fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; + if ((fcnp->cn_flags & SAVESTART) == 0) + panic("msdosfs_rename: lost from startdir"); VOP_UNLOCK(tdvp); vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); - if ((error = relookup(fdvp, &fvp, fcnp, 0))) { + if ((error = relookup(fdvp, &fvp, fcnp))) { VOP_UNLOCK(fdvp); vrele(ap->a_fvp); vrele(tdvp); @@ -1016,6 +1036,7 @@ abortit: fstrans_done(fdvp->v_mount); return 0; } + fdvp_dorele = 1; VOP_UNLOCK(fdvp); xp = VTODE(fvp); zp = VTODE(fdvp); @@ -1119,8 +1140,10 @@ bad: if (tvp) vput(tvp); vrele(tdvp); +out: ip->de_flag &= ~DE_RENAME; - vrele(fdvp); + if (fdvp_dorele) + vrele(fdvp); vrele(fvp); fstrans_done(fdvp->v_mount); return (error); @@ -1250,6 +1273,10 @@ msdosfs_mkdir(void *v) * cluster. This will be written to an empty slot in the parent * directory. */ +#ifdef DIAGNOSTIC + if ((cnp->cn_flags & HASBUF) == 0) + panic("msdosfs_mkdir: no name"); +#endif if ((error = uniqdosname(pdep, cnp, ndirent.de_Name)) != 0) goto bad; @@ -1800,8 +1827,10 @@ msdosfs_fsync(void *v) fstrans_start(vp->v_mount, FSTRANS_LAZY); wait = (ap->a_flags & FSYNC_WAIT) != 0; - error = vflushbuf(vp, wait); - if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) + vflushbuf(vp, wait); + if ((ap->a_flags & FSYNC_DATAONLY) != 0) + error = 0; + else error = msdosfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); if (error == 0 && ap->a_flags & FSYNC_CACHE) {