diff --git a/sys/ufs/ffs/ffs_softdep.c b/sys/ufs/ffs/ffs_softdep.c index b666c0f..01232f1 100644 --- a/sys/ufs/ffs/ffs_softdep.c +++ b/sys/ufs/ffs/ffs_softdep.c @@ -2270,7 +2270,6 @@ journal_mount(mp, fs, cred) int error; int i; - mp->mnt_kern_flag |= MNTK_SUJ; error = softdep_journal_lookup(mp, &vp); if (error != 0) { printf("Failed to find journal. Use tunefs to create one\n"); @@ -2295,20 +2294,26 @@ journal_mount(mp, fs, cred) } jblocks->jb_low = jblocks->jb_free / 3; /* Reserve 33%. */ jblocks->jb_min = jblocks->jb_free / 10; /* Suspend at 10%. */ - /* - * Only validate the journal contents if the filesystem is clean, - * otherwise we write the logs but they'll never be used. If the - * filesystem was still dirty when we mounted it the journal is - * invalid and a new journal can only be valid if it starts from a - * clean mount. - */ - if (fs->fs_clean) { - DIP_SET(ip, i_modrev, fs->fs_mtime); - ip->i_flags |= IN_MODIFIED; - ffs_update(vp, 1); - } VFSTOUFS(mp)->softdep_jblocks = jblocks; out: + if (error == 0) { + MNT_ILOCK(mp); + mp->mnt_kern_flag |= MNTK_SUJ; + MNT_IUNLOCK(mp); + /* + * Only validate the journal contents if the + * filesystem is clean, otherwise we write the logs + * but they'll never be used. If the filesystem was + * still dirty when we mounted it the journal is + * invalid and a new journal can only be valid if it + * starts from a clean mount. + */ + if (fs->fs_clean) { + DIP_SET(ip, i_modrev, fs->fs_mtime); + ip->i_flags |= IN_MODIFIED; + ffs_update(vp, 1); + } + } vput(vp); return (error); } @@ -6048,6 +6053,7 @@ indir_trunc(freework, dbn, lbn) struct jnewblk *jnewblk; struct freeblks *freeblks; struct buf *bp; + struct bufobj *bo; struct fs *fs; struct worklist *wkn; struct worklist *wk; @@ -6088,14 +6094,13 @@ indir_trunc(freework, dbn, lbn) * a complete copy of the indirect block in memory for our use. * Otherwise we have to read the blocks in from the disk. */ -#ifdef notyet - bp = getblk(freeblks->fb_devvp, dbn, (int)fs->fs_bsize, 0, 0, - GB_NOCREAT); -#else - bp = incore(&freeblks->fb_devvp->v_bufobj, dbn); -#endif + bo = &freeblks->fb_devvp->v_bufobj; +check_incore: ACQUIRE_LOCK(&lk); + BO_LOCK(bo); + bp = gbincore(bo, dbn); if (bp != NULL && (wk = LIST_FIRST(&bp->b_dep)) != NULL) { + BO_UNLOCK(bo); if (wk->wk_type != D_INDIRDEP || (wk->wk_state & GOINGAWAY) == 0) panic("indir_trunc: lost indirdep %p", wk); @@ -6108,15 +6113,34 @@ indir_trunc(freework, dbn, lbn) ump->um_numindirdeps -= 1; FREE_LOCK(&lk); } else { -#ifdef notyet - if (bp) - brelse(bp); -#endif FREE_LOCK(&lk); - if (bread(freeblks->fb_devvp, dbn, (int)fs->fs_bsize, - NOCRED, &bp) != 0) { - brelse(bp); - return; + if (bp != NULL) { + if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT | + LK_INTERLOCK, BO_MTX(bo)) != 0) { + pause("INDIRT", 1); + goto check_incore; + } + } else { + BO_UNLOCK(bo); + bp = getblk(freeblks->fb_devvp, dbn, fs->fs_bsize, 0, + 0, 0); + if (LIST_FIRST(&bp->b_dep) != NULL) { + brelse(bp); + goto check_incore; + } + } + + if ((bp->b_flags & B_CACHE) == 0) { + bp->b_iocmd = BIO_READ; + bp->b_flags &= ~B_INVAL; + bp->b_ioflags &= ~BIO_ERROR; + vfs_busy_pages(bp, 0); + bp->b_iooffset = dbtob(bp->b_blkno); + bstrategy(bp); + if (bufwait(bp) != 0) { + brelse(bp); + return; + } } } /* @@ -6770,7 +6791,8 @@ cancel_diradd(dap, dirrem, jremref, dotremref, dotdotremref) mkdir->md_jaddref = NULL; if (mkdir->md_state & MKDIR_PARENT) { if (cancel_jaddref(jaddref, NULL, - &dirrem->dm_jwork) == 0) { + &dirrem->dm_jwork) == 0 && + dotdotremref != NULL) { free_jremref(dotdotremref); dotdotremref = NULL; }