Page MenuHomeFreeBSD

D59356.id185857.diff
No OneTemporary

D59356.id185857.diff

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -712,7 +712,8 @@
static int flush_pagedep_deps(struct vnode *, struct mount *,
struct diraddhd *, struct buf *);
static int free_pagedep(struct pagedep *);
-static int flush_newblk_dep(struct vnode *, struct mount *, ufs_lbn_t);
+static int flush_newblk_dep(struct vnode *, struct mount *, ufs_lbn_t,
+ struct diradd *);
static int flush_inodedep_deps(struct vnode *, struct mount *, ino_t);
static int flush_deplist(struct allocdirectlst *, int, int *);
static int sync_cgs(struct mount *, int);
@@ -13210,13 +13211,16 @@
}
/*
- * Flush dependencies associated with an allocdirect block.
+ * Flush dependencies associated with an allocdirect block. The softdep
+ * lock must be held on entry and is released on return. The locked parent
+ * directory buffer keeps dap valid while the lock is dropped.
*/
static int
flush_newblk_dep(
struct vnode *vp,
struct mount *mp,
- ufs_lbn_t lbn)
+ ufs_lbn_t lbn,
+ struct diradd *dap)
{
struct newblk *newblk;
struct ufsmount *ump;
@@ -13233,14 +13237,23 @@
if (blkno == 0)
panic("flush_newblk_dep: Missing block");
ump = VFSTOUFS(mp);
- ACQUIRE_LOCK(ump);
+ LOCK_OWNED(ump);
+ KASSERT(dap->da_newinum == ip->i_number,
+ ("flush_newblk_dep: inode mismatch %ju != %ju",
+ (uintmax_t)dap->da_newinum, (uintmax_t)ip->i_number));
/*
* Loop until all dependencies related to this block are satisfied.
* We must be careful to restart after each sleep in case a write
* completes some part of this process for us.
*/
for (;;) {
- if (newblk_lookup(mp, blkno, 0, &newblk) == 0) {
+ /*
+ * The mkdir dependency may have completed while we dropped the
+ * lock. Its allocdirect may then have been freed, exposing an
+ * older dependency for a previous use of the same block number.
+ */
+ if ((dap->da_state & MKDIR_BODY) == 0 ||
+ newblk_lookup(mp, blkno, 0, &newblk) == 0) {
FREE_LOCK(ump);
break;
}
@@ -13328,9 +13341,19 @@
LIST_INIT(&unfinished);
ump = VFSTOUFS(mp);
+ vp = NULL;
LOCK_OWNED(ump);
restart:
while ((dap = LIST_FIRST(diraddhdp)) != NULL) {
+ /*
+ * Only retain a vnode while restarting the lookup of the same
+ * MKDIR_BODY dependency. Dropping it may change the dependency
+ * list, so restart again after vput().
+ */
+ if (vp != NULL &&
+ ((dap->da_state & (MKDIR_PARENT | MKDIR_BODY)) != MKDIR_BODY ||
+ VTOI(vp)->i_number != dap->da_newinum))
+ goto vput_restart;
/*
* Flush ourselves if this directory entry
* has a MKDIR_PARENT dependency.
@@ -13375,25 +13398,38 @@
TAILQ_FOREACH(inoref, &inodedep->id_inoreflst, if_deps) {
if ((inoref->if_state & (DEPCOMPLETE | GOINGAWAY))
== DEPCOMPLETE) {
+ if (vp != NULL)
+ goto vput_restart;
jwait(&inoref->if_list, MNT_WAIT);
goto restart;
}
}
if (dap->da_state & MKDIR_BODY) {
- FREE_LOCK(ump);
- error = get_parent_vp(pvp, mp, inum, locked_bp,
- diraddhdp, &unfinished, &vp);
- if (error != 0)
- break;
- error = flush_newblk_dep(vp, mp, 0);
+ if (vp == NULL) {
+ FREE_LOCK(ump);
+ error = get_parent_vp(pvp, mp, inum, locked_bp,
+ diraddhdp, &unfinished, &vp);
+ if (error != 0)
+ break;
+ ACQUIRE_LOCK(ump);
+ goto restart;
+ }
+ error = flush_newblk_dep(vp, mp, 0, dap);
/*
* If we still have the dependency we might need to
* update the vnode to sync the new link count to
* disk.
*/
- if (error == 0 && dap == LIST_FIRST(diraddhdp))
- error = ffs_update(vp, 1);
+ if (error == 0) {
+ ACQUIRE_LOCK(ump);
+ if (dap == LIST_FIRST(diraddhdp)) {
+ FREE_LOCK(ump);
+ error = ffs_update(vp, 1);
+ } else
+ FREE_LOCK(ump);
+ }
vput(vp);
+ vp = NULL;
if (error != 0)
break;
ACQUIRE_LOCK(ump);
@@ -13452,6 +13488,7 @@
break;
error = ffs_update(vp, 1);
vput(vp);
+ vp = NULL;
if (error)
break;
ACQUIRE_LOCK(ump);
@@ -13469,11 +13506,23 @@
}
if (error)
ACQUIRE_LOCK(ump);
+ if (vp != NULL) {
+ FREE_LOCK(ump);
+ vput(vp);
+ ACQUIRE_LOCK(ump);
+ }
while ((dap = LIST_FIRST(&unfinished)) != NULL) {
LIST_REMOVE(dap, da_pdlist);
LIST_INSERT_HEAD(diraddhdp, dap, da_pdlist);
}
return (error);
+
+vput_restart:
+ FREE_LOCK(ump);
+ vput(vp);
+ vp = NULL;
+ ACQUIRE_LOCK(ump);
+ goto restart;
}
/*

File Metadata

Mime Type
text/plain
Expires
Wed, Sep 9, 3:26 PM (3 h, 51 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
38353965
Default Alt Text
D59356.id185857.diff (4 KB)

Event Timeline