Path: blob/main/website/static/security/patches/EN-15:05/ufs.patch
18096 views
Index: sys/ufs/ffs/ffs_softdep.c1===================================================================2--- sys/ufs/ffs/ffs_softdep.c (revision 282245)3+++ sys/ufs/ffs/ffs_softdep.c (working copy)4@@ -735,9 +735,10 @@ static struct malloc_type *memtype[] = {5static void check_clear_deps(struct mount *);6static void softdep_error(char *, int);7static int softdep_process_worklist(struct mount *, int);8-static int softdep_waitidle(struct mount *);9+static int softdep_waitidle(struct mount *, int);10static void drain_output(struct vnode *);11static struct buf *getdirtybuf(struct buf *, struct rwlock *, int);12+static int check_inodedep_free(struct inodedep *);13static void clear_remove(struct mount *);14static void clear_inodedeps(struct mount *);15static void unlinked_inodedep(struct mount *, struct inodedep *);16@@ -1377,6 +1378,10 @@ softdep_flush(addr)17mp = (struct mount *)addr;18ump = VFSTOUFS(mp);19atomic_add_int(&stat_flush_threads, 1);20+ ACQUIRE_LOCK(ump);21+ ump->softdep_flags &= ~FLUSH_STARTING;22+ wakeup(&ump->softdep_flushtd);23+ FREE_LOCK(ump);24if (print_threads) {25if (stat_flush_threads == 1)26printf("Running %s at pid %d\n", bufdaemonproc->p_comm,27@@ -1389,7 +1394,7 @@ softdep_flush(addr)28VFSTOUFS(mp)->softdep_jblocks->jb_suspended))29kthread_suspend_check();30ACQUIRE_LOCK(ump);31- if ((ump->softdep_flags & FLUSH_CLEANUP) == 0)32+ if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)33msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM,34"sdflush", hz / 2);35ump->softdep_flags &= ~FLUSH_CLEANUP;36@@ -1419,11 +1424,9 @@ worklist_speedup(mp)3738ump = VFSTOUFS(mp);39LOCK_OWNED(ump);40- if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {41+ if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)42ump->softdep_flags |= FLUSH_CLEANUP;43- if (ump->softdep_flushtd->td_wchan == &ump->softdep_flushtd)44- wakeup(&ump->softdep_flushtd);45- }46+ wakeup(&ump->softdep_flushtd);47}4849static int50@@ -1468,14 +1471,10 @@ softdep_speedup(ump)51TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);52FREE_GBLLOCK(&lk);53if ((altump->softdep_flags &54- (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {55+ (FLUSH_CLEANUP | FLUSH_EXIT)) == 0)56altump->softdep_flags |= FLUSH_CLEANUP;57- altump->um_softdep->sd_cleanups++;58- if (altump->softdep_flushtd->td_wchan ==59- &altump->softdep_flushtd) {60- wakeup(&altump->softdep_flushtd);61- }62- }63+ altump->um_softdep->sd_cleanups++;64+ wakeup(&altump->softdep_flushtd);65FREE_LOCK(altump);66}67}68@@ -1887,8 +1886,8 @@ softdep_flushworklist(oldmnt, countp, td69struct thread *td;70{71struct vnode *devvp;72- int count, error = 0;73struct ufsmount *ump;74+ int count, error;7576/*77* Alternately flush the block device associated with the mount78@@ -1897,6 +1896,7 @@ softdep_flushworklist(oldmnt, countp, td79* are found.80*/81*countp = 0;82+ error = 0;83ump = VFSTOUFS(oldmnt);84devvp = ump->um_devvp;85while ((count = softdep_process_worklist(oldmnt, 1)) > 0) {86@@ -1904,36 +1904,47 @@ softdep_flushworklist(oldmnt, countp, td87vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);88error = VOP_FSYNC(devvp, MNT_WAIT, td);89VOP_UNLOCK(devvp, 0);90- if (error)91+ if (error != 0)92break;93}94return (error);95}9697+#define SU_WAITIDLE_RETRIES 2098static int99-softdep_waitidle(struct mount *mp)100+softdep_waitidle(struct mount *mp, int flags __unused)101{102struct ufsmount *ump;103- int error;104- int i;105+ struct vnode *devvp;106+ struct thread *td;107+ int error, i;108109ump = VFSTOUFS(mp);110+ devvp = ump->um_devvp;111+ td = curthread;112+ error = 0;113ACQUIRE_LOCK(ump);114- for (i = 0; i < 10 && ump->softdep_deps; i++) {115+ for (i = 0; i < SU_WAITIDLE_RETRIES && ump->softdep_deps != 0; i++) {116ump->softdep_req = 1;117- if (ump->softdep_on_worklist)118- panic("softdep_waitidle: work added after flush.");119- msleep(&ump->softdep_deps, LOCK_PTR(ump), PVM, "softdeps", 1);120+ KASSERT((flags & FORCECLOSE) == 0 ||121+ ump->softdep_on_worklist == 0,122+ ("softdep_waitidle: work added after flush"));123+ msleep(&ump->softdep_deps, LOCK_PTR(ump), PVM | PDROP,124+ "softdeps", 10 * hz);125+ vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);126+ error = VOP_FSYNC(devvp, MNT_WAIT, td);127+ VOP_UNLOCK(devvp, 0);128+ if (error != 0)129+ break;130+ ACQUIRE_LOCK(ump);131}132ump->softdep_req = 0;133- FREE_LOCK(ump);134- error = 0;135- if (i == 10) {136+ if (i == SU_WAITIDLE_RETRIES && error == 0 && ump->softdep_deps != 0) {137error = EBUSY;138printf("softdep_waitidle: Failed to flush worklist for %p\n",139mp);140}141-142+ FREE_LOCK(ump);143return (error);144}145146@@ -1990,7 +2001,7 @@ retry_flush:147error = EBUSY;148}149if (!error)150- error = softdep_waitidle(oldmnt);151+ error = softdep_waitidle(oldmnt, flags);152if (!error) {153if (oldmnt->mnt_kern_flag & MNTK_UNMOUNT) {154retry = 0;155@@ -2490,9 +2501,18 @@ softdep_mount(devvp, mp, fs, cred)156/*157* Start our flushing thread in the bufdaemon process.158*/159+ ACQUIRE_LOCK(ump);160+ ump->softdep_flags |= FLUSH_STARTING;161+ FREE_LOCK(ump);162kproc_kthread_add(&softdep_flush, mp, &bufdaemonproc,163&ump->softdep_flushtd, 0, 0, "softdepflush", "%s worker",164mp->mnt_stat.f_mntonname);165+ ACQUIRE_LOCK(ump);166+ while ((ump->softdep_flags & FLUSH_STARTING) != 0) {167+ msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM, "sdstart",168+ hz / 2);169+ }170+ FREE_LOCK(ump);171/*172* When doing soft updates, the counters in the173* superblock may have gotten out of sync. Recomputation174@@ -7629,17 +7649,13 @@ check_inode_unwritten(inodedep)175return (1);176}177178-/*179- * Try to free an inodedep structure. Return 1 if it could be freed.180- */181static int182-free_inodedep(inodedep)183+check_inodedep_free(inodedep)184struct inodedep *inodedep;185{186187LOCK_OWNED(VFSTOUFS(inodedep->id_list.wk_mp));188- if ((inodedep->id_state & (ONWORKLIST | UNLINKED)) != 0 ||189- (inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||190+ if ((inodedep->id_state & ALLCOMPLETE) != ALLCOMPLETE ||191!LIST_EMPTY(&inodedep->id_dirremhd) ||192!LIST_EMPTY(&inodedep->id_pendinghd) ||193!LIST_EMPTY(&inodedep->id_bufwait) ||194@@ -7654,6 +7670,21 @@ free_inodedep(inodedep)195inodedep->id_nlinkdelta != 0 ||196inodedep->id_savedino1 != NULL)197return (0);198+ return (1);199+}200+201+/*202+ * Try to free an inodedep structure. Return 1 if it could be freed.203+ */204+static int205+free_inodedep(inodedep)206+ struct inodedep *inodedep;207+{208+209+ LOCK_OWNED(VFSTOUFS(inodedep->id_list.wk_mp));210+ if ((inodedep->id_state & (ONWORKLIST | UNLINKED)) != 0 ||211+ !check_inodedep_free(inodedep))212+ return (0);213if (inodedep->id_state & ONDEPLIST)214LIST_REMOVE(inodedep, id_deps);215LIST_REMOVE(inodedep, id_hash);216@@ -13838,7 +13869,8 @@ softdep_check_suspend(struct mount *mp,217{218struct bufobj *bo;219struct ufsmount *ump;220- int error;221+ struct inodedep *inodedep;222+ int error, unlinked;223224bo = &devvp->v_bufobj;225ASSERT_BO_WLOCKED(bo);226@@ -13899,6 +13931,20 @@ softdep_check_suspend(struct mount *mp,227break;228}229230+ unlinked = 0;231+ if (MOUNTEDSUJ(mp)) {232+ for (inodedep = TAILQ_FIRST(&ump->softdep_unlinked);233+ inodedep != NULL;234+ inodedep = TAILQ_NEXT(inodedep, id_unlinked)) {235+ if ((inodedep->id_state & (UNLINKED | UNLINKLINKS |236+ UNLINKONLIST)) != (UNLINKED | UNLINKLINKS |237+ UNLINKONLIST) ||238+ !check_inodedep_free(inodedep))239+ continue;240+ unlinked++;241+ }242+ }243+244/*245* Reasons for needing more work before suspend:246* - Dirty buffers on devvp.247@@ -13908,8 +13954,8 @@ softdep_check_suspend(struct mount *mp,248error = 0;249if (bo->bo_numoutput > 0 ||250bo->bo_dirty.bv_cnt > 0 ||251- softdep_depcnt != 0 ||252- ump->softdep_deps != 0 ||253+ softdep_depcnt != unlinked ||254+ ump->softdep_deps != unlinked ||255softdep_accdepcnt != ump->softdep_accdeps ||256secondary_writes != 0 ||257mp->mnt_secondary_writes != 0 ||258Index: sys/ufs/ffs/ffs_vfsops.c259===================================================================260--- sys/ufs/ffs/ffs_vfsops.c (revision 282245)261+++ sys/ufs/ffs/ffs_vfsops.c (working copy)262@@ -1502,8 +1502,11 @@ ffs_sync(mp, waitfor)263if (fs->fs_fmod != 0 && fs->fs_ronly != 0 && ump->um_fsckpid == 0)264panic("%s: ffs_sync: modification on read-only filesystem",265fs->fs_fsmnt);266- if (waitfor == MNT_LAZY)267- return (ffs_sync_lazy(mp));268+ if (waitfor == MNT_LAZY) {269+ if (!rebooting)270+ return (ffs_sync_lazy(mp));271+ waitfor = MNT_NOWAIT;272+ }273274/*275* Write back each (modified) inode.276@@ -1560,7 +1563,7 @@ loop:277/*278* Force stale filesystem control information to be flushed.279*/280- if (waitfor == MNT_WAIT) {281+ if (waitfor == MNT_WAIT || rebooting) {282if ((error = softdep_flushworklist(ump->um_mountp, &count, td)))283allerror = error;284/* Flushed work items may create new vnodes to clean */285@@ -1577,9 +1580,12 @@ loop:286if (bo->bo_numoutput > 0 || bo->bo_dirty.bv_cnt > 0) {287BO_UNLOCK(bo);288vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);289- if ((error = VOP_FSYNC(devvp, waitfor, td)) != 0)290- allerror = error;291+ error = VOP_FSYNC(devvp, waitfor, td);292VOP_UNLOCK(devvp, 0);293+ if (MOUNTEDSOFTDEP(mp) && (error == 0 || error == EAGAIN))294+ error = ffs_sbupdate(ump, waitfor, 0);295+ if (error != 0)296+ allerror = error;297if (allerror == 0 && waitfor == MNT_WAIT)298goto loop;299} else if (suspend != 0) {300Index: sys/ufs/ffs/softdep.h301===================================================================302--- sys/ufs/ffs/softdep.h (revision 282245)303+++ sys/ufs/ffs/softdep.h (working copy)304@@ -1063,6 +1063,8 @@ struct mount_softdeps {305*/306#define FLUSH_EXIT 0x0001 /* time to exit */307#define FLUSH_CLEANUP 0x0002 /* need to clear out softdep structures */308+#define FLUSH_STARTING 0x0004 /* flush thread not yet started */309+310/*311* Keep the old names from when these were in the ufsmount structure.312*/313314315