From 868630039f3335e1079202ef1795b0391612c7e2 Mon Sep 17 00:00:00 2001 From: kib Date: Sun, 7 Dec 2008 13:25:06 +0000 Subject: Improve usefulness of the panic by printing the pointer to the problematic dquot. In-tree gdb is often unable to get the dq value, so supply it in panic message. MFC after: 3 days --- sys/ufs/ufs/ufs_quota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index e5cb956..5f068c0 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -1151,7 +1151,7 @@ hfound: DQI_LOCK(dq); return (EUSERS); } if (dq->dq_cnt || (dq->dq_flags & DQ_MOD)) - panic("dqget: free dquot isn't"); + panic("dqget: free dquot isn't %p", dq); TAILQ_REMOVE(&dqfreelist, dq, dq_freelist); if (dq->dq_ump != NULL) LIST_REMOVE(dq, dq_hash); -- cgit v1.1 From 01085e085d51e1ee61dcba260fad1e95ee8a4e99 Mon Sep 17 00:00:00 2001 From: kib Date: Mon, 8 Dec 2008 11:04:17 +0000 Subject: The dqrele() function syncs the dq, then acquires the dqh lock, and then does final drop of the the dq reference to put it onto the free list. There is a possibility that the dq would be found by another thread after sync and before the dqh lock is acquired. If that other thread drops the dq before we have taken the dqh lock, the dirty dq is put on the free list. Recheck the DQ_MOD after the dqh lock is relocked. Repeat dqsync() if the dq is dirty. This ensures that up to date dq is written in the quota file and fixes assertion in dqget(). Reported and tested by: Frode Nordahl MFC after: 3 days --- sys/ufs/ufs/ufs_quota.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_quota.c b/sys/ufs/ufs/ufs_quota.c index 5f068c0..2db0444 100644 --- a/sys/ufs/ufs/ufs_quota.c +++ b/sys/ufs/ufs/ufs_quota.c @@ -1262,7 +1262,7 @@ dqrele(struct vnode *vp, struct dquot *dq) return; } DQH_UNLOCK(); - +sync: (void) dqsync(vp, dq); DQH_LOCK(); @@ -1271,6 +1271,18 @@ dqrele(struct vnode *vp, struct dquot *dq) DQH_UNLOCK(); return; } + + /* + * The dq may become dirty after it is synced but before it is + * put to the free list. Checking the DQ_MOD there without + * locking dq should be safe since no other references to the + * dq exist. + */ + if ((dq->dq_flags & DQ_MOD) != 0) { + dq->dq_cnt++; + DQH_UNLOCK(); + goto sync; + } TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); DQH_UNLOCK(); } -- cgit v1.1 From b2515a861b17c67bef0ad8eb3e85cdaffe242388 Mon Sep 17 00:00:00 2001 From: trasz Date: Tue, 16 Dec 2008 21:13:11 +0000 Subject: According to phk@, VOP_STRATEGY should never, _ever_, return anything other than 0. Make it so. This fixes "panic: VOP_STRATEGY failed bp=0xc320dd90 vp=0xc3b9f648", encountered when writing to an orphaned filesystem. Reason for the panic was the following assert: KASSERT(i == 0, ("VOP_STRATEGY failed bp=%p vp=%p", bp, bp->b_vp)); at vfs_bio:bufstrategy(). Reviewed by: scottl, phk Approved by: rwatson (mentor) Sponsored by: FreeBSD Foundation --- sys/ufs/ufs/ufs_vnops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index e5047e9..7b639e8 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -2013,7 +2013,7 @@ ufs_strategy(ap) bp->b_error = error; bp->b_ioflags |= BIO_ERROR; bufdone(bp); - return (error); + return (0); } if ((long)bp->b_blkno == -1) vfs_bio_clrbuf(bp); -- cgit v1.1 From 068931a9897e3bea2e9c192f392fe5548cbed6ce Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 18 Dec 2008 12:01:53 +0000 Subject: Do not busy twice the mount point where a quota operation is performed. Tested by: pho MFC after: 1 month --- sys/ufs/ufs/ufs_vfsops.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_vfsops.c b/sys/ufs/ufs/ufs_vfsops.c index 14ce4c6..ac1fbcf 100644 --- a/sys/ufs/ufs/ufs_vfsops.c +++ b/sys/ufs/ufs/ufs_vfsops.c @@ -118,9 +118,6 @@ ufs_quotactl(mp, cmds, id, arg, td) if ((u_int)type >= MAXQUOTAS) return (EINVAL); - if (vfs_busy(mp, MBF_NOWAIT)) - return (0); - switch (cmd) { case Q_QUOTAON: error = quotaon(td, mp, type, arg); @@ -150,7 +147,6 @@ ufs_quotactl(mp, cmds, id, arg, td) error = EINVAL; break; } - vfs_unbusy(mp); return (error); #endif } -- cgit v1.1 From 1f52da301fa5379c80d0cff685919ebf84bbfcb2 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 8 Jan 2009 12:48:27 +0000 Subject: If unmount of the ffs mp failed, reinitialize the extended attributes for the mp, and restart them if autostart is enabled. Reported and tested by: pho Reviewed by: rwatson MFC after: 3 weeks --- sys/ufs/ffs/ffs_vfsops.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 563473c..d5a1a4f 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1030,6 +1030,9 @@ ffs_unmount(mp, mntflags, td) struct ufsmount *ump = VFSTOUFS(mp); struct fs *fs; int error, flags, susp; +#ifdef UFS_EXTATTR + int e_restart; +#endif flags = 0; fs = ump->um_fs; @@ -1043,8 +1046,10 @@ ffs_unmount(mp, mntflags, td) if (error != EOPNOTSUPP) printf("ffs_unmount: ufs_extattr_stop returned %d\n", error); + e_restart = 0; } else { ufs_extattr_uepm_destroy(&ump->um_extattr); + e_restart = 1; } #endif if (susp) { @@ -1121,6 +1126,15 @@ fail: vfs_write_resume(mp); vn_start_write(NULL, &mp, V_WAIT); } +#ifdef UFS_EXTATTR + if (e_restart) { + ufs_extattr_uepm_init(&ump->um_extattr); +#ifdef UFS_EXTATTR_AUTOSTART + (void) ufs_extattr_autostart(mp, td); +#endif + } +#endif + return (error); } -- cgit v1.1 From ca2e9cb3a95ecaff97ffcaba97157c04af4855c4 Mon Sep 17 00:00:00 2001 From: kib Date: Thu, 8 Jan 2009 12:49:55 +0000 Subject: Lock the uepm_lock around the autostart of extattrs. Reported and tested by: pho Reviewed by: rwatson MFC after: 3 weeks --- sys/ufs/ufs/ufs_extattr.c | 45 ++++++++++++++++++++++++++++++--------------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_extattr.c b/sys/ufs/ufs/ufs_extattr.c index b991920..d034bee 100644 --- a/sys/ufs/ufs/ufs_extattr.c +++ b/sys/ufs/ufs/ufs_extattr.c @@ -93,6 +93,10 @@ static int ufs_extattr_set(struct vnode *vp, int attrnamespace, struct thread *td); static int ufs_extattr_rm(struct vnode *vp, int attrnamespace, const char *name, struct ucred *cred, struct thread *td); +static int ufs_extattr_autostart_locked(struct mount *mp, + struct thread *td); +static int ufs_extattr_start_locked(struct ufsmount *ump, + struct thread *td); /* * Per-FS attribute lock protecting attribute operations. @@ -208,24 +212,22 @@ ufs_extattr_start(struct mount *mp, struct thread *td) ump = VFSTOUFS(mp); ufs_extattr_uepm_lock(ump, td); + error = ufs_extattr_start_locked(ump, td); + ufs_extattr_uepm_unlock(ump, td); + return (error); +} - if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED)) { - error = EOPNOTSUPP; - goto unlock; - } - if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED) { - error = EBUSY; - goto unlock; - } +static int +ufs_extattr_start_locked(struct ufsmount *ump, struct thread *td) +{ + if (!(ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_INITIALIZED)) + return (EOPNOTSUPP); + if (ump->um_extattr.uepm_flags & UFS_EXTATTR_UEPM_STARTED) + return (EBUSY); ump->um_extattr.uepm_flags |= UFS_EXTATTR_UEPM_STARTED; - ump->um_extattr.uepm_ucred = crhold(td->td_ucred); - -unlock: - ufs_extattr_uepm_unlock(ump, td); - - return (error); + return (0); } #ifdef UFS_EXTATTR_AUTOSTART @@ -448,6 +450,19 @@ ufs_extattr_iterate_directory(struct ufsmount *ump, struct vnode *dvp, int ufs_extattr_autostart(struct mount *mp, struct thread *td) { + struct ufsmount *ump; + int error; + + ump = VFSTOUFS(mp); + ufs_extattr_uepm_lock(ump, td); + error = ufs_extattr_autostart_locked(mp, td); + ufs_extattr_uepm_unlock(ump, td); + return (error); +} + +static int +ufs_extattr_autostart_locked(struct mount *mp, struct thread *td) +{ struct vnode *rvp, *attr_dvp, *attr_system_dvp, *attr_user_dvp; struct ufsmount *ump = VFSTOUFS(mp); int error; @@ -491,7 +506,7 @@ ufs_extattr_autostart(struct mount *mp, struct thread *td) goto return_vput_attr_dvp; } - error = ufs_extattr_start(mp, td); + error = ufs_extattr_start_locked(ump, td); if (error) { printf("ufs_extattr_autostart: ufs_extattr_start failed (%d)\n", error); -- cgit v1.1 From cbb8defa10711f9b65be83f41f04cbabab84b5fc Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 20 Jan 2009 11:27:45 +0000 Subject: FFS puts the extended attributes blocks at the negative blocks for the vnode, from -1 down. When vinvalbuf(vp, V_ALT) is done for the vnode, it incorrectly does vm_object_page_remove(0, 0), removing all pages from the underlying vm object, not only the pages that back the extended attributes data. Change vinvalbuf() to not remove any pages from the object when V_NORMAL or V_ALT are specified. Instead, the only in-tree caller in ffs_inode.c:ffs_truncate() that specifies V_ALT explicitely removes the corresponding page range. The V_NORMAL caller does vnode_pager_setsize(vp, 0) immediately after the call to vinvalbuf(V_NORMAL) already. Reported by: csjp Reviewed by: ups MFC after: 3 weeks --- sys/ufs/ffs/ffs_inode.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index fa679ef..2be220e 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include @@ -151,6 +152,7 @@ ffs_truncate(vp, length, flags, cred, td) struct fs *fs; struct buf *bp; struct ufsmount *ump; + vm_object_t object; int needextclean, softdepslowdown, extblocks; int offset, size, level, nblocks; int i, error, allerror; @@ -205,6 +207,13 @@ ffs_truncate(vp, length, flags, cred, td) (void) chkdq(ip, -extblocks, NOCRED, 0); #endif vinvalbuf(vp, V_ALT, 0, 0); + if ((object = vp->v_object) != NULL) { + VM_OBJECT_LOCK(object); + vm_object_page_remove(object, + OFF_TO_IDX(lblktosize(fs, -extblocks)), 0, + FALSE); + VM_OBJECT_UNLOCK(object); + } ip->i_din2->di_extsize = 0; for (i = 0; i < NXADDR; i++) { oldblks[i] = ip->i_din2->di_extb[i]; -- cgit v1.1 From ac57d6e717c7b5921f7a8c6d60d1c846ea1d04d5 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 20 Jan 2009 11:30:22 +0000 Subject: When extending inode size, we call vnode_pager_setsize(), to have a address space where to put vnode pages, and then call UFS_BALLOC(), to actually allocate new block and map it. When UFS_BALLOC() returns error, sometimes we forget to revert the vm object size increase, allowing for the pages that are not backed by the logical disk blocks. Revert vnode_pager_setsize() back when UFS_BALLOC() failed, for ffs_truncate() and ffs_write(). PR: 129956 Reviewed by: ups MFC after: 3 weeks --- sys/ufs/ffs/ffs_inode.c | 4 +++- sys/ufs/ffs/ffs_vnops.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 2be220e..36aac0e 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -305,8 +305,10 @@ ffs_truncate(vp, length, flags, cred, td) vnode_pager_setsize(vp, length); flags |= BA_CLRBUF; error = UFS_BALLOC(vp, length - 1, 1, cred, flags, &bp); - if (error) + if (error) { + vnode_pager_setsize(vp, osize); return (error); + } ip->i_size = length; DIP_SET(ip, i_size, length); if (bp->b_bufsize == fs->fs_bsize) diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index 38dc2b6..e5b3ffe 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -723,8 +723,10 @@ ffs_write(ap) /* XXX is uio->uio_offset the right thing here? */ error = UFS_BALLOC(vp, uio->uio_offset, xfersize, ap->a_cred, flags, &bp); - if (error != 0) + if (error != 0) { + vnode_pager_setsize(vp, ip->i_size); break; + } /* * If the buffer is not valid we have to clear out any * garbage data from the pages instantiated for the buffer. -- cgit v1.1 From 19686e364d4eaa10fb7ddc1226b367ef47a22480 Mon Sep 17 00:00:00 2001 From: jhb Date: Tue, 20 Jan 2009 16:35:34 +0000 Subject: Add a comment explaining why the "bufwait" / "dirhash" LOR reported by WITNESS will not actually result in a deadlock. Discussed with: kib MFC after: 1 week --- sys/ufs/ufs/ufs_dirhash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 0eacb58..3b6d5e1 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -126,6 +126,18 @@ static struct mtx ufsdirhash_mtx; * free a dirhash structure that was recycled by ufsdirhash_recycle(). * * The dirhash lock may be held across io operations. + * + * WITNESS reports a lock order reversal between the "bufwait" lock + * and the "dirhash" lock. However, this specific reversal will not + * cause a deadlock. To get a deadlock, one would have to lock a + * buffer followed by the dirhash while a second thread locked a + * buffer while holding the dirhash lock. The second order can happen + * under a shared or exclusive vnode lock for the associated directory + * in lookup(). The first order, however, can only happen under an + * exclusive vnode lock (e.g. unlink(), rename(), etc.). Thus, for + * a thread to be doing a "bufwait" -> "dirhash" order, it has to hold + * an exclusive vnode lock. That exclusive vnode lock will prevent + * any other threads from doing a "dirhash" -> "bufwait" order. */ static void -- cgit v1.1 From 1a9032d3393992926a15a517a335cdb0e656baf9 Mon Sep 17 00:00:00 2001 From: kib Date: Tue, 20 Jan 2009 22:00:19 +0000 Subject: The r187467 should remove all pages for V_NORMAL case too, because indirect block pages are not removed by the mentioned invocation of the vnode_pager_setsize(). Put a common code into the helper function ffs_pages_remove(). Reported and tested by: dchagin Reviewed by: ups MFC after: 3 weeks --- sys/ufs/ffs/ffs_inode.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index 36aac0e..e6269b6 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -129,6 +129,18 @@ ffs_update(vp, waitfor) } } +static void +ffs_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end) +{ + vm_object_t object; + + if ((object = vp->v_object) == NULL) + return; + VM_OBJECT_LOCK(object); + vm_object_page_remove(object, start, end, FALSE); + VM_OBJECT_UNLOCK(object); +} + #define SINGLE 0 /* index of single indirect block */ #define DOUBLE 1 /* index of double indirect block */ #define TRIPLE 2 /* index of triple indirect block */ @@ -152,7 +164,6 @@ ffs_truncate(vp, length, flags, cred, td) struct fs *fs; struct buf *bp; struct ufsmount *ump; - vm_object_t object; int needextclean, softdepslowdown, extblocks; int offset, size, level, nblocks; int i, error, allerror; @@ -207,13 +218,8 @@ ffs_truncate(vp, length, flags, cred, td) (void) chkdq(ip, -extblocks, NOCRED, 0); #endif vinvalbuf(vp, V_ALT, 0, 0); - if ((object = vp->v_object) != NULL) { - VM_OBJECT_LOCK(object); - vm_object_page_remove(object, - OFF_TO_IDX(lblktosize(fs, -extblocks)), 0, - FALSE); - VM_OBJECT_UNLOCK(object); - } + ffs_pages_remove(vp, + OFF_TO_IDX(lblktosize(fs, -extblocks)), 0); ip->i_din2->di_extsize = 0; for (i = 0; i < NXADDR; i++) { oldblks[i] = ip->i_din2->di_extb[i]; @@ -290,6 +296,9 @@ ffs_truncate(vp, length, flags, cred, td) IO_EXT | IO_NORMAL : IO_NORMAL); ASSERT_VOP_LOCKED(vp, "ffs_truncate1"); vinvalbuf(vp, needextclean ? 0 : V_NORMAL, 0, 0); + if (!needextclean) + ffs_pages_remove(vp, 0, + OFF_TO_IDX(lblktosize(fs, -extblocks))); vnode_pager_setsize(vp, 0); ip->i_flag |= IN_CHANGE | IN_UPDATE; return (ffs_update(vp, 0)); -- cgit v1.1 From 47455a7b41fddec8ed401d12470434bd77477189 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 21 Jan 2009 14:42:00 +0000 Subject: Move the VA_MARKATIME flag for VOP_SETATTR() out into its own VOP: VOP_MARKATIME() since unlike the rest of VOP_SETATTR(), VA_MARKATIME can be performed while holding a shared vnode lock (the same functionality is done internally by VOP_READ which can run with a shared vnode lock). Add missing locking of the vnode interlock to the ufs implementation and remove a special note and test from the NFS client about not supporting the feature. Inspired by: ups Tested by: pho --- sys/ufs/ufs/ufs_vnops.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 7b639e8..3fc16a1 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -98,6 +98,7 @@ static vop_create_t ufs_create; static vop_getattr_t ufs_getattr; static vop_link_t ufs_link; static int ufs_makeinode(int mode, struct vnode *, struct vnode **, struct componentname *); +static vop_markatime_t ufs_markatime; static vop_mkdir_t ufs_mkdir; static vop_mknod_t ufs_mknod; static vop_open_t ufs_open; @@ -491,17 +492,6 @@ ufs_setattr(ap) ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL)) { return (EINVAL); } - /* - * Mark for update the file's access time for vfs_mark_atime(). - * We are doing this here to avoid some of the checks done - * below -- this operation is done by request of the kernel and - * should bypass some security checks. Things like read-only - * checks get handled by other levels (e.g., ffs_update()). - */ - if (vap->va_vaflags & VA_MARK_ATIME) { - ip->i_flag |= IN_ACCESS; - return (0); - } if (vap->va_flags != VNOVAL) { if (vp->v_mount->mnt_flag & MNT_RDONLY) return (EROFS); @@ -663,6 +653,25 @@ ufs_setattr(ap) } /* + * Mark this file's access time for update for vfs_mark_atime(). This + * is called from execve() and mmap(). + */ +static int +ufs_markatime(ap) + struct vop_markatime_args /* { + struct vnode *a_vp; + } */ *ap; +{ + struct vnode *vp = ap->a_vp; + struct inode *ip = VTOI(vp); + + VI_LOCK(vp); + ip->i_flag |= IN_ACCESS; + VI_UNLOCK(vp); + return (0); +} + +/* * Change the mode on a file. * Inode must be locked before calling. */ @@ -2481,6 +2490,7 @@ struct vop_vector ufs_vnodeops = { .vop_rename = ufs_rename, .vop_rmdir = ufs_rmdir, .vop_setattr = ufs_setattr, + .vop_markatime = ufs_markatime, #ifdef MAC .vop_setlabel = vop_stdsetlabel_ea, #endif @@ -2511,6 +2521,7 @@ struct vop_vector ufs_fifoops = { .vop_read = VOP_PANIC, .vop_reclaim = ufs_reclaim, .vop_setattr = ufs_setattr, + .vop_markatime = ufs_markatime, #ifdef MAC .vop_setlabel = vop_stdsetlabel_ea, #endif -- cgit v1.1 From 44eef9d9bb82bfa3434a676ef8796afa45b737fc Mon Sep 17 00:00:00 2001 From: kib Date: Wed, 21 Jan 2009 14:51:38 +0000 Subject: Move the code from ufs_lookup.c used to do dotdot lookup, into the helper function. It is supposed to be useful for any filesystem that has to unlock dvp to walk to the ".." entry in lookup routine. Requested by: jhb Tested by: pho MFC after: 1 month --- sys/ufs/ufs/ufs_lookup.c | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_lookup.c b/sys/ufs/ufs/ufs_lookup.c index 65ab0da..bc11a6a 100644 --- a/sys/ufs/ufs/ufs_lookup.c +++ b/sys/ufs/ufs/ufs_lookup.c @@ -157,7 +157,6 @@ ufs_lookup(ap) int nameiop = cnp->cn_nameiop; ino_t ino; int ltype; - struct mount *mp; bp = NULL; slotoffset = -1; @@ -578,27 +577,7 @@ found: */ pdp = vdp; if (flags & ISDOTDOT) { - ltype = VOP_ISLOCKED(pdp); - mp = pdp->v_mount; - for (;;) { - error = vfs_busy(mp, MBF_NOWAIT); - if (error == 0) - break; - VOP_UNLOCK(pdp, 0); - pause("ufs_dd", 1); - vn_lock(pdp, ltype | LK_RETRY); - if (pdp->v_iflag & VI_DOOMED) - return (ENOENT); - } - VOP_UNLOCK(pdp, 0); /* race to get the inode */ - error = VFS_VGET(mp, ino, cnp->cn_lkflags, &tdp); - vfs_unbusy(mp); - vn_lock(pdp, ltype | LK_RETRY); - if (pdp->v_iflag & VI_DOOMED) { - if (error == 0) - vput(tdp); - error = ENOENT; - } + error = vn_vget_ino(pdp, ino, cnp->cn_lkflags, &tdp); if (error) return (error); *vpp = tdp; -- cgit v1.1 From 2939c2f76f4c6f9ca6b56d817cdf9f28de9bd66f Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 21 Jan 2009 20:08:17 +0000 Subject: Fix a few style bogons. Submitted by: bde --- sys/ufs/ufs/ufs_vnops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ufs/ufs_vnops.c b/sys/ufs/ufs/ufs_vnops.c index 3fc16a1..675c55c 100644 --- a/sys/ufs/ufs/ufs_vnops.c +++ b/sys/ufs/ufs/ufs_vnops.c @@ -2477,6 +2477,7 @@ struct vop_vector ufs_vnodeops = { .vop_inactive = ufs_inactive, .vop_link = ufs_link, .vop_lookup = vfs_cache_lookup, + .vop_markatime = ufs_markatime, .vop_mkdir = ufs_mkdir, .vop_mknod = ufs_mknod, .vop_open = ufs_open, @@ -2490,7 +2491,6 @@ struct vop_vector ufs_vnodeops = { .vop_rename = ufs_rename, .vop_rmdir = ufs_rmdir, .vop_setattr = ufs_setattr, - .vop_markatime = ufs_markatime, #ifdef MAC .vop_setlabel = vop_stdsetlabel_ea, #endif @@ -2517,11 +2517,11 @@ struct vop_vector ufs_fifoops = { .vop_getattr = ufs_getattr, .vop_inactive = ufs_inactive, .vop_kqfilter = ufsfifo_kqfilter, + .vop_markatime = ufs_markatime, .vop_print = ufs_print, .vop_read = VOP_PANIC, .vop_reclaim = ufs_reclaim, .vop_setattr = ufs_setattr, - .vop_markatime = ufs_markatime, #ifdef MAC .vop_setlabel = vop_stdsetlabel_ea, #endif -- cgit v1.1 From c99f201c9eed9159ea6ab00a0bac551174f7e125 Mon Sep 17 00:00:00 2001 From: rwatson Date: Tue, 27 Jan 2009 21:48:47 +0000 Subject: Following a fair amount of real world experience with ACLs and extended attributes since FreeBSD 5, make the following semantic changes: - Don't update the inode modification time (mtime) when extended attributes (and hence also ACLs) are added, modified, or removed. - Don't update the inode access tie (atime) when extended attributes (and hence also ACLs) are queried. This means that rsync (and related tools) won't improperly think that the data in the file has changed when only the ACL has changed. Note that ffs_reallocblks() has not been changed to not update on an IO_EXT transaction, but currently EAs don't use the cluster write routines so this shouldn't be a problem. If EAs grow support for clustering, then VOP_REALLOCBLKS() will need to grow a flag argument to carry down IO_EXT to UFS. MFC after: 1 week PR: ports/125739 Reported by: Alexander Zagrebin Tested by: pluknet , Greg Byshenk Discussed with: kib, kientzle, timur, Alexander Bokovoy --- sys/ufs/ffs/ffs_alloc.c | 23 ++++++++++++++++------- sys/ufs/ffs/ffs_balloc.c | 42 +++++++++++++++++++++++------------------- sys/ufs/ffs/ffs_extern.h | 6 +++--- sys/ufs/ffs/ffs_inode.c | 2 +- sys/ufs/ffs/ffs_vnops.c | 10 +--------- 5 files changed, 44 insertions(+), 39 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index a72137e..e21a484 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -130,10 +130,10 @@ static int ffs_reallocblks_ufs2(struct vop_reallocblks_args *); * available block is located. */ int -ffs_alloc(ip, lbn, bpref, size, cred, bnp) +ffs_alloc(ip, lbn, bpref, size, flags, cred, bnp) struct inode *ip; ufs2_daddr_t lbn, bpref; - int size; + int size, flags; struct ucred *cred; ufs2_daddr_t *bnp; { @@ -191,7 +191,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; *bnp = bno; return (0); } @@ -227,12 +230,12 @@ nospace: * invoked to get an appropriate block. */ int -ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, cred, bpp) +ffs_realloccg(ip, lbprev, bprev, bpref, osize, nsize, flags, cred, bpp) struct inode *ip; ufs2_daddr_t lbprev; ufs2_daddr_t bprev; ufs2_daddr_t bpref; - int osize, nsize; + int osize, nsize, flags; struct ucred *cred; struct buf **bpp; { @@ -317,7 +320,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); bp->b_flags |= B_DONE; if ((bp->b_flags & (B_MALLOC | B_VMIO)) != B_VMIO) @@ -392,7 +398,10 @@ retry: UFS_UNLOCK(ump); } DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + delta); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + if (flags & IO_EXT) + ip->i_flag |= IN_CHANGE; + else + ip->i_flag |= IN_CHANGE | IN_UPDATE; allocbuf(bp, nsize); bp->b_flags |= B_DONE; if ((bp->b_flags & (B_MALLOC | B_VMIO)) != B_VMIO) diff --git a/sys/ufs/ffs/ffs_balloc.c b/sys/ufs/ffs/ffs_balloc.c index 0bd895f..a12f96e 100644 --- a/sys/ufs/ffs/ffs_balloc.c +++ b/sys/ufs/ffs/ffs_balloc.c @@ -133,7 +133,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_realloccg(ip, nb, dp->di_db[nb], ffs_blkpref_ufs1(ip, lastlbn, (int)nb, - &dp->di_db[0]), osize, (int)fs->fs_bsize, cred, &bp); + &dp->di_db[0]), osize, (int)fs->fs_bsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -184,7 +185,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_realloccg(ip, lbn, dp->di_db[lbn], ffs_blkpref_ufs1(ip, lbn, (int)lbn, - &dp->di_db[0]), osize, nsize, cred, &bp); + &dp->di_db[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -200,7 +202,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs1(ip, lbn, (int)lbn, &dp->di_db[0]), - nsize, cred, &newb); + nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, lbn, nsize, 0, 0, 0); @@ -241,7 +243,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0); if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, - cred, &newb)) != 0) { + flags, cred, &newb)) != 0) { curthread->td_pflags &= saved_inbdflush; return (error); } @@ -291,8 +293,8 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); if (pref == 0) pref = ffs_blkpref_ufs1(ip, lbn, 0, (ufs1_daddr_t *)0); - if ((error = - ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) { + if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, + flags, cred, &newb)) != 0) { brelse(bp); goto fail; } @@ -346,7 +348,7 @@ ffs_balloc_ufs1(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); pref = ffs_blkpref_ufs1(ip, lbn, indirs[i].in_off, &bap[0]); error = ffs_alloc(ip, - lbn, pref, (int)fs->fs_bsize, cred, &newb); + lbn, pref, (int)fs->fs_bsize, flags, cred, &newb); if (error) { brelse(bp); goto fail; @@ -534,7 +536,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, dp->di_extb[nb], ffs_blkpref_ufs2(ip, lastlbn, (int)nb, &dp->di_extb[0]), osize, - (int)fs->fs_bsize, cred, &bp); + (int)fs->fs_bsize, flags, cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -545,7 +547,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, dp->di_extsize = smalllblktosize(fs, nb + 1); dp->di_extb[nb] = dbtofsb(fs, bp->b_blkno); bp->b_xflags |= BX_ALTDATA; - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; if (flags & IO_SYNC) bwrite(bp); else @@ -588,7 +590,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, error = ffs_realloccg(ip, -1 - lbn, dp->di_extb[lbn], ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_extb[0]), osize, nsize, cred, &bp); + &dp->di_extb[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); bp->b_xflags |= BX_ALTDATA; @@ -605,7 +608,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs2(ip, lbn, (int)lbn, &dp->di_extb[0]), - nsize, cred, &newb); + nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, -1 - lbn, nsize, 0, 0, 0); @@ -618,7 +621,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, nsize, 0, bp); } dp->di_extb[lbn] = dbtofsb(fs, bp->b_blkno); - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; *bpp = bp; return (0); } @@ -636,7 +639,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, error = ffs_realloccg(ip, nb, dp->di_db[nb], ffs_blkpref_ufs2(ip, lastlbn, (int)nb, &dp->di_db[0]), osize, (int)fs->fs_bsize, - cred, &bp); + flags, cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -688,7 +691,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_realloccg(ip, lbn, dp->di_db[lbn], ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_db[0]), osize, nsize, cred, &bp); + &dp->di_db[0]), osize, nsize, flags, + cred, &bp); if (error) return (error); if (DOINGSOFTDEP(vp)) @@ -704,7 +708,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); error = ffs_alloc(ip, lbn, ffs_blkpref_ufs2(ip, lbn, (int)lbn, - &dp->di_db[0]), nsize, cred, &newb); + &dp->di_db[0]), nsize, flags, cred, &newb); if (error) return (error); bp = getblk(vp, lbn, nsize, 0, 0, 0); @@ -745,7 +749,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0); if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, - cred, &newb)) != 0) { + flags, cred, &newb)) != 0) { curthread->td_pflags &= saved_inbdflush; return (error); } @@ -795,8 +799,8 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); if (pref == 0) pref = ffs_blkpref_ufs2(ip, lbn, 0, (ufs2_daddr_t *)0); - if ((error = - ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, cred, &newb)) != 0) { + if ((error = ffs_alloc(ip, lbn, pref, (int)fs->fs_bsize, + flags, cred, &newb)) != 0) { brelse(bp); goto fail; } @@ -850,7 +854,7 @@ ffs_balloc_ufs2(struct vnode *vp, off_t startoffset, int size, UFS_LOCK(ump); pref = ffs_blkpref_ufs2(ip, lbn, indirs[i].in_off, &bap[0]); error = ffs_alloc(ip, - lbn, pref, (int)fs->fs_bsize, cred, &newb); + lbn, pref, (int)fs->fs_bsize, flags, cred, &newb); if (error) { brelse(bp); goto fail; diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h index 4a2f3a2..7e32ced 100644 --- a/sys/ufs/ffs/ffs_extern.h +++ b/sys/ufs/ffs/ffs_extern.h @@ -48,8 +48,8 @@ struct vnode; struct vop_fsync_args; struct vop_reallocblks_args; -int ffs_alloc(struct inode *, - ufs2_daddr_t, ufs2_daddr_t, int, struct ucred *, ufs2_daddr_t *); +int ffs_alloc(struct inode *, ufs2_daddr_t, ufs2_daddr_t, int, int, + struct ucred *, ufs2_daddr_t *); int ffs_balloc_ufs1(struct vnode *a_vp, off_t a_startoffset, int a_size, struct ucred *a_cred, int a_flags, struct buf **a_bpp); int ffs_balloc_ufs2(struct vnode *a_vp, off_t a_startoffset, int a_size, @@ -72,7 +72,7 @@ void ffs_load_inode(struct buf *, struct inode *, struct fs *, ino_t); int ffs_mountroot(void); int ffs_reallocblks(struct vop_reallocblks_args *); int ffs_realloccg(struct inode *, ufs2_daddr_t, ufs2_daddr_t, - ufs2_daddr_t, int, int, struct ucred *, struct buf **); + ufs2_daddr_t, int, int, int, struct ucred *, struct buf **); int ffs_sbupdate(struct ufsmount *, int, int); void ffs_setblock(struct fs *, u_char *, ufs1_daddr_t); int ffs_snapblkfree(struct fs *, struct vnode *, ufs2_daddr_t, long, ino_t); diff --git a/sys/ufs/ffs/ffs_inode.c b/sys/ufs/ffs/ffs_inode.c index e6269b6..b2f9067 100644 --- a/sys/ufs/ffs/ffs_inode.c +++ b/sys/ufs/ffs/ffs_inode.c @@ -225,7 +225,7 @@ ffs_truncate(vp, length, flags, cred, td) oldblks[i] = ip->i_din2->di_extb[i]; ip->i_din2->di_extb[i] = 0; } - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; if ((error = ffs_update(vp, 1))) return (error); for (i = 0; i < NXADDR; i++) { diff --git a/sys/ufs/ffs/ffs_vnops.c b/sys/ufs/ffs/ffs_vnops.c index e5b3ffe..ca2efa6 100644 --- a/sys/ufs/ffs/ffs_vnops.c +++ b/sys/ufs/ffs/ffs_vnops.c @@ -1006,14 +1006,6 @@ ffs_extread(struct vnode *vp, struct uio *uio, int ioflag) bqrelse(bp); } } - - if ((error == 0 || uio->uio_resid != orig_resid) && - (vp->v_mount->mnt_flag & MNT_NOATIME) == 0 && - (ip->i_flag & IN_ACCESS) == 0) { - VI_LOCK(vp); - ip->i_flag |= IN_ACCESS; - VI_UNLOCK(vp); - } return (error); } @@ -1119,7 +1111,7 @@ ffs_extwrite(struct vnode *vp, struct uio *uio, int ioflag, struct ucred *ucred) bdwrite(bp); if (error || xfersize == 0) break; - ip->i_flag |= IN_CHANGE | IN_UPDATE; + ip->i_flag |= IN_CHANGE; } /* * If we successfully wrote any data, and we are not the superuser -- cgit v1.1 From d27cdd2fdd1b3c6f17b9a97f484bca9fad2760df Mon Sep 17 00:00:00 2001 From: trasz Date: Thu, 29 Jan 2009 16:47:15 +0000 Subject: Make sure the cdev doesn't go away while the filesystem is still mounted. Otherwise dev2udev() could return garbage. Reviewed by: kib Approved by: rwatson (mentor) Sponsored by: FreeBSD Foundation --- sys/ufs/ffs/ffs_vfsops.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index d5a1a4f..b9ad090 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -641,6 +641,7 @@ ffs_mountfs(devvp, mp, td) VOP_UNLOCK(devvp, 0); if (error) return (error); + dev_ref(dev); if (devvp->v_rdev->si_iosize_max != 0) mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max; if (mp->mnt_iosize_max > MAXPHYS) @@ -921,6 +922,7 @@ out: free(ump, M_UFSMNT); mp->mnt_data = NULL; } + dev_rel(dev); return (error); } @@ -1107,6 +1109,7 @@ ffs_unmount(mp, mntflags, td) g_topology_unlock(); PICKUP_GIANT(); vrele(ump->um_devvp); + dev_rel(ump->um_dev); mtx_destroy(UFS_MTX(ump)); if (mp->mnt_gjprovider != NULL) { free(mp->mnt_gjprovider, M_UFSMNT); -- cgit v1.1 From e0aa6f81f98bad4fc91bab83c82424bcfd95feed Mon Sep 17 00:00:00 2001 From: trasz Date: Fri, 6 Feb 2009 17:14:07 +0000 Subject: When a device containing mounted UFS filesystem disappears, the type of devvp becomes VBAD, which UFS incorrectly interprets as snapshot vnode, which in turns causes panic. Fix it by replacing '!= VCHR' with '== VREG'. With this fix in place, you should no longer be able to panic the system by removing a device with an UFS filesystem mounted from it - assuming you don't use softupdates. Reviewed by: kib Tested by: pho Approved by: rwatson (mentor) Sponsored by: FreeBSD Foundation --- sys/ufs/ffs/ffs_alloc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c index e21a484..4748f68 100644 --- a/sys/ufs/ffs/ffs_alloc.c +++ b/sys/ufs/ffs/ffs_alloc.c @@ -1858,7 +1858,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum) struct cdev *dev; cg = dtog(fs, bno); - if (devvp->v_type != VCHR) { + if (devvp->v_type == VREG) { /* devvp is a snapshot */ dev = VTOI(devvp)->i_devvp->v_rdev; cgblkno = fragstoblks(fs, cgtod(fs, cg)); @@ -1903,7 +1903,7 @@ ffs_blkfree(ump, fs, devvp, bno, size, inum) if (size == fs->fs_bsize) { fragno = fragstoblks(fs, cgbno); if (!ffs_isfreeblock(fs, blksfree, fragno)) { - if (devvp->v_type != VCHR) { + if (devvp->v_type == VREG) { UFS_UNLOCK(ump); /* devvp is a snapshot */ brelse(bp); @@ -2056,7 +2056,7 @@ ffs_freefile(ump, fs, devvp, ino, mode) struct cdev *dev; cg = ino_to_cg(fs, ino); - if (devvp->v_type != VCHR) { + if (devvp->v_type == VREG) { /* devvp is a snapshot */ dev = VTOI(devvp)->i_devvp->v_rdev; cgbno = fragstoblks(fs, cgtod(fs, cg)); @@ -2122,7 +2122,7 @@ ffs_checkfreefile(fs, devvp, ino) u_int8_t *inosused; cg = ino_to_cg(fs, ino); - if (devvp->v_type != VCHR) { + if (devvp->v_type == VREG) { /* devvp is a snapshot */ cgbno = fragstoblks(fs, cgtod(fs, cg)); } else { -- cgit v1.1 From 6f82ac1ceb31d819ced6b5f2a93db4518a1805d7 Mon Sep 17 00:00:00 2001 From: jhb Date: Wed, 11 Feb 2009 22:19:54 +0000 Subject: - If the g_access() call for the initial root mount fails, then fully cleanup. Before the GEOM consumer would not have been closed. - Bump the reference on the character device being mounted while the associated devfs vnode is locked. Reviewed by: kib --- sys/ufs/ffs/ffs_vfsops.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'sys/ufs') diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index b9ad090..95dbeb1 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -622,10 +622,13 @@ ffs_mountfs(devvp, mp, td) struct g_consumer *cp; struct mount *nmp; - dev = devvp->v_rdev; + bp = NULL; + ump = NULL; cred = td ? td->td_ucred : NOCRED; - ronly = (mp->mnt_flag & MNT_RDONLY) != 0; + + dev = devvp->v_rdev; + dev_ref(dev); DROP_GIANT(); g_topology_lock(); error = g_vfs_open(devvp, &cp, "ffs", ronly ? 0 : 1); @@ -640,8 +643,7 @@ ffs_mountfs(devvp, mp, td) PICKUP_GIANT(); VOP_UNLOCK(devvp, 0); if (error) - return (error); - dev_ref(dev); + goto out; if (devvp->v_rdev->si_iosize_max != 0) mp->mnt_iosize_max = devvp->v_rdev->si_iosize_max; if (mp->mnt_iosize_max > MAXPHYS) @@ -650,8 +652,6 @@ ffs_mountfs(devvp, mp, td) devvp->v_bufobj.bo_private = cp; devvp->v_bufobj.bo_ops = &ffs_ops; - bp = NULL; - ump = NULL; fs = NULL; sblockloc = 0; /* -- cgit v1.1