Page MenuHomeFreeBSD

D26136.id76043.diff
No OneTemporary

D26136.id76043.diff

Index: sys/ufs/ffs/ffs_snapshot.c
===================================================================
--- sys/ufs/ffs/ffs_snapshot.c
+++ sys/ufs/ffs/ffs_snapshot.c
@@ -368,8 +368,12 @@
if (error)
goto out;
bawrite(nbp);
- if (cg % 10 == 0)
- ffs_syncvnode(vp, MNT_WAIT, 0);
+ if (cg % 10 == 0) {
+ error = ffs_syncvnode(vp, MNT_WAIT, 0);
+ /* vp possibly reclaimed if unlocked */
+ if (error != 0)
+ goto out;
+ }
}
/*
* Copy all the cylinder group maps. Although the
@@ -391,8 +395,8 @@
goto out;
error = cgaccount(cg, vp, nbp, 1);
bawrite(nbp);
- if (cg % 10 == 0)
- ffs_syncvnode(vp, MNT_WAIT, 0);
+ if (cg % 10 == 0 && error == 0)
+ error = ffs_syncvnode(vp, MNT_WAIT, 0);
if (error)
goto out;
}
Index: sys/ufs/ffs/ffs_softdep.c
===================================================================
--- sys/ufs/ffs/ffs_softdep.c
+++ sys/ufs/ffs/ffs_softdep.c
@@ -748,7 +748,7 @@
static void clear_unlinked_inodedep(struct inodedep *);
static struct inodedep *first_unlinked_inodedep(struct ufsmount *);
static int flush_pagedep_deps(struct vnode *, struct mount *,
- struct diraddhd *);
+ 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_inodedep_deps(struct vnode *, struct mount *, ino_t);
@@ -1389,6 +1389,60 @@
/* List of all filesystems mounted with soft updates */
static TAILQ_HEAD(, mount_softdeps) softdepmounts;
+static int
+get_parent_vp(struct vnode *vp, struct mount *mp, ino_t inum, struct buf *bp,
+ struct vnode **rvp)
+{
+ struct vnode *pvp;
+ int error;
+
+ ASSERT_VOP_ELOCKED(vp, "child vnode must be locked");
+ for (;;) {
+ error = ffs_vgetf(mp, inum, LK_EXCLUSIVE | LK_NOWAIT, &pvp,
+ FFSV_FORCEINSMQ);
+ if (error == 0) {
+ KASSERT(VTOI(pvp)->i_mode != 0,
+ ("vnode %p/ino %jx is not fully constructed",
+ vp, (uintmax_t)inum));
+ *rvp = pvp;
+ return (0);
+ }
+ VOP_UNLOCK(vp);
+ if (bp != NULL) {
+ BUF_NOREC(bp);
+ BUF_UNLOCK(bp);
+ }
+ error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &pvp, FFSV_FORCEINSMQ);
+ if (error != 0) {
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ return (error);
+ }
+ KASSERT(VTOI(pvp)->i_mode != 0,
+ ("vnode %p/ino %jx is not fully constructed",
+ vp, (uintmax_t)inum));
+ error = vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT);
+ if (error == 0)
+ break;
+ vput(pvp);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+ if (VN_IS_DOOMED(vp))
+ return (ENOENT);
+ }
+ if (VN_IS_DOOMED(vp)) {
+ if (error == 0)
+ vput(pvp);
+ error = ENOENT;
+ }
+ if (bp != NULL) {
+ if (error == 0)
+ vput(pvp);
+ error = ERESTART;
+ }
+ if (error == 0)
+ *rvp = pvp;
+ return (error);
+}
+
/*
* This function cleans the worklist for a filesystem.
* Each filesystem running with soft dependencies gets its own
@@ -12629,25 +12683,9 @@
* for details on possible races.
*/
FREE_LOCK(ump);
- if (ffs_vgetf(mp, parentino, LK_NOWAIT | LK_EXCLUSIVE, &pvp,
- FFSV_FORCEINSMQ)) {
- /*
- * Unmount cannot proceed after unlock because
- * caller must have called vn_start_write().
- */
- VOP_UNLOCK(vp);
- error = ffs_vgetf(mp, parentino, LK_EXCLUSIVE,
- &pvp, FFSV_FORCEINSMQ);
- MPASS(VTOI(pvp)->i_mode != 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
- if (VN_IS_DOOMED(vp)) {
- if (error == 0)
- vput(pvp);
- error = ENOENT;
- }
- if (error != 0)
- return (error);
- }
+ error = get_parent_vp(vp, mp, parentino, NULL, &pvp);
+ if (error != 0)
+ return (error);
/*
* All MKDIR_PARENT dependencies and all the NEWBLOCK pagedeps
* that are contained in direct blocks will be resolved by
@@ -12972,9 +13010,11 @@
for (i = 0; i < DAHASHSZ; i++) {
if (LIST_FIRST(&pagedep->pd_diraddhd[i]) == 0)
continue;
- if ((error = flush_pagedep_deps(vp, wk->wk_mp,
- &pagedep->pd_diraddhd[i]))) {
- BUF_NOREC(bp);
+ error = flush_pagedep_deps(vp, wk->wk_mp,
+ &pagedep->pd_diraddhd[i], bp);
+ if (error != 0) {
+ if (error != ERESTART)
+ BUF_NOREC(bp);
goto out_unlock;
}
}
@@ -13208,10 +13248,11 @@
* Eliminate a pagedep dependency by flushing out all its diradd dependencies.
*/
static int
-flush_pagedep_deps(pvp, mp, diraddhdp)
+flush_pagedep_deps(pvp, mp, diraddhdp, locked_bp)
struct vnode *pvp;
struct mount *mp;
struct diraddhd *diraddhdp;
+ struct buf *locked_bp;
{
struct inodedep *inodedep;
struct inoref *inoref;
@@ -13278,10 +13319,9 @@
}
if (dap->da_state & MKDIR_BODY) {
FREE_LOCK(ump);
- if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp,
- FFSV_FORCEINSMQ)))
+ error = get_parent_vp(pvp, mp, inum, locked_bp, &vp);
+ if (error != 0)
break;
- MPASS(VTOI(vp)->i_mode != 0);
error = flush_newblk_dep(vp, mp, 0);
/*
* If we still have the dependency we might need to
@@ -13343,10 +13383,9 @@
*/
if (dap == LIST_FIRST(diraddhdp)) {
FREE_LOCK(ump);
- if ((error = ffs_vgetf(mp, inum, LK_EXCLUSIVE, &vp,
- FFSV_FORCEINSMQ)))
+ error = get_parent_vp(pvp, mp, inum, locked_bp, &vp);
+ if (error != 0)
break;
- MPASS(VTOI(vp)->i_mode != 0);
error = ffs_update(vp, 1);
vput(vp);
if (error)
Index: sys/ufs/ffs/ffs_vnops.c
===================================================================
--- sys/ufs/ffs/ffs_vnops.c
+++ sys/ufs/ffs/ffs_vnops.c
@@ -325,6 +325,9 @@
if (!LIST_EMPTY(&bp->b_dep) &&
(error = softdep_sync_buf(vp, bp,
wait ? MNT_WAIT : MNT_NOWAIT)) != 0) {
+ /* Lock order conflict, buffer was already unlocked. */
+ if (error == ERESTART)
+ goto next;
/* I/O error. */
if (error != EBUSY) {
BUF_UNLOCK(bp);

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 6, 11:03 PM (14 h, 46 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17021181
Default Alt Text
D26136.id76043.diff (5 KB)

Event Timeline