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.3 retrieving revision 1.85 diff -u -p -r1.61.4.3 -r1.85 --- src/sys/fs/msdosfs/msdosfs_vnops.c 2010/07/03 01:19:50 1.61.4.3 +++ src/sys/fs/msdosfs/msdosfs_vnops.c 2012/12/28 08:03:59 1.85 @@ -1,4 +1,4 @@ -/* $NetBSD: msdosfs_vnops.c,v 1.61.4.3 2010/07/03 01:19:50 rmind Exp $ */ +/* $NetBSD: msdosfs_vnops.c,v 1.85 2012/12/28 08:03:59 hannken Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.61.4.3 2010/07/03 01:19:50 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.85 2012/12/28 08:03:59 hannken Exp $"); #include #include @@ -99,9 +99,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnop /* * Create a regular file. On entry the directory to contain the file being - * created is locked. We must release before we return. We must also free - * the pathname buffer pointed at by cnp->cn_pnbuf, always on error, or - * only if the SAVESTART bit in cn_flags is clear on success. + * created is locked. We must release before we return. */ int msdosfs_create(void *v) @@ -140,10 +138,6 @@ 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; @@ -159,8 +153,6 @@ msdosfs_create(void *v) DETIMES(&ndirent, NULL, NULL, NULL, pdep->de_pmp->pm_gmtoff); if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) goto bad; - if ((cnp->cn_flags & SAVESTART) == 0) - PNBUF_PUT(cnp->cn_pnbuf); fstrans_done(ap->a_dvp->v_mount); VN_KNOTE(ap->a_dvp, NOTE_WRITE); vput(ap->a_dvp); @@ -169,7 +161,6 @@ msdosfs_create(void *v) bad: fstrans_done(ap->a_dvp->v_mount); - PNBUF_PUT(cnp->cn_pnbuf); vput(ap->a_dvp); return (error); } @@ -230,9 +221,11 @@ msdosfs_check_permitted(struct vnode *vp else file_mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - return genfs_can_access(vp->v_type, - file_mode & (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask), - pmp->pm_uid, pmp->pm_gid, mode, cred); + file_mode &= (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask); + + return kauth_authorize_vnode(cred, kauth_access_action(mode, + vp->v_type, file_mode), vp, NULL, genfs_can_access(vp->v_type, + file_mode, pmp->pm_uid, pmp->pm_gid, mode, cred)); } int @@ -313,8 +306,10 @@ msdosfs_getattr(void *v) vap->va_ctime = vap->va_mtime; } vap->va_flags = 0; - if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) + if ((dep->de_Attributes & ATTR_ARCHIVE) == 0) { + vap->va_flags |= SF_ARCHIVED; vap->va_mode |= S_ARCH1; + } vap->va_gen = 0; vap->va_blocksize = pmp->pm_bpcluster; vap->va_bytes = @@ -358,7 +353,7 @@ msdosfs_setattr(void *v) vap->va_type, vap->va_nlink, vap->va_fsid, (unsigned long long)vap->va_fileid); printf(" va_blocksize %lx, va_rdev %"PRIx64", va_bytes %"PRIx64", va_gen %lx\n", - vap->va_blocksize, vap->va_rdev, (long long)vap->va_bytes, vap->va_gen); + vap->va_blocksize, vap->va_rdev, vap->va_bytes, vap->va_gen); #endif return (EINVAL); } @@ -384,8 +379,9 @@ msdosfs_setattr(void *v) error = EROFS; goto bad; } - error = genfs_can_chtimes(ap->a_vp, vap->va_vaflags, - pmp->pm_uid, cred); + error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_TIMES, + ap->a_vp, NULL, genfs_can_chtimes(ap->a_vp, vap->va_vaflags, + pmp->pm_uid, cred)); if (error) goto bad; if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && @@ -407,9 +403,9 @@ msdosfs_setattr(void *v) error = EROFS; goto bad; } - if (kauth_cred_geteuid(cred) != pmp->pm_uid && - (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, - NULL))) + error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, + NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); + if (error) goto bad; /* We ignore the read and execute bits. */ if (vap->va_mode & S_IWUSR) @@ -427,9 +423,9 @@ msdosfs_setattr(void *v) error = EROFS; goto bad; } - if (kauth_cred_geteuid(cred) != pmp->pm_uid && - (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, - NULL))) + error = kauth_authorize_vnode(cred, KAUTH_VNODE_WRITE_FLAGS, vp, + NULL, genfs_can_chflags(cred, vp->v_type, pmp->pm_uid, false)); + if (error) goto bad; if (vap->va_flags & SF_ARCHIVED) dep->de_Attributes &= ~ATTR_ARCHIVE; @@ -508,8 +504,10 @@ msdosfs_read(void *v) lbn = de_cluster(pmp, uio->uio_offset); on = uio->uio_offset & pmp->pm_crbomask; n = MIN(pmp->pm_bpcluster - on, uio->uio_resid); - if (uio->uio_offset >= dep->de_FileSize) + if (uio->uio_offset >= dep->de_FileSize) { + fstrans_done(vp->v_mount); return (0); + } /* file size (and hence diff) may be up to 4GB */ diff = dep->de_FileSize - uio->uio_offset; if (diff < n) @@ -527,11 +525,10 @@ msdosfs_read(void *v) */ error = bread(pmp->pm_devvp, de_bn2kb(pmp, lbn), blsize, NOCRED, 0, &bp); - n = MIN(n, pmp->pm_bpcluster - bp->b_resid); if (error) { - brelse(bp, 0); goto bad; } + n = MIN(n, pmp->pm_bpcluster - bp->b_resid); error = uiomove((char *)bp->b_data + on, (int) n, uio); brelse(bp, 0); } while (error == 0 && uio->uio_resid > 0 && n != 0); @@ -563,6 +560,7 @@ 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); @@ -632,6 +630,11 @@ 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) + ubc_zerorange(&vp->v_uobj, (off_t)dep->de_FileSize, + rem, UBC_UNMAP_FLAG(vp)); extended = 1; } @@ -652,7 +655,8 @@ msdosfs_write(void *v) if (!async && oldoff >> 16 != uio->uio_offset >> 16) { mutex_enter(vp->v_interlock); error = VOP_PUTPAGES(vp, (oldoff >> 16) << 16, - (uio->uio_offset >> 16) << 16, PGO_CLEANIT); + (uio->uio_offset >> 16) << 16, + PGO_CLEANIT | PGO_LAZY); } } while (error == 0 && uio->uio_resid > 0); @@ -828,7 +832,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[11], oldname[11]; + u_char toname[12], oldname[12]; u_long from_diroffset, to_diroffset; u_char to_count; int doingdirectory = 0, newparent = 0; @@ -838,15 +842,9 @@ 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. */ @@ -936,16 +934,6 @@ 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; @@ -953,22 +941,19 @@ abortit: vput(tvp); tvp = NULL; /* - * doscheckpath() vput()'s dp, - * so we have to do a relookup afterwards + * 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. */ + vref(tdvp); if ((error = doscheckpath(ip, dp)) != 0) - goto out; - if ((tcnp->cn_flags & SAVESTART) == 0) - panic("msdosfs_rename: lost to startdir"); + goto bad; vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); - if ((error = relookup(tdvp, &tvp, tcnp)) != 0) { + if ((error = relookup(tdvp, &tvp, tcnp, 0)) != 0) { VOP_UNLOCK(tdvp); - goto out; + goto bad; } - /* - * XXX: SAVESTART causes us to get a reference, but - * that's released already above in doscheckpath() - */ dp = VTODE(tdvp); xp = tvp ? VTODE(tvp) : NULL; } @@ -1018,11 +1003,9 @@ 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))) { + if ((error = relookup(fdvp, &fvp, fcnp, 0))) { VOP_UNLOCK(fdvp); vrele(ap->a_fvp); vrele(tdvp); @@ -1041,7 +1024,6 @@ abortit: fstrans_done(fdvp->v_mount); return 0; } - fdvp_dorele = 1; VOP_UNLOCK(fdvp); xp = VTODE(fvp); zp = VTODE(fdvp); @@ -1120,7 +1102,6 @@ abortit: pmp->pm_bpcluster, NOCRED, B_MODIFY, &bp); if (error) { /* XXX should really panic here, fs is corrupt */ - brelse(bp, 0); VOP_UNLOCK(fvp); goto bad; } @@ -1145,10 +1126,8 @@ bad: if (tvp) vput(tvp); vrele(tdvp); -out: ip->de_flag &= ~DE_RENAME; - if (fdvp_dorele) - vrele(fdvp); + vrele(fdvp); vrele(fvp); fstrans_done(fdvp->v_mount); return (error); @@ -1278,10 +1257,6 @@ 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; @@ -1292,8 +1267,6 @@ msdosfs_mkdir(void *v) ndirent.de_devvp = pdep->de_devvp; if ((error = createde(&ndirent, pdep, &dep, cnp)) != 0) goto bad; - if ((cnp->cn_flags & SAVESTART) == 0) - PNBUF_PUT(cnp->cn_pnbuf); VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); vput(ap->a_dvp); *ap->a_vpp = DETOV(dep); @@ -1303,7 +1276,6 @@ msdosfs_mkdir(void *v) bad: clusterfree(pmp, newcluster, NULL); bad2: - PNBUF_PUT(cnp->cn_pnbuf); vput(ap->a_dvp); fstrans_done(ap->a_dvp->v_mount); return (error); @@ -1521,7 +1493,6 @@ msdosfs_readdir(void *v) error = bread(pmp->pm_devvp, de_bn2kb(pmp, bn), blsize, NOCRED, 0, &bp); if (error) { - brelse(bp, 0); goto bad; } n = MIN(n, blsize - bp->b_resid); @@ -1805,7 +1776,7 @@ msdosfs_pathconf(void *v) *ap->a_retval = 1; return (0); case _PC_NO_TRUNC: - *ap->a_retval = 0; + *ap->a_retval = 1; return (0); case _PC_SYNC_IO: *ap->a_retval = 1; @@ -1835,10 +1806,8 @@ msdosfs_fsync(void *v) fstrans_start(vp->v_mount, FSTRANS_LAZY); wait = (ap->a_flags & FSYNC_WAIT) != 0; - vflushbuf(vp, wait); - if ((ap->a_flags & FSYNC_DATAONLY) != 0) - error = 0; - else + error = vflushbuf(vp, ap->a_flags); + if (error == 0 && (ap->a_flags & FSYNC_DATAONLY) == 0) error = msdosfs_update(vp, NULL, NULL, wait ? UPDATE_WAIT : 0); if (error == 0 && ap->a_flags & FSYNC_CACHE) {