summaryrefslogtreecommitdiffstats
path: root/sys/ufs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-08-28 09:18:20 +0000
committerkib <kib@FreeBSD.org>2008-08-28 09:18:20 +0000
commit2a5baa49d2b2d537072a458d7e86c120a59acc67 (patch)
treeaf27bf91f7ed54bb0a2f56fc820400ae397a64c6 /sys/ufs
parentdd53532f9375b0bc12ccefe8249b0f02d0ea09c4 (diff)
downloadFreeBSD-src-2a5baa49d2b2d537072a458d7e86c120a59acc67.zip
FreeBSD-src-2a5baa49d2b2d537072a458d7e86c120a59acc67.tar.gz
Softdep code may need to instantiate vnode when processing
dependencies. In particular, it may need this while syncing filesystem being unmounted. Since during unmount MNTK_NOINSMNTQUE flag is set, that could sometimes disallow insertion of the vnode into the vnode mount list, softdep code needs to overwrite the MNTK_NOINSMNTQUE flag. Create the ffs_vgetf() function that sets the VV_FORCEINSMQ flag for new vnode and use it consistently from the softdep code instead of ffs_vget(). Add the retry logic to the softdep_flushfiles() to flush the vnodes that could be instantiated while flushing softdep dependencies. Tested by: pho, kris Reviewed by: tegge MFC after: 1 month
Diffstat (limited to 'sys/ufs')
-rw-r--r--sys/ufs/ffs/ffs_extern.h3
-rw-r--r--sys/ufs/ffs/ffs_softdep.c57
-rw-r--r--sys/ufs/ffs/ffs_vfsops.c14
3 files changed, 59 insertions, 15 deletions
diff --git a/sys/ufs/ffs/ffs_extern.h b/sys/ufs/ffs/ffs_extern.h
index 67986c1..22afbaa 100644
--- a/sys/ufs/ffs/ffs_extern.h
+++ b/sys/ufs/ffs/ffs_extern.h
@@ -87,6 +87,9 @@ int ffs_valloc(struct vnode *, int, struct ucred *, struct vnode **);
int ffs_vfree(struct vnode *, ino_t, int);
vfs_vget_t ffs_vget;
+int ffs_vgetf(struct mount *, ino_t, int, struct vnode **, int);
+
+#define FFSV_FORCEINSMQ 0x0001
extern struct vop_vector ffs_vnodeops1;
extern struct vop_vector ffs_fifoops1;
diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index e4c0def..2475bb3 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -913,8 +913,8 @@ process_worklist_item(mp, flags)
wk->wk_state |= INPROGRESS;
ump->softdep_on_worklist_inprogress++;
FREE_LOCK(&lk);
- ffs_vget(mp, WK_DIRREM(wk)->dm_oldinum,
- LK_NOWAIT | LK_EXCLUSIVE, &vp);
+ ffs_vgetf(mp, WK_DIRREM(wk)->dm_oldinum,
+ LK_NOWAIT | LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ);
ACQUIRE_LOCK(&lk);
wk->wk_state &= ~INPROGRESS;
ump->softdep_on_worklist_inprogress--;
@@ -1068,8 +1068,11 @@ softdep_flushfiles(oldmnt, flags, td)
int flags;
struct thread *td;
{
- int error, count, loopcnt;
+ int error, depcount, loopcnt, retry_flush_count, retry;
+ loopcnt = 10;
+ retry_flush_count = 3;
+retry_flush:
error = 0;
/*
@@ -1078,15 +1081,15 @@ softdep_flushfiles(oldmnt, flags, td)
* creates. In theory, this loop can happen at most twice,
* but we give it a few extra just to be sure.
*/
- for (loopcnt = 10; loopcnt > 0; loopcnt--) {
+ for (; loopcnt > 0; loopcnt--) {
/*
* Do another flush in case any vnodes were brought in
* as part of the cleanup operations.
*/
if ((error = ffs_flushfiles(oldmnt, flags, td)) != 0)
break;
- if ((error = softdep_flushworklist(oldmnt, &count, td)) != 0 ||
- count == 0)
+ if ((error = softdep_flushworklist(oldmnt, &depcount, td)) != 0 ||
+ depcount == 0)
break;
}
/*
@@ -1101,6 +1104,24 @@ softdep_flushfiles(oldmnt, flags, td)
}
if (!error)
error = softdep_waitidle(oldmnt);
+ if (!error) {
+ if (oldmnt->mnt_kern_flag & MNTK_UNMOUNT) {
+ retry = 0;
+ MNT_ILOCK(oldmnt);
+ KASSERT((oldmnt->mnt_kern_flag & MNTK_NOINSMNTQ) != 0,
+ ("softdep_flushfiles: !MNTK_NOINSMNTQ"));
+ if (oldmnt->mnt_nvnodelistsize > 0) {
+ if (--retry_flush_count > 0) {
+ retry = 1;
+ loopcnt = 3;
+ } else
+ error = EBUSY;
+ }
+ MNT_IUNLOCK(oldmnt);
+ if (retry)
+ goto retry_flush;
+ }
+ }
return (error);
}
@@ -2770,8 +2791,9 @@ handle_workitem_freeblocks(freeblks, flags)
*/
if (freeblks->fb_chkcnt != blocksreleased &&
(fs->fs_flags & FS_UNCLEAN) != 0 &&
- ffs_vget(freeblks->fb_list.wk_mp, freeblks->fb_previousinum,
- (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp) == 0) {
+ ffs_vgetf(freeblks->fb_list.wk_mp, freeblks->fb_previousinum,
+ (flags & LK_NOWAIT) | LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ)
+ == 0) {
ip = VTOI(vp);
DIP_SET(ip, i_blocks, DIP(ip, i_blocks) + \
freeblks->fb_chkcnt - blocksreleased);
@@ -3558,8 +3580,8 @@ handle_workitem_remove(dirrem, xp)
int error;
if ((vp = xp) == NULL &&
- (error = ffs_vget(dirrem->dm_list.wk_mp,
- dirrem->dm_oldinum, LK_EXCLUSIVE, &vp)) != 0) {
+ (error = ffs_vgetf(dirrem->dm_list.wk_mp,
+ dirrem->dm_oldinum, LK_EXCLUSIVE, &vp, FFSV_FORCEINSMQ)) != 0) {
softdep_error("handle_workitem_remove: vget", error);
return;
}
@@ -5074,9 +5096,11 @@ softdep_fsync(vp)
* for details on possible races.
*/
FREE_LOCK(&lk);
- if (ffs_vget(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp)) {
+ if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp,
+ FFSV_FORCEINSMQ)) {
VOP_UNLOCK(vp, 0);
- error = ffs_vget(mp, parentino, LK_EXCLUSIVE, &pvp);
+ error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE,
+ &pvp, FFSV_FORCEINSMQ);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
if (error != 0)
return (error);
@@ -5581,7 +5605,8 @@ flush_pagedep_deps(pvp, mp, diraddhdp)
inum = dap->da_newinum;
if (dap->da_state & MKDIR_BODY) {
FREE_LOCK(&lk);
- if ((error = ffs_vget(mp, inum, LK_EXCLUSIVE, &vp)))
+ if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp,
+ FFSV_FORCEINSMQ)))
break;
if ((error=ffs_syncvnode(vp, MNT_NOWAIT)) ||
(error=ffs_syncvnode(vp, MNT_NOWAIT))) {
@@ -5921,7 +5946,8 @@ clear_remove(td)
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
FREE_LOCK(&lk);
- if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp))) {
+ if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
+ FFSV_FORCEINSMQ))) {
softdep_error("clear_remove: vget", error);
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
@@ -5993,7 +6019,8 @@ clear_inodedeps(td)
if (vn_start_write(NULL, &mp, V_NOWAIT) != 0)
continue;
FREE_LOCK(&lk);
- if ((error = ffs_vget(mp, ino, LK_EXCLUSIVE, &vp)) != 0) {
+ if ((error = ffs_vgetf(mp, ino, LK_EXCLUSIVE, &vp,
+ FFSV_FORCEINSMQ)) != 0) {
softdep_error("clear_inodedeps: vget", error);
vn_finished_write(mp);
ACQUIRE_LOCK(&lk);
diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c
index 5ee123a..91cd7cf 100644
--- a/sys/ufs/ffs/ffs_vfsops.c
+++ b/sys/ufs/ffs/ffs_vfsops.c
@@ -1296,6 +1296,17 @@ ffs_vget(mp, ino, flags, vpp)
int flags;
struct vnode **vpp;
{
+ return (ffs_vgetf(mp, ino, flags, vpp, 0));
+}
+
+int
+ffs_vgetf(mp, ino, flags, vpp, ffs_flags)
+ struct mount *mp;
+ ino_t ino;
+ int flags;
+ struct vnode **vpp;
+ int ffs_flags;
+{
struct fs *fs;
struct inode *ip;
struct ufsmount *ump;
@@ -1368,12 +1379,15 @@ ffs_vget(mp, ino, flags, vpp)
#endif
lockmgr(vp->v_vnlock, LK_EXCLUSIVE, NULL);
+ if (ffs_flags & FFSV_FORCEINSMQ)
+ vp->v_vflag |= VV_FORCEINSMQ;
error = insmntque(vp, mp);
if (error != 0) {
uma_zfree(uma_inode, ip);
*vpp = NULL;
return (error);
}
+ vp->v_vflag &= ~VV_FORCEINSMQ;
error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL);
if (error || *vpp != NULL)
return (error);
OpenPOWER on IntegriCloud