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.52.10.2 retrieving revision 1.61.4.3 diff -u -p -r1.52.10.2 -r1.61.4.3 --- src/sys/fs/msdosfs/msdosfs_vnops.c 2008/11/09 02:05:20 1.52.10.2 +++ src/sys/fs/msdosfs/msdosfs_vnops.c 2010/07/03 01:19:50 1.61.4.3 @@ -1,4 +1,4 @@ -/* $NetBSD: msdosfs_vnops.c,v 1.52.10.2 2008/11/09 02:05:20 christos Exp $ */ +/* $NetBSD: msdosfs_vnops.c,v 1.61.4.3 2010/07/03 01:19:50 rmind Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -48,7 +48,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.52.10.2 2008/11/09 02:05:20 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: msdosfs_vnops.c,v 1.61.4.3 2010/07/03 01:19:50 rmind Exp $"); #include #include @@ -60,6 +60,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnop #include #include #include +#include #include #include #include @@ -103,8 +104,7 @@ __KERNEL_RCSID(0, "$NetBSD: msdosfs_vnop * only if the SAVESTART bit in cn_flags is clear on success. */ int -msdosfs_create(v) - void *v; +msdosfs_create(void *v) { struct vop_create_args /* { struct vnode *a_dvp; @@ -122,6 +122,7 @@ msdosfs_create(v) printf("msdosfs_create(cnp %p, vap %p\n", cnp, ap->a_vap); #endif + fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); /* * If this is the root directory and there is no space left we * can't do anything. This is because the root directory can not @@ -160,50 +161,21 @@ msdosfs_create(v) 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); *ap->a_vpp = DETOV(dep); return (0); bad: + fstrans_done(ap->a_dvp->v_mount); PNBUF_PUT(cnp->cn_pnbuf); vput(ap->a_dvp); return (error); } int -msdosfs_mknod(v) - void *v; -{ - struct vop_mknod_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - } */ *ap = v; - - PNBUF_PUT(ap->a_cnp->cn_pnbuf); - vput(ap->a_dvp); - return (EINVAL); -} - -int -msdosfs_open(void *v) -{ -#if 0 - struct vop_open_args /* { - struct vnode *a_vp; - int a_mode; - kauth_cred_t a_cred; - } */ *ap; -#endif - - return (0); -} - -int -msdosfs_close(v) - void *v; +msdosfs_close(void *v) { struct vop_close_args /* { struct vnode *a_vp; @@ -213,26 +185,18 @@ msdosfs_close(v) struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); - mutex_enter(&vp->v_interlock); + fstrans_start(vp->v_mount, FSTRANS_SHARED); + 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); } -int -msdosfs_access(v) - void *v; +static int +msdosfs_check_possible(struct vnode *vp, struct denode *dep, mode_t mode) { - struct vop_access_args /* { - struct vnode *a_vp; - int a_mode; - kauth_cred_t a_cred; - } */ *ap = v; - struct vnode *vp = ap->a_vp; - struct denode *dep = VTODE(vp); - struct msdosfsmount *pmp = dep->de_pmp; - mode_t mode = ap->a_mode; /* * Disallow write attempts on read-only file systems; @@ -251,18 +215,49 @@ msdosfs_access(v) } } + return 0; +} + +static int +msdosfs_check_permitted(struct vnode *vp, struct denode *dep, mode_t mode, + kauth_cred_t cred) +{ + struct msdosfsmount *pmp = dep->de_pmp; + mode_t file_mode; + if ((dep->de_Attributes & ATTR_READONLY) == 0) - mode = S_IRWXU|S_IRWXG|S_IRWXO; + file_mode = S_IRWXU|S_IRWXG|S_IRWXO; else - mode = S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH; - return (vaccess(ap->a_vp->v_type, - mode & (vp->v_type == VDIR ? pmp->pm_dirmask : pmp->pm_mask), - pmp->pm_uid, pmp->pm_gid, ap->a_mode, ap->a_cred)); + 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); +} + +int +msdosfs_access(void *v) +{ + struct vop_access_args /* { + struct vnode *a_vp; + int a_mode; + kauth_cred_t a_cred; + } */ *ap = v; + struct vnode *vp = ap->a_vp; + struct denode *dep = VTODE(vp); + int error; + + error = msdosfs_check_possible(vp, dep, ap->a_mode); + if (error) + return error; + + error = msdosfs_check_permitted(vp, dep, ap->a_mode, ap->a_cred); + + return error; } int -msdosfs_getattr(v) - void *v; +msdosfs_getattr(void *v) { struct vop_getattr_args /* { struct vnode *a_vp; @@ -276,6 +271,7 @@ msdosfs_getattr(v) u_long dirsperblk = pmp->pm_BytesPerSec / sizeof(struct direntry); ino_t fileid; + fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); DETIMES(dep, NULL, NULL, NULL, pmp->pm_gmtoff); vap->va_fsid = dep->de_dev; /* @@ -324,12 +320,12 @@ msdosfs_getattr(v) vap->va_bytes = (dep->de_FileSize + pmp->pm_crbomask) & ~pmp->pm_crbomask; vap->va_type = ap->a_vp->v_type; + fstrans_done(ap->a_vp->v_mount); return (0); } int -msdosfs_setattr(v) - void *v; +msdosfs_setattr(void *v) { struct vop_setattr_args /* { struct vnode *a_vp; @@ -358,10 +354,10 @@ msdosfs_setattr(v) (vap->va_gid != VNOVAL && vap->va_gid != pmp->pm_gid)) { #ifdef MSDOSFS_DEBUG printf("msdosfs_setattr(): returning EINVAL\n"); - printf(" va_type %d, va_nlink %x, va_fsid %lx, va_fileid %llx\n", + printf(" va_type %d, va_nlink %x, va_fsid %"PRIx64", va_fileid %llx\n", vap->va_type, vap->va_nlink, vap->va_fsid, (unsigned long long)vap->va_fileid); - printf(" va_blocksize %lx, va_rdev %x, va_bytes %qx, va_gen %lx\n", + 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); #endif return (EINVAL); @@ -372,23 +368,26 @@ msdosfs_setattr(v) if (ap->a_vp->v_type == VDIR) return 0; + fstrans_start(vp->v_mount, FSTRANS_SHARED); if (vap->va_size != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { + error = EROFS; + goto bad; + } error = detrunc(dep, (u_long)vap->va_size, 0, cred); if (error) - return (error); + goto bad; de_changed = 1; } if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); - if (kauth_cred_geteuid(cred) != pmp->pm_uid && - (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, - NULL)) && - ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || - (error = VOP_ACCESS(ap->a_vp, VWRITE, cred)))) - return (error); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { + error = EROFS; + goto bad; + } + error = genfs_can_chtimes(ap->a_vp, vap->va_vaflags, + pmp->pm_uid, cred); + if (error) + goto bad; if ((pmp->pm_flags & MSDOSFSMNT_NOWIN95) == 0 && vap->va_atime.tv_sec != VNOVAL) unix2dostime(&vap->va_atime, pmp->pm_gmtoff, &dep->de_ADate, NULL, NULL); @@ -404,12 +403,14 @@ msdosfs_setattr(v) * attribute. */ if (vap->va_mode != (mode_t)VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { + error = EROFS; + goto bad; + } if (kauth_cred_geteuid(cred) != pmp->pm_uid && (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL))) - return (error); + goto bad; /* We ignore the read and execute bits. */ if (vap->va_mode & S_IWUSR) dep->de_Attributes &= ~ATTR_READONLY; @@ -422,12 +423,14 @@ msdosfs_setattr(v) * Allow the `archived' bit to be toggled. */ if (vap->va_flags != VNOVAL) { - if (vp->v_mount->mnt_flag & MNT_RDONLY) - return (EROFS); + if (vp->v_mount->mnt_flag & MNT_RDONLY) { + error = EROFS; + goto bad; + } if (kauth_cred_geteuid(cred) != pmp->pm_uid && (error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER, NULL))) - return (error); + goto bad; if (vap->va_flags & SF_ARCHIVED) dep->de_Attributes &= ~ATTR_ARCHIVE; else @@ -438,14 +441,18 @@ msdosfs_setattr(v) if (de_changed) { VN_KNOTE(vp, NOTE_ATTRIB); - return (deupdat(dep, 1)); - } else - return (0); + error = deupdat(dep, 1); + if (error) + goto bad; + } + +bad: + fstrans_done(vp->v_mount); + return error; } int -msdosfs_read(v) - void *v; +msdosfs_read(void *v) { struct vop_read_args /* { struct vnode *a_vp; @@ -453,13 +460,12 @@ msdosfs_read(v) int a_ioflag; kauth_cred_t a_cred; } */ *ap = v; - int error = 0, flags; + int error = 0; int64_t diff; int blsize; long n; long on; daddr_t lbn; - void *win; vsize_t bytelen; struct buf *bp; struct vnode *vp = ap->a_vp; @@ -478,6 +484,7 @@ msdosfs_read(v) if (uio->uio_offset >= dep->de_FileSize) return (0); + fstrans_start(vp->v_mount, FSTRANS_SHARED); if (vp->v_type == VREG) { const int advice = IO_ADV_DECODE(ap->a_ioflag); @@ -487,11 +494,8 @@ msdosfs_read(v) if (bytelen == 0) break; - win = ubc_alloc(&vp->v_uobj, uio->uio_offset, - &bytelen, advice, UBC_READ); - error = uiomove(win, bytelen, uio); - flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; - ubc_release(win, flags); + error = ubc_uiomove(&vp->v_uobj, uio, bytelen, advice, + UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp)); if (error) break; } @@ -514,7 +518,7 @@ msdosfs_read(v) /* convert cluster # to sector # */ error = pcbmap(dep, lbn, &lbn, 0, &blsize); if (error) - return (error); + goto bad; /* * If we are operating on a directory file then be sure to @@ -526,7 +530,7 @@ msdosfs_read(v) n = MIN(n, pmp->pm_bpcluster - bp->b_resid); if (error) { brelse(bp, 0); - return (error); + goto bad; } error = uiomove((char *)bp->b_data + on, (int) n, uio); brelse(bp, 0); @@ -535,6 +539,8 @@ msdosfs_read(v) out: if ((ap->a_ioflag & IO_SYNC) == IO_SYNC) error = deupdat(dep, 1); +bad: + fstrans_done(vp->v_mount); return (error); } @@ -542,8 +548,7 @@ out: * Write data to a file or directory. */ int -msdosfs_write(v) - void *v; +msdosfs_write(void *v) { struct vop_write_args /* { struct vnode *a_vp; @@ -551,16 +556,14 @@ msdosfs_write(v) int a_ioflag; kauth_cred_t a_cred; } */ *ap = v; - int resid, flags, extended = 0; + int resid, extended = 0; int error = 0; int ioflag = ap->a_ioflag; u_long osize; u_long count; - void *win; vsize_t bytelen; off_t oldoff; struct uio *uio = ap->a_uio; - struct proc *p = curproc; struct vnode *vp = ap->a_vp; struct denode *dep = VTODE(vp); struct msdosfsmount *pmp = dep->de_pmp; @@ -595,17 +598,7 @@ msdosfs_write(v) if (uio->uio_offset + uio->uio_resid > MSDOSFS_FILESIZE_MAX) return (EFBIG); - /* - * If they've exceeded their filesize limit, tell them about it. - */ - if (((uio->uio_offset + uio->uio_resid) > - p->p_rlimit[RLIMIT_FSIZE].rlim_cur)) { - mutex_enter(proc_lock); - psignal(p, SIGXFSZ); - mutex_exit(proc_lock); - return (EFBIG); - } - + fstrans_start(vp->v_mount, FSTRANS_SHARED); /* * If the offset we are starting the write at is beyond the end of * the file, then they've done a seek. Unix filesystems allow @@ -613,8 +606,10 @@ msdosfs_write(v) * with zeroed blocks. */ if (uio->uio_offset > dep->de_FileSize) { - if ((error = deextend(dep, uio->uio_offset, cred)) != 0) + if ((error = deextend(dep, uio->uio_offset, cred)) != 0) { + fstrans_done(vp->v_mount); return (error); + } } /* @@ -631,8 +626,7 @@ msdosfs_write(v) if (uio->uio_offset + resid > osize) { count = de_clcount(pmp, uio->uio_offset + resid) - de_clcount(pmp, osize); - if ((error = extendfile(dep, count, NULL, NULL, 0)) && - (error != ENOSPC || (ioflag & IO_UNIT))) + if ((error = extendfile(dep, count, NULL, NULL, 0))) goto errexit; dep->de_FileSize = uio->uio_offset + resid; @@ -645,11 +639,8 @@ msdosfs_write(v) oldoff = uio->uio_offset; bytelen = uio->uio_resid; - win = ubc_alloc(&vp->v_uobj, oldoff, &bytelen, UVM_ADV_NORMAL, - UBC_WRITE); - error = uiomove(win, bytelen, uio); - flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0; - ubc_release(win, flags); + error = ubc_uiomove(&vp->v_uobj, uio, bytelen, + IO_ADV_DECODE(ioflag), UBC_WRITE | UBC_UNMAP_FLAG(vp)); if (error) break; @@ -659,7 +650,7 @@ msdosfs_write(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); } @@ -668,7 +659,7 @@ msdosfs_write(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); } @@ -687,6 +678,7 @@ errexit: uio->uio_resid = resid; } else if ((ioflag & IO_SYNC) == IO_SYNC) error = deupdat(dep, 1); + fstrans_done(vp->v_mount); KASSERT(vp->v_size == dep->de_FileSize); return (error); } @@ -730,8 +722,7 @@ msdosfs_update(struct vnode *vp, const s * could just do a sync if they try an fsync on a directory file. */ int -msdosfs_remove(v) - void *v; +msdosfs_remove(void *v) { struct vop_remove_args /* { struct vnode *a_dvp; @@ -742,6 +733,7 @@ msdosfs_remove(v) struct denode *ddep = VTODE(ap->a_dvp); int error; + fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); if (ap->a_vp->v_type == VDIR) error = EPERM; else @@ -758,30 +750,11 @@ msdosfs_remove(v) vput(ap->a_vp); /* causes msdosfs_inactive() to be called * via vrele() */ vput(ap->a_dvp); + fstrans_done(ap->a_dvp->v_mount); return (error); } /* - * DOS filesystems don't know what links are. But since we already called - * msdosfs_lookup() with create and lockparent, the parent is locked so we - * have to free it before we return the error. - */ -int -msdosfs_link(v) - void *v; -{ - struct vop_link_args /* { - struct vnode *a_dvp; - struct vnode *a_vp; - struct componentname *a_cnp; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EOPNOTSUPP); -} - -/* * Renames on files require moving the denode to a new hash queue since the * denode's location is used to compute which hash queue to put the file * in. Unless it is a rename in place. For example "mv a b". @@ -838,8 +811,7 @@ msdosfs_link(v) * This routine needs help. badly. */ int -msdosfs_rename(v) - void *v; +msdosfs_rename(void *v) { struct vop_rename_args /* { struct vnode *a_fdvp; @@ -927,7 +899,7 @@ abortit: (fcnp->cn_flags & ISDOTDOT) || (tcnp->cn_flags & ISDOTDOT) || (ip->de_flag & DE_RENAME)) { - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); error = EINVAL; goto abortit; } @@ -936,6 +908,7 @@ abortit: } VN_KNOTE(fdvp, NOTE_WRITE); /* XXXLUKEM/XXX: right place? */ + fstrans_start(fdvp->v_mount, FSTRANS_SHARED); /* * When the target exists, both the directory * and target vnodes are returned locked. @@ -959,7 +932,7 @@ abortit: * call to doscheckpath(). */ error = VOP_ACCESS(fvp, VWRITE, tcnp->cn_cred); - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); if (VTODE(fdvp)->de_StartCluster != VTODE(tdvp)->de_StartCluster) newparent = 1; @@ -989,7 +962,7 @@ abortit: panic("msdosfs_rename: lost to startdir"); vn_lock(tdvp, LK_EXCLUSIVE | LK_RETRY); if ((error = relookup(tdvp, &tvp, tcnp)) != 0) { - VOP_UNLOCK(tdvp, 0); + VOP_UNLOCK(tdvp); goto out; } /* @@ -1034,8 +1007,10 @@ abortit: * into the denode and directory entry for the destination * file/directory. */ - if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) + if ((error = uniqdosname(VTODE(tdvp), tcnp, toname)) != 0) { + fstrans_done(fdvp->v_mount); goto abortit; + } /* * Since from wasn't locked at various places above, @@ -1045,12 +1020,13 @@ abortit: fcnp->cn_flags |= LOCKPARENT | LOCKLEAF; if ((fcnp->cn_flags & SAVESTART) == 0) panic("msdosfs_rename: lost from startdir"); - VOP_UNLOCK(tdvp, 0); + VOP_UNLOCK(tdvp); vn_lock(fdvp, LK_EXCLUSIVE | LK_RETRY); if ((error = relookup(fdvp, &fvp, fcnp))) { - VOP_UNLOCK(fdvp, 0); + VOP_UNLOCK(fdvp); vrele(ap->a_fvp); vrele(tdvp); + fstrans_done(fdvp->v_mount); return (error); } if (fvp == NULL) { @@ -1062,10 +1038,11 @@ abortit: vput(fdvp); vrele(ap->a_fvp); vrele(tdvp); + fstrans_done(fdvp->v_mount); return 0; } fdvp_dorele = 1; - VOP_UNLOCK(fdvp, 0); + VOP_UNLOCK(fdvp); xp = VTODE(fvp); zp = VTODE(fdvp); from_diroffset = zp->de_fndoffset; @@ -1082,7 +1059,6 @@ abortit: if (doingdirectory) panic("rename: lost dir entry"); vrele(ap->a_fvp); - VOP_UNLOCK(fvp, 0); xp = NULL; } else { vrele(fvp); @@ -1103,14 +1079,14 @@ abortit: error = createde(ip, dp, (struct denode **)0, tcnp); if (error) { memcpy(ip->de_Name, oldname, 11); - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); goto bad; } ip->de_refcnt++; zp->de_fndoffset = from_diroffset; if ((error = removede(zp, ip)) != 0) { /* XXX should really panic here, fs is corrupt */ - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); goto bad; } cache_purge(fvp); @@ -1119,7 +1095,7 @@ abortit: &ip->de_dirclust, 0); if (error) { /* XXX should really panic here, fs is corrupt */ - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); goto bad; } ip->de_diroffset = to_diroffset; @@ -1145,7 +1121,7 @@ abortit: if (error) { /* XXX should really panic here, fs is corrupt */ brelse(bp, 0); - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); goto bad; } dotdotp = (struct direntry *)bp->b_data + 1; @@ -1158,13 +1134,13 @@ abortit: } if ((error = bwrite(bp)) != 0) { /* XXX should really panic here, fs is corrupt */ - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); goto bad; } } VN_KNOTE(fvp, NOTE_RENAME); - VOP_UNLOCK(fvp, 0); + VOP_UNLOCK(fvp); bad: if (tvp) vput(tvp); @@ -1174,11 +1150,12 @@ out: if (fdvp_dorele) vrele(fdvp); vrele(fvp); + fstrans_done(fdvp->v_mount); return (error); /* XXX: uuuh */ tdvpbad: - VOP_UNLOCK(tdvp, 0); + VOP_UNLOCK(tdvp); goto bad; } @@ -1209,8 +1186,7 @@ static const struct { }; int -msdosfs_mkdir(v) - void *v; +msdosfs_mkdir(void *v) { struct vop_mkdir_args /* { struct vnode *a_dvp; @@ -1231,6 +1207,7 @@ msdosfs_mkdir(v) struct buf *bp; int async = pdep->de_pmp->pm_mountp->mnt_flag & MNT_ASYNC; + fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); /* * If this is the root directory and there is no space left we * can't do anything. This is because the root directory can not @@ -1320,6 +1297,7 @@ msdosfs_mkdir(v) VN_KNOTE(ap->a_dvp, NOTE_WRITE | NOTE_LINK); vput(ap->a_dvp); *ap->a_vpp = DETOV(dep); + fstrans_done(ap->a_dvp->v_mount); return (0); bad: @@ -1327,12 +1305,12 @@ bad: bad2: PNBUF_PUT(cnp->cn_pnbuf); vput(ap->a_dvp); + fstrans_done(ap->a_dvp->v_mount); return (error); } int -msdosfs_rmdir(v) - void *v; +msdosfs_rmdir(void *v) { struct vop_rmdir_args /* { struct vnode *a_dvp; @@ -1355,6 +1333,7 @@ msdosfs_rmdir(v) vput(vp); return (EINVAL); } + fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); /* * Verify the directory is empty (and valid). * (Rmdir ".." won't be valid since @@ -1396,32 +1375,12 @@ out: if (dvp) vput(dvp); vput(vp); + fstrans_done(ap->a_dvp->v_mount); return (error); } -/* - * DOS filesystems don't know what symlinks are. - */ -int -msdosfs_symlink(v) - void *v; -{ - struct vop_symlink_args /* { - struct vnode *a_dvp; - struct vnode **a_vpp; - struct componentname *a_cnp; - struct vattr *a_vap; - char *a_target; - } */ *ap = v; - - VOP_ABORTOP(ap->a_dvp, ap->a_cnp); - vput(ap->a_dvp); - return (EOPNOTSUPP); -} - int -msdosfs_readdir(v) - void *v; +msdosfs_readdir(void *v) { struct vop_readdir_args /* { struct vnode *a_vp; @@ -1482,6 +1441,8 @@ msdosfs_readdir(v) uio->uio_resid = count; uio_off = uio->uio_offset; + fstrans_start(ap->a_vp->v_mount, FSTRANS_SHARED); + /* Allocate a temporary dirent buffer. */ dirbuf = malloc(sizeof(struct dirent), M_MSDOSFSTMP, M_WAITOK | M_ZERO); @@ -1561,8 +1522,7 @@ msdosfs_readdir(v) NOCRED, 0, &bp); if (error) { brelse(bp, 0); - free(dirbuf, M_MSDOSFSTMP); - return (error); + goto bad; } n = MIN(n, blsize - bp->b_resid); @@ -1683,28 +1643,14 @@ out: } else *ap->a_ncookies = ncookies; } + +bad: free(dirbuf, M_MSDOSFSTMP); + fstrans_done(ap->a_vp->v_mount); return (error); } /* - * DOS filesystems don't know what symlinks are. - */ -int -msdosfs_readlink(void *v) -{ -#if 0 - struct vop_readlink_args /* { - struct vnode *a_vp; - struct uio *a_uio; - kauth_cred_t a_cred; - } */ *ap; -#endif - - return (EINVAL); -} - -/* * vp - address of vnode file the file * bn - which cluster we are interested in mapping to a filesystem block number. * vpp - returns the vnode for the block special file holding the filesystem @@ -1712,8 +1658,7 @@ msdosfs_readlink(void *v) * bnp - address of where to return the filesystem relative block number */ int -msdosfs_bmap(v) - void *v; +msdosfs_bmap(void *v) { struct vop_bmap_args /* { struct vnode *a_vp; @@ -1762,8 +1707,7 @@ msdosfs_bmap(v) } int -msdosfs_strategy(v) - void *v; +msdosfs_strategy(void *v) { struct vop_strategy_args /* { struct vnode *a_vp; @@ -1807,8 +1751,7 @@ msdosfs_strategy(v) } int -msdosfs_print(v) - void *v; +msdosfs_print(void *v) { struct vop_print_args /* { struct vnode *vp; @@ -1825,8 +1768,7 @@ msdosfs_print(v) } int -msdosfs_advlock(v) - void *v; +msdosfs_advlock(void *v) { struct vop_advlock_args /* { struct vnode *a_vp; @@ -1841,8 +1783,7 @@ msdosfs_advlock(v) } int -msdosfs_pathconf(v) - void *v; +msdosfs_pathconf(void *v) { struct vop_pathconf_args /* { struct vnode *a_vp; @@ -1879,8 +1820,7 @@ msdosfs_pathconf(v) } int -msdosfs_fsync(v) - void *v; +msdosfs_fsync(void *v) { struct vop_fsync_args /* { struct vnode *a_vp; @@ -1893,6 +1833,7 @@ msdosfs_fsync(v) int wait; int error; + fstrans_start(vp->v_mount, FSTRANS_LAZY); wait = (ap->a_flags & FSYNC_WAIT) != 0; vflushbuf(vp, wait); if ((ap->a_flags & FSYNC_DATAONLY) != 0) @@ -1908,6 +1849,7 @@ msdosfs_fsync(v) error = VOP_IOCTL(devvp, DIOCCACHESYNC, &l, FWRITE, curlwp->l_cred); } + fstrans_done(vp->v_mount); return (error); } @@ -1954,8 +1896,8 @@ const struct vnodeopv_entry_desc msdosfs { &vop_default_desc, vn_default_error }, { &vop_lookup_desc, msdosfs_lookup }, /* lookup */ { &vop_create_desc, msdosfs_create }, /* create */ - { &vop_mknod_desc, msdosfs_mknod }, /* mknod */ - { &vop_open_desc, msdosfs_open }, /* open */ + { &vop_mknod_desc, genfs_eopnotsupp }, /* mknod */ + { &vop_open_desc, genfs_nullop }, /* open */ { &vop_close_desc, msdosfs_close }, /* close */ { &vop_access_desc, msdosfs_access }, /* access */ { &vop_getattr_desc, msdosfs_getattr }, /* getattr */ @@ -1971,13 +1913,13 @@ const struct vnodeopv_entry_desc msdosfs { &vop_fsync_desc, msdosfs_fsync }, /* fsync */ { &vop_seek_desc, msdosfs_seek }, /* seek */ { &vop_remove_desc, msdosfs_remove }, /* remove */ - { &vop_link_desc, msdosfs_link }, /* link */ + { &vop_link_desc, genfs_eopnotsupp }, /* link */ { &vop_rename_desc, msdosfs_rename }, /* rename */ { &vop_mkdir_desc, msdosfs_mkdir }, /* mkdir */ { &vop_rmdir_desc, msdosfs_rmdir }, /* rmdir */ - { &vop_symlink_desc, msdosfs_symlink }, /* symlink */ + { &vop_symlink_desc, genfs_eopnotsupp }, /* symlink */ { &vop_readdir_desc, msdosfs_readdir }, /* readdir */ - { &vop_readlink_desc, msdosfs_readlink }, /* readlink */ + { &vop_readlink_desc, genfs_einval }, /* readlink */ { &vop_abortop_desc, msdosfs_abortop }, /* abortop */ { &vop_inactive_desc, msdosfs_inactive }, /* inactive */ { &vop_reclaim_desc, msdosfs_reclaim }, /* reclaim */