The branch stable/13 has been updated by mckusick:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=654e91791ba3230bf26954d3ac1af6848702e4e6

commit 654e91791ba3230bf26954d3ac1af6848702e4e6
Author:     Kirk McKusick <mckus...@freebsd.org>
AuthorDate: 2021-07-29 23:11:58 +0000
Commit:     Kirk McKusick <mckus...@freebsd.org>
CommitDate: 2021-08-13 17:37:26 +0000

    Clean up orphaned indirdep dependency structures after disk failure.
    
    (cherry picked from commit 412b5e40a721430adba1b4abae210641f733f976)
    (cherry picked from commit a91716efeb684c50289c0e1136f5432f880dc873)
---
 sys/ufs/ffs/ffs_softdep.c | 54 +++++++++++++++++++++++++++++++++++++++++------
 sys/ufs/ffs/softdep.h     |  4 +---
 2 files changed, 49 insertions(+), 9 deletions(-)

diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c
index 446fc69a6a32..c53ba7c70d2f 100644
--- a/sys/ufs/ffs/ffs_softdep.c
+++ b/sys/ufs/ffs/ffs_softdep.c
@@ -1233,9 +1233,7 @@ workitem_free(item, type)
            ump->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
        atomic_subtract_long(&dep_current[item->wk_type], 1);
        ump->softdep_curdeps[item->wk_type] -= 1;
-#ifdef INVARIANTS
        LIST_REMOVE(item, wk_all);
-#endif
        free(item, DtoM(type));
 }
 
@@ -1262,9 +1260,7 @@ workitem_alloc(item, type, mp)
        ump->softdep_curdeps[type] += 1;
        ump->softdep_deps++;
        ump->softdep_accdeps++;
-#ifdef INVARIANTS
        LIST_INSERT_HEAD(&ump->softdep_alldeps[type], item, wk_all);
-#endif
        FREE_LOCK(ump);
 }
 
@@ -1293,6 +1289,8 @@ workitem_reassign(item, newtype)
        dep_total[newtype]++;
        FREE_GBLLOCK(&lk);
        item->wk_type = newtype;
+       LIST_REMOVE(item, wk_all);
+       LIST_INSERT_HEAD(&ump->softdep_alldeps[newtype], item, wk_all);
 }
 
 /*
@@ -2710,10 +2708,8 @@ softdep_mount(devvp, mp, fs, cred)
        ump->indir_hash_size = i - 1;
        for (i = 0; i <= ump->indir_hash_size; i++)
                TAILQ_INIT(&ump->indir_hashtbl[i]);
-#ifdef INVARIANTS
        for (i = 0; i <= D_LAST; i++)
                LIST_INIT(&ump->softdep_alldeps[i]);
-#endif
        ACQUIRE_GBLLOCK(&lk);
        TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
        FREE_GBLLOCK(&lk);
@@ -14765,9 +14761,12 @@ softdep_check_suspend(struct mount *mp,
                      int secondary_writes,
                      int secondary_accwrites)
 {
+       struct buf *bp;
        struct bufobj *bo;
        struct ufsmount *ump;
        struct inodedep *inodedep;
+       struct indirdep *indirdep;
+       struct worklist *wk, *nextwk;
        int error, unlinked;
 
        bo = &devvp->v_bufobj;
@@ -14843,9 +14842,52 @@ softdep_check_suspend(struct mount *mp,
                }
        }
 
+       /*
+        * XXX Check for orphaned indirdep dependency structures.
+        *
+        * During forcible unmount after a disk failure there is a
+        * bug that causes one or more indirdep dependency structures
+        * to fail to be deallocated. We check for them here and clean
+        * them up so that the unmount can succeed.
+        */
+       if ((ump->um_flags & UM_FSFAIL_CLEANUP) != 0 && ump->softdep_deps > 0 &&
+           ump->softdep_deps == ump->softdep_curdeps[D_INDIRDEP]) {
+               LIST_FOREACH_SAFE(wk, &ump->softdep_alldeps[D_INDIRDEP],
+                   wk_all, nextwk) {
+                       indirdep = WK_INDIRDEP(wk);
+                       if ((indirdep->ir_state & (GOINGAWAY | DEPCOMPLETE)) !=
+                           (GOINGAWAY | DEPCOMPLETE) ||
+                           !TAILQ_EMPTY(&indirdep->ir_trunc) ||
+                           !LIST_EMPTY(&indirdep->ir_completehd) ||
+                           !LIST_EMPTY(&indirdep->ir_writehd) ||
+                           !LIST_EMPTY(&indirdep->ir_donehd) ||
+                           !LIST_EMPTY(&indirdep->ir_deplisthd) ||
+                           indirdep->ir_saveddata != NULL ||
+                           indirdep->ir_savebp == NULL) {
+                               printf("%s: skipping orphaned indirdep %p\n",
+                                   __FUNCTION__, indirdep);
+                               continue;
+                       }
+                       printf("%s: freeing orphaned indirdep %p\n",
+                           __FUNCTION__, indirdep);
+                       bp = indirdep->ir_savebp;
+                       indirdep->ir_savebp = NULL;
+                       free_indirdep(indirdep);
+                       FREE_LOCK(ump);
+                       brelse(bp);
+                       while (!TRY_ACQUIRE_LOCK(ump)) {
+                               BO_UNLOCK(bo);
+                               ACQUIRE_LOCK(ump);
+                               FREE_LOCK(ump);
+                               BO_LOCK(bo);
+                       }
+               }
+       }
+
        /*
         * Reasons for needing more work before suspend:
         * - Dirty buffers on devvp.
+        * - Dependency structures still exist
         * - Softdep activity occurred after start of vnode sync loop
         * - Secondary writes occurred after start of vnode sync loop
         */
diff --git a/sys/ufs/ffs/softdep.h b/sys/ufs/ffs/softdep.h
index 3493aadafc98..41728be3ec0f 100644
--- a/sys/ufs/ffs/softdep.h
+++ b/sys/ufs/ffs/softdep.h
@@ -213,10 +213,10 @@ struct worklist {
        struct mount            *wk_mp;         /* Mount we live in */
        unsigned int            wk_type:8,      /* type of request */
                                wk_state:24;    /* state flags */
+       LIST_ENTRY(worklist)    wk_all;         /* list of deps of this type */
 #ifdef INVARIANTS
        const char              *wk_func;       /* func where added / removed */
        int                     wk_line;        /* line where added / removed */
-       LIST_ENTRY(worklist)    wk_all;         /* list of deps of this type */
 #endif
 };
 #define        WK_DATA(wk) ((void *)(wk))
@@ -1075,9 +1075,7 @@ struct mount_softdeps {
        TAILQ_ENTRY(mount_softdeps) sd_next;    /* List of softdep filesystem */
        struct  ufsmount *sd_ump;               /* our ufsmount structure */
        u_long  sd_curdeps[D_LAST + 1];         /* count of current deps */
-#ifdef INVARIANTS
        struct  workhead sd_alldeps[D_LAST + 1];/* Lists of all deps */
-#endif
 };
 /*
  * Flags for communicating with the syncer thread.
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to