Add support for multi-threading of soft updates.
Replace a single soft updates thread with a thread per FFS-filesystem mount point. The threads are associated with the bufdaemon process. Reviewed by: kib Tested by: Peter Holm and Scott Long MFC after: 2 weeks Sponsored by: Netflix
This commit is contained in:
parent
8029eb754a
commit
5f9500c358
@ -98,7 +98,8 @@ struct buf_ops buf_ops_bio = {
|
|||||||
struct buf *buf; /* buffer header pool */
|
struct buf *buf; /* buffer header pool */
|
||||||
caddr_t unmapped_buf;
|
caddr_t unmapped_buf;
|
||||||
|
|
||||||
static struct proc *bufdaemonproc;
|
/* Used below and for softdep flushing threads in ufs/ffs/ffs_softdep.c */
|
||||||
|
struct proc *bufdaemonproc;
|
||||||
|
|
||||||
static int inmem(struct vnode *vp, daddr_t blkno);
|
static int inmem(struct vnode *vp, daddr_t blkno);
|
||||||
static void vm_hold_free_pages(struct buf *bp, int newbsize);
|
static void vm_hold_free_pages(struct buf *bp, int newbsize);
|
||||||
|
@ -908,9 +908,9 @@ static void add_to_worklist(struct worklist *, int);
|
|||||||
static void wake_worklist(struct worklist *);
|
static void wake_worklist(struct worklist *);
|
||||||
static void wait_worklist(struct worklist *, char *);
|
static void wait_worklist(struct worklist *, char *);
|
||||||
static void remove_from_worklist(struct worklist *);
|
static void remove_from_worklist(struct worklist *);
|
||||||
static void softdep_flush(void);
|
static void softdep_flush(void *);
|
||||||
static void softdep_flushjournal(struct mount *);
|
static void softdep_flushjournal(struct mount *);
|
||||||
static int softdep_speedup(void);
|
static int softdep_speedup(struct ufsmount *);
|
||||||
static void worklist_speedup(struct mount *);
|
static void worklist_speedup(struct mount *);
|
||||||
static int journal_mount(struct mount *, struct fs *, struct ucred *);
|
static int journal_mount(struct mount *, struct fs *, struct ucred *);
|
||||||
static void journal_unmount(struct ufsmount *);
|
static void journal_unmount(struct ufsmount *);
|
||||||
@ -962,18 +962,21 @@ static int softdep_count_dependencies(struct buf *bp, int);
|
|||||||
/*
|
/*
|
||||||
* Global lock over all of soft updates.
|
* Global lock over all of soft updates.
|
||||||
*/
|
*/
|
||||||
static struct rwlock lk;
|
static struct mtx lk;
|
||||||
RW_SYSINIT(softdep_lock, &lk, "Softdep Lock");
|
MTX_SYSINIT(softdep_lock, &lk, "Global Softdep Lock", MTX_DEF);
|
||||||
|
|
||||||
|
#define ACQUIRE_GBLLOCK(lk) mtx_lock(lk)
|
||||||
|
#define FREE_GBLLOCK(lk) mtx_unlock(lk)
|
||||||
|
#define GBLLOCK_OWNED(lk) mtx_assert((lk), MA_OWNED)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allow per-filesystem soft-updates locking.
|
* Per-filesystem soft-updates locking.
|
||||||
* For now all use the same global lock defined above.
|
|
||||||
*/
|
*/
|
||||||
#define LOCK_PTR(ump) ((ump)->um_softdep->sd_fslock)
|
#define LOCK_PTR(ump) (&(ump)->um_softdep->sd_fslock)
|
||||||
#define TRY_ACQUIRE_LOCK(ump) rw_try_wlock((ump)->um_softdep->sd_fslock)
|
#define TRY_ACQUIRE_LOCK(ump) rw_try_wlock(&(ump)->um_softdep->sd_fslock)
|
||||||
#define ACQUIRE_LOCK(ump) rw_wlock((ump)->um_softdep->sd_fslock)
|
#define ACQUIRE_LOCK(ump) rw_wlock(&(ump)->um_softdep->sd_fslock)
|
||||||
#define FREE_LOCK(ump) rw_wunlock((ump)->um_softdep->sd_fslock)
|
#define FREE_LOCK(ump) rw_wunlock(&(ump)->um_softdep->sd_fslock)
|
||||||
#define LOCK_OWNED(ump) rw_assert((ump)->um_softdep->sd_fslock, \
|
#define LOCK_OWNED(ump) rw_assert(&(ump)->um_softdep->sd_fslock, \
|
||||||
RA_WLOCKED)
|
RA_WLOCKED)
|
||||||
|
|
||||||
#define BUF_AREC(bp) lockallowrecurse(&(bp)->b_lock)
|
#define BUF_AREC(bp) lockallowrecurse(&(bp)->b_lock)
|
||||||
@ -1178,7 +1181,7 @@ workitem_free(item, type)
|
|||||||
KASSERT(ump->softdep_curdeps[item->wk_type] > 0,
|
KASSERT(ump->softdep_curdeps[item->wk_type] > 0,
|
||||||
("workitem_free: %s: softdep_curdeps[%s] going negative",
|
("workitem_free: %s: softdep_curdeps[%s] going negative",
|
||||||
ump->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
|
ump->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
|
||||||
dep_current[item->wk_type]--;
|
atomic_subtract_long(&dep_current[item->wk_type], 1);
|
||||||
ump->softdep_curdeps[item->wk_type] -= 1;
|
ump->softdep_curdeps[item->wk_type] -= 1;
|
||||||
free(item, DtoM(type));
|
free(item, DtoM(type));
|
||||||
}
|
}
|
||||||
@ -1196,11 +1199,13 @@ workitem_alloc(item, type, mp)
|
|||||||
item->wk_state = 0;
|
item->wk_state = 0;
|
||||||
|
|
||||||
ump = VFSTOUFS(mp);
|
ump = VFSTOUFS(mp);
|
||||||
ACQUIRE_LOCK(ump);
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
dep_current[type]++;
|
dep_current[type]++;
|
||||||
if (dep_current[type] > dep_highuse[type])
|
if (dep_current[type] > dep_highuse[type])
|
||||||
dep_highuse[type] = dep_current[type];
|
dep_highuse[type] = dep_current[type];
|
||||||
dep_total[type]++;
|
dep_total[type]++;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
|
ACQUIRE_LOCK(ump);
|
||||||
ump->softdep_curdeps[type] += 1;
|
ump->softdep_curdeps[type] += 1;
|
||||||
ump->softdep_deps++;
|
ump->softdep_deps++;
|
||||||
ump->softdep_accdeps++;
|
ump->softdep_accdeps++;
|
||||||
@ -1224,11 +1229,13 @@ workitem_reassign(item, newtype)
|
|||||||
KASSERT(dep_current[item->wk_type] > 0,
|
KASSERT(dep_current[item->wk_type] > 0,
|
||||||
("workitem_reassign: %s: dep_current[%s] going negative",
|
("workitem_reassign: %s: dep_current[%s] going negative",
|
||||||
VFSTOUFS(item->wk_mp)->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
|
VFSTOUFS(item->wk_mp)->um_fs->fs_fsmnt, TYPENAME(item->wk_type)));
|
||||||
dep_current[item->wk_type]--;
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
dep_current[newtype]++;
|
dep_current[newtype]++;
|
||||||
|
dep_current[item->wk_type]--;
|
||||||
if (dep_current[newtype] > dep_highuse[newtype])
|
if (dep_current[newtype] > dep_highuse[newtype])
|
||||||
dep_highuse[newtype] = dep_current[newtype];
|
dep_highuse[newtype] = dep_current[newtype];
|
||||||
dep_total[newtype]++;
|
dep_total[newtype]++;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
item->wk_type = newtype;
|
item->wk_type = newtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1236,13 +1243,10 @@ workitem_reassign(item, newtype)
|
|||||||
* Workitem queue management
|
* Workitem queue management
|
||||||
*/
|
*/
|
||||||
static int max_softdeps; /* maximum number of structs before slowdown */
|
static int max_softdeps; /* maximum number of structs before slowdown */
|
||||||
static int maxindirdeps = 50; /* max number of indirdeps before slowdown */
|
|
||||||
static int tickdelay = 2; /* number of ticks to pause during slowdown */
|
static int tickdelay = 2; /* number of ticks to pause during slowdown */
|
||||||
static int proc_waiting; /* tracks whether we have a timeout posted */
|
static int proc_waiting; /* tracks whether we have a timeout posted */
|
||||||
static int *stat_countp; /* statistic to count in proc_waiting timeout */
|
static int *stat_countp; /* statistic to count in proc_waiting timeout */
|
||||||
static struct callout softdep_callout;
|
static struct callout softdep_callout;
|
||||||
static struct mount *req_pending;
|
|
||||||
#define ALLCLEAN ((struct mount *)-1)
|
|
||||||
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
|
static int req_clear_inodedeps; /* syncer process flush some inodedeps */
|
||||||
static int req_clear_remove; /* syncer process flush some freeblks */
|
static int req_clear_remove; /* syncer process flush some freeblks */
|
||||||
static int softdep_flushcache = 0; /* Should we do BIO_FLUSH? */
|
static int softdep_flushcache = 0; /* Should we do BIO_FLUSH? */
|
||||||
@ -1250,7 +1254,7 @@ static int softdep_flushcache = 0; /* Should we do BIO_FLUSH? */
|
|||||||
/*
|
/*
|
||||||
* runtime statistics
|
* runtime statistics
|
||||||
*/
|
*/
|
||||||
static int stat_softdep_mounts; /* number of softdep mounted filesystems */
|
static int stat_flush_threads; /* number of softdep flushing threads */
|
||||||
static int stat_worklist_push; /* number of worklist cleanups */
|
static int stat_worklist_push; /* number of worklist cleanups */
|
||||||
static int stat_blk_limit_push; /* number of times block limit neared */
|
static int stat_blk_limit_push; /* number of times block limit neared */
|
||||||
static int stat_ino_limit_push; /* number of times inode limit neared */
|
static int stat_ino_limit_push; /* number of times inode limit neared */
|
||||||
@ -1281,10 +1285,8 @@ SYSCTL_INT(_debug_softdep, OID_AUTO, max_softdeps, CTLFLAG_RW,
|
|||||||
&max_softdeps, 0, "");
|
&max_softdeps, 0, "");
|
||||||
SYSCTL_INT(_debug_softdep, OID_AUTO, tickdelay, CTLFLAG_RW,
|
SYSCTL_INT(_debug_softdep, OID_AUTO, tickdelay, CTLFLAG_RW,
|
||||||
&tickdelay, 0, "");
|
&tickdelay, 0, "");
|
||||||
SYSCTL_INT(_debug_softdep, OID_AUTO, maxindirdeps, CTLFLAG_RW,
|
SYSCTL_INT(_debug_softdep, OID_AUTO, flush_threads, CTLFLAG_RD,
|
||||||
&maxindirdeps, 0, "");
|
&stat_flush_threads, 0, "");
|
||||||
SYSCTL_INT(_debug_softdep, OID_AUTO, softdep_mounts, CTLFLAG_RD,
|
|
||||||
&stat_softdep_mounts, 0, "");
|
|
||||||
SYSCTL_INT(_debug_softdep, OID_AUTO, worklist_push, CTLFLAG_RW,
|
SYSCTL_INT(_debug_softdep, OID_AUTO, worklist_push, CTLFLAG_RW,
|
||||||
&stat_worklist_push, 0,"");
|
&stat_worklist_push, 0,"");
|
||||||
SYSCTL_INT(_debug_softdep, OID_AUTO, blk_limit_push, CTLFLAG_RW,
|
SYSCTL_INT(_debug_softdep, OID_AUTO, blk_limit_push, CTLFLAG_RW,
|
||||||
@ -1344,53 +1346,67 @@ SYSCTL_DECL(_vfs_ffs);
|
|||||||
static int compute_summary_at_mount = 0;
|
static int compute_summary_at_mount = 0;
|
||||||
SYSCTL_INT(_vfs_ffs, OID_AUTO, compute_summary_at_mount, CTLFLAG_RW,
|
SYSCTL_INT(_vfs_ffs, OID_AUTO, compute_summary_at_mount, CTLFLAG_RW,
|
||||||
&compute_summary_at_mount, 0, "Recompute summary at mount");
|
&compute_summary_at_mount, 0, "Recompute summary at mount");
|
||||||
static struct proc *softdepproc;
|
static int print_threads = 0;
|
||||||
static struct kproc_desc softdep_kp = {
|
SYSCTL_INT(_debug_softdep, OID_AUTO, print_threads, CTLFLAG_RW,
|
||||||
"softdepflush",
|
&print_threads, 0, "Notify flusher thread start/stop");
|
||||||
softdep_flush,
|
|
||||||
&softdepproc
|
|
||||||
};
|
|
||||||
SYSINIT(sdproc, SI_SUB_KTHREAD_UPDATE, SI_ORDER_ANY, kproc_start,
|
|
||||||
&softdep_kp);
|
|
||||||
|
|
||||||
|
/* List of all filesystems mounted with soft updates */
|
||||||
|
static TAILQ_HEAD(, mount_softdeps) softdepmounts;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function cleans the worklist for a filesystem.
|
||||||
|
* Each filesystem running with soft dependencies gets its own
|
||||||
|
* thread to run in this function. The thread is started up in
|
||||||
|
* softdep_mount and shutdown in softdep_unmount. They show up
|
||||||
|
* as part of the kernel "bufdaemon" process whose process
|
||||||
|
* entry is available in bufdaemonproc.
|
||||||
|
*/
|
||||||
|
static int searchfailed;
|
||||||
|
extern struct proc *bufdaemonproc;
|
||||||
static void
|
static void
|
||||||
softdep_flush(void)
|
softdep_flush(addr)
|
||||||
|
void *addr;
|
||||||
{
|
{
|
||||||
struct mount *nmp;
|
|
||||||
struct mount *mp;
|
struct mount *mp;
|
||||||
struct ufsmount *ump;
|
|
||||||
struct thread *td;
|
struct thread *td;
|
||||||
int remaining;
|
struct ufsmount *ump;
|
||||||
int progress;
|
|
||||||
|
|
||||||
td = curthread;
|
td = curthread;
|
||||||
td->td_pflags |= TDP_NORUNNINGBUF;
|
td->td_pflags |= TDP_NORUNNINGBUF;
|
||||||
|
mp = (struct mount *)addr;
|
||||||
|
ump = VFSTOUFS(mp);
|
||||||
|
atomic_add_int(&stat_flush_threads, 1);
|
||||||
|
if (print_threads) {
|
||||||
|
if (stat_flush_threads == 1)
|
||||||
|
printf("Running %s at pid %d\n", bufdaemonproc->p_comm,
|
||||||
|
bufdaemonproc->p_pid);
|
||||||
|
printf("Start thread %s\n", td->td_name);
|
||||||
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
kproc_suspend_check(softdepproc);
|
while (softdep_process_worklist(mp, 0) > 0 ||
|
||||||
remaining = progress = 0;
|
(MOUNTEDSUJ(mp) &&
|
||||||
mtx_lock(&mountlist_mtx);
|
VFSTOUFS(mp)->softdep_jblocks->jb_suspended))
|
||||||
for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) {
|
kthread_suspend_check();
|
||||||
nmp = TAILQ_NEXT(mp, mnt_list);
|
ACQUIRE_LOCK(ump);
|
||||||
if (MOUNTEDSOFTDEP(mp) == 0)
|
if ((ump->softdep_flags & FLUSH_CLEANUP) == 0)
|
||||||
continue;
|
msleep(&ump->softdep_flushtd, LOCK_PTR(ump), PVM,
|
||||||
if (vfs_busy(mp, MBF_NOWAIT | MBF_MNTLSTLOCK))
|
"sdflush", hz / 2);
|
||||||
continue;
|
ump->softdep_flags &= ~FLUSH_CLEANUP;
|
||||||
ump = VFSTOUFS(mp);
|
/*
|
||||||
progress += softdep_process_worklist(mp, 0);
|
* Check to see if we are done and need to exit.
|
||||||
remaining += ump->softdep_on_worklist;
|
*/
|
||||||
mtx_lock(&mountlist_mtx);
|
if ((ump->softdep_flags & FLUSH_EXIT) == 0) {
|
||||||
nmp = TAILQ_NEXT(mp, mnt_list);
|
FREE_LOCK(ump);
|
||||||
vfs_unbusy(mp);
|
|
||||||
}
|
|
||||||
mtx_unlock(&mountlist_mtx);
|
|
||||||
if (remaining && progress)
|
|
||||||
continue;
|
continue;
|
||||||
rw_wlock(&lk);
|
}
|
||||||
if (req_pending == NULL)
|
ump->softdep_flags &= ~FLUSH_EXIT;
|
||||||
msleep(&req_pending, &lk, PVM, "sdflush", hz);
|
FREE_LOCK(ump);
|
||||||
req_pending = NULL;
|
wakeup(&ump->softdep_flags);
|
||||||
rw_wunlock(&lk);
|
if (print_threads)
|
||||||
|
printf("Stop thread %s: searchfailed %d, did cleanups %d\n", td->td_name, searchfailed, ump->um_softdep->sd_cleanups);
|
||||||
|
atomic_subtract_int(&stat_flush_threads, 1);
|
||||||
|
kthread_exit();
|
||||||
|
panic("kthread_exit failed\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1398,19 +1414,70 @@ static void
|
|||||||
worklist_speedup(mp)
|
worklist_speedup(mp)
|
||||||
struct mount *mp;
|
struct mount *mp;
|
||||||
{
|
{
|
||||||
rw_assert(&lk, RA_WLOCKED);
|
struct ufsmount *ump;
|
||||||
if (req_pending == 0) {
|
|
||||||
req_pending = mp;
|
ump = VFSTOUFS(mp);
|
||||||
wakeup(&req_pending);
|
LOCK_OWNED(ump);
|
||||||
|
if ((ump->softdep_flags & (FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
|
||||||
|
ump->softdep_flags |= FLUSH_CLEANUP;
|
||||||
|
if (ump->softdep_flushtd->td_wchan == &ump->softdep_flushtd)
|
||||||
|
wakeup(&ump->softdep_flushtd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
softdep_speedup(void)
|
softdep_speedup(ump)
|
||||||
|
struct ufsmount *ump;
|
||||||
{
|
{
|
||||||
|
struct ufsmount *altump;
|
||||||
|
struct mount_softdeps *sdp;
|
||||||
|
|
||||||
worklist_speedup(ALLCLEAN);
|
LOCK_OWNED(ump);
|
||||||
|
worklist_speedup(ump->um_mountp);
|
||||||
bd_speedup();
|
bd_speedup();
|
||||||
|
/*
|
||||||
|
* If we have global shortages, then we need other
|
||||||
|
* filesystems to help with the cleanup. Here we wakeup a
|
||||||
|
* flusher thread for a filesystem that is over its fair
|
||||||
|
* share of resources.
|
||||||
|
*/
|
||||||
|
if (req_clear_inodedeps || req_clear_remove) {
|
||||||
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
|
TAILQ_FOREACH(sdp, &softdepmounts, sd_next) {
|
||||||
|
if ((altump = sdp->sd_ump) == ump)
|
||||||
|
continue;
|
||||||
|
if (((req_clear_inodedeps &&
|
||||||
|
altump->softdep_curdeps[D_INODEDEP] >
|
||||||
|
max_softdeps / stat_flush_threads) ||
|
||||||
|
(req_clear_remove &&
|
||||||
|
altump->softdep_curdeps[D_DIRREM] >
|
||||||
|
(max_softdeps / 2) / stat_flush_threads)) &&
|
||||||
|
TRY_ACQUIRE_LOCK(altump))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (sdp == NULL) {
|
||||||
|
searchfailed++;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
* Move to the end of the list so we pick a
|
||||||
|
* different one on out next try.
|
||||||
|
*/
|
||||||
|
TAILQ_REMOVE(&softdepmounts, sdp, sd_next);
|
||||||
|
TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
|
if ((altump->softdep_flags &
|
||||||
|
(FLUSH_CLEANUP | FLUSH_EXIT)) == 0) {
|
||||||
|
altump->softdep_flags |= FLUSH_CLEANUP;
|
||||||
|
altump->um_softdep->sd_cleanups++;
|
||||||
|
if (altump->softdep_flushtd->td_wchan ==
|
||||||
|
&altump->softdep_flushtd) {
|
||||||
|
wakeup(&altump->softdep_flushtd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FREE_LOCK(altump);
|
||||||
|
}
|
||||||
|
}
|
||||||
return (speedup_syncer());
|
return (speedup_syncer());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2126,9 +2193,14 @@ inodedep_lookup(mp, inum, flags, inodedeppp)
|
|||||||
if ((flags & DEPALLOC) == 0)
|
if ((flags & DEPALLOC) == 0)
|
||||||
return (0);
|
return (0);
|
||||||
/*
|
/*
|
||||||
* If we are over our limit, try to improve the situation.
|
* If the system is over its limit and our filesystem is
|
||||||
|
* responsible for more than our share of that usage and
|
||||||
|
* we are not in a rush, request some inodedep cleanup.
|
||||||
*/
|
*/
|
||||||
if (dep_current[D_INODEDEP] > max_softdeps && (flags & NODELAY) == 0)
|
while (dep_current[D_INODEDEP] > max_softdeps &&
|
||||||
|
(flags & NODELAY) == 0 &&
|
||||||
|
ump->softdep_curdeps[D_INODEDEP] >
|
||||||
|
max_softdeps / stat_flush_threads)
|
||||||
request_cleanup(mp, FLUSH_INODES);
|
request_cleanup(mp, FLUSH_INODES);
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
inodedep = malloc(sizeof(struct inodedep),
|
inodedep = malloc(sizeof(struct inodedep),
|
||||||
@ -2320,6 +2392,7 @@ void
|
|||||||
softdep_initialize()
|
softdep_initialize()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
TAILQ_INIT(&softdepmounts);
|
||||||
max_softdeps = desiredvnodes * 4;
|
max_softdeps = desiredvnodes * 4;
|
||||||
|
|
||||||
/* initialise bioops hack */
|
/* initialise bioops hack */
|
||||||
@ -2378,7 +2451,9 @@ softdep_mount(devvp, mp, fs, cred)
|
|||||||
ump = VFSTOUFS(mp);
|
ump = VFSTOUFS(mp);
|
||||||
ump->um_softdep = sdp;
|
ump->um_softdep = sdp;
|
||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
LOCK_PTR(ump) = &lk;
|
rw_init(LOCK_PTR(ump), "Per-Filesystem Softdep Lock");
|
||||||
|
TAILQ_INSERT_TAIL(&softdepmounts, sdp, sd_next);
|
||||||
|
sdp->sd_ump = ump;
|
||||||
LIST_INIT(&ump->softdep_workitem_pending);
|
LIST_INIT(&ump->softdep_workitem_pending);
|
||||||
LIST_INIT(&ump->softdep_journal_pending);
|
LIST_INIT(&ump->softdep_journal_pending);
|
||||||
TAILQ_INIT(&ump->softdep_unlinked);
|
TAILQ_INIT(&ump->softdep_unlinked);
|
||||||
@ -2409,7 +2484,12 @@ softdep_mount(devvp, mp, fs, cred)
|
|||||||
softdep_unmount(mp);
|
softdep_unmount(mp);
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
atomic_add_int(&stat_softdep_mounts, 1);
|
/*
|
||||||
|
* Start our flushing thread in the bufdaemon process.
|
||||||
|
*/
|
||||||
|
kproc_kthread_add(&softdep_flush, mp, &bufdaemonproc,
|
||||||
|
&ump->softdep_flushtd, 0, 0, "softdepflush", "%s worker",
|
||||||
|
mp->mnt_stat.f_mntonname);
|
||||||
/*
|
/*
|
||||||
* When doing soft updates, the counters in the
|
* When doing soft updates, the counters in the
|
||||||
* superblock may have gotten out of sync. Recomputation
|
* superblock may have gotten out of sync. Recomputation
|
||||||
@ -2465,7 +2545,24 @@ softdep_unmount(mp)
|
|||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
journal_unmount(ump);
|
journal_unmount(ump);
|
||||||
}
|
}
|
||||||
atomic_subtract_int(&stat_softdep_mounts, 1);
|
/*
|
||||||
|
* Shut down our flushing thread. Check for NULL is if
|
||||||
|
* softdep_mount errors out before the thread has been created.
|
||||||
|
*/
|
||||||
|
if (ump->softdep_flushtd != NULL) {
|
||||||
|
ACQUIRE_LOCK(ump);
|
||||||
|
ump->softdep_flags |= FLUSH_EXIT;
|
||||||
|
wakeup(&ump->softdep_flushtd);
|
||||||
|
msleep(&ump->softdep_flags, LOCK_PTR(ump), PVM | PDROP,
|
||||||
|
"sdwait", 0);
|
||||||
|
KASSERT((ump->softdep_flags & FLUSH_EXIT) == 0,
|
||||||
|
("Thread shutdown failed"));
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Free up our resources.
|
||||||
|
*/
|
||||||
|
rw_destroy(LOCK_PTR(ump));
|
||||||
|
TAILQ_REMOVE(&softdepmounts, ump->um_softdep, sd_next);
|
||||||
hashdestroy(ump->pagedep_hashtbl, M_PAGEDEP, ump->pagedep_hash_size);
|
hashdestroy(ump->pagedep_hashtbl, M_PAGEDEP, ump->pagedep_hash_size);
|
||||||
hashdestroy(ump->inodedep_hashtbl, M_INODEDEP, ump->inodedep_hash_size);
|
hashdestroy(ump->inodedep_hashtbl, M_INODEDEP, ump->inodedep_hash_size);
|
||||||
hashdestroy(ump->newblk_hashtbl, M_NEWBLK, ump->newblk_hash_size);
|
hashdestroy(ump->newblk_hashtbl, M_NEWBLK, ump->newblk_hash_size);
|
||||||
@ -2788,7 +2885,7 @@ journal_space(ump, thresh)
|
|||||||
*/
|
*/
|
||||||
limit = (max_softdeps / 10) * 9;
|
limit = (max_softdeps / 10) * 9;
|
||||||
if (dep_current[D_INODEDEP] > limit &&
|
if (dep_current[D_INODEDEP] > limit &&
|
||||||
ump->softdep_curdeps[D_INODEDEP] > limit / stat_softdep_mounts)
|
ump->softdep_curdeps[D_INODEDEP] > limit / stat_flush_threads)
|
||||||
return (0);
|
return (0);
|
||||||
if (thresh)
|
if (thresh)
|
||||||
thresh = jblocks->jb_min;
|
thresh = jblocks->jb_min;
|
||||||
@ -2813,7 +2910,7 @@ journal_suspend(ump)
|
|||||||
if ((mp->mnt_kern_flag & MNTK_SUSPEND) == 0) {
|
if ((mp->mnt_kern_flag & MNTK_SUSPEND) == 0) {
|
||||||
stat_journal_min++;
|
stat_journal_min++;
|
||||||
mp->mnt_kern_flag |= MNTK_SUSPEND;
|
mp->mnt_kern_flag |= MNTK_SUSPEND;
|
||||||
mp->mnt_susp_owner = FIRST_THREAD_IN_PROC(softdepproc);
|
mp->mnt_susp_owner = ump->softdep_flushtd;
|
||||||
}
|
}
|
||||||
jblocks->jb_suspended = 1;
|
jblocks->jb_suspended = 1;
|
||||||
MNT_IUNLOCK(mp);
|
MNT_IUNLOCK(mp);
|
||||||
@ -2888,7 +2985,7 @@ softdep_prealloc(vp, waitok)
|
|||||||
process_removes(vp);
|
process_removes(vp);
|
||||||
process_truncates(vp);
|
process_truncates(vp);
|
||||||
if (journal_space(ump, 0) == 0) {
|
if (journal_space(ump, 0) == 0) {
|
||||||
softdep_speedup();
|
softdep_speedup(ump);
|
||||||
if (journal_space(ump, 1) == 0)
|
if (journal_space(ump, 1) == 0)
|
||||||
journal_suspend(ump);
|
journal_suspend(ump);
|
||||||
}
|
}
|
||||||
@ -2932,10 +3029,10 @@ softdep_prelink(dvp, vp)
|
|||||||
}
|
}
|
||||||
process_removes(dvp);
|
process_removes(dvp);
|
||||||
process_truncates(dvp);
|
process_truncates(dvp);
|
||||||
softdep_speedup();
|
softdep_speedup(ump);
|
||||||
process_worklist_item(UFSTOVFS(ump), 2, LK_NOWAIT);
|
process_worklist_item(UFSTOVFS(ump), 2, LK_NOWAIT);
|
||||||
if (journal_space(ump, 0) == 0) {
|
if (journal_space(ump, 0) == 0) {
|
||||||
softdep_speedup();
|
softdep_speedup(ump);
|
||||||
if (journal_space(ump, 1) == 0)
|
if (journal_space(ump, 1) == 0)
|
||||||
journal_suspend(ump);
|
journal_suspend(ump);
|
||||||
}
|
}
|
||||||
@ -3257,7 +3354,7 @@ softdep_process_journal(mp, needwk, flags)
|
|||||||
if (flags != MNT_WAIT)
|
if (flags != MNT_WAIT)
|
||||||
break;
|
break;
|
||||||
printf("softdep: Out of journal space!\n");
|
printf("softdep: Out of journal space!\n");
|
||||||
softdep_speedup();
|
softdep_speedup(ump);
|
||||||
msleep(jblocks, LOCK_PTR(ump), PRIBIO, "jblocks", hz);
|
msleep(jblocks, LOCK_PTR(ump), PRIBIO, "jblocks", hz);
|
||||||
}
|
}
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
@ -3970,7 +4067,7 @@ free_freedep(freedep)
|
|||||||
/*
|
/*
|
||||||
* Allocate a new freework structure that may be a level in an indirect
|
* Allocate a new freework structure that may be a level in an indirect
|
||||||
* when parent is not NULL or a top level block when it is. The top level
|
* when parent is not NULL or a top level block when it is. The top level
|
||||||
* freework structures are allocated without the soft updates lock held
|
* freework structures are allocated without the per-filesystem lock held
|
||||||
* and before the freeblks is visible outside of softdep_setup_freeblocks().
|
* and before the freeblks is visible outside of softdep_setup_freeblocks().
|
||||||
*/
|
*/
|
||||||
static struct freework *
|
static struct freework *
|
||||||
@ -4039,7 +4136,7 @@ cancel_jfreeblk(freeblks, blkno)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a new jfreeblk to journal top level block pointer when truncating
|
* Allocate a new jfreeblk to journal top level block pointer when truncating
|
||||||
* a file. The caller must add this to the worklist when the soft updates
|
* a file. The caller must add this to the worklist when the per-filesystem
|
||||||
* lock is held.
|
* lock is held.
|
||||||
*/
|
*/
|
||||||
static struct jfreeblk *
|
static struct jfreeblk *
|
||||||
@ -7419,7 +7516,7 @@ softdep_freefile(pvp, ino, mode)
|
|||||||
clear_unlinked_inodedep(inodedep);
|
clear_unlinked_inodedep(inodedep);
|
||||||
/*
|
/*
|
||||||
* Re-acquire inodedep as we've dropped the
|
* Re-acquire inodedep as we've dropped the
|
||||||
* soft updates lock in clear_unlinked_inodedep().
|
* per-filesystem lock in clear_unlinked_inodedep().
|
||||||
*/
|
*/
|
||||||
inodedep_lookup(pvp->v_mount, ino, 0, &inodedep);
|
inodedep_lookup(pvp->v_mount, ino, 0, &inodedep);
|
||||||
}
|
}
|
||||||
@ -7965,10 +8062,8 @@ indir_trunc(freework, dbn, lbn)
|
|||||||
* If we're goingaway, free the indirdep. Otherwise it will
|
* If we're goingaway, free the indirdep. Otherwise it will
|
||||||
* linger until the write completes.
|
* linger until the write completes.
|
||||||
*/
|
*/
|
||||||
if (goingaway) {
|
if (goingaway)
|
||||||
free_indirdep(indirdep);
|
free_indirdep(indirdep);
|
||||||
ump->softdep_numindirdeps -= 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
/* Initialize pointers depending on block size. */
|
/* Initialize pointers depending on block size. */
|
||||||
@ -8140,7 +8235,7 @@ cancel_allocindir(aip, bp, freeblks, trunc)
|
|||||||
* Create the mkdir dependencies for . and .. in a new directory. Link them
|
* Create the mkdir dependencies for . and .. in a new directory. Link them
|
||||||
* in to a newdirblk so any subsequent additions are tracked properly. The
|
* in to a newdirblk so any subsequent additions are tracked properly. The
|
||||||
* caller is responsible for adding the mkdir1 dependency to the journal
|
* caller is responsible for adding the mkdir1 dependency to the journal
|
||||||
* and updating id_mkdiradd. This function returns with the soft updates
|
* and updating id_mkdiradd. This function returns with the per-filesystem
|
||||||
* lock held.
|
* lock held.
|
||||||
*/
|
*/
|
||||||
static struct mkdir *
|
static struct mkdir *
|
||||||
@ -8958,12 +9053,16 @@ newdirrem(bp, dp, ip, isrmdir, prevdirremp)
|
|||||||
panic("newdirrem: whiteout");
|
panic("newdirrem: whiteout");
|
||||||
dvp = ITOV(dp);
|
dvp = ITOV(dp);
|
||||||
/*
|
/*
|
||||||
* If we are over our limit, try to improve the situation.
|
* If the system is over its limit and our filesystem is
|
||||||
|
* responsible for more than our share of that usage and
|
||||||
|
* we are not a snapshot, request some inodedep cleanup.
|
||||||
* Limiting the number of dirrem structures will also limit
|
* Limiting the number of dirrem structures will also limit
|
||||||
* the number of freefile and freeblks structures.
|
* the number of freefile and freeblks structures.
|
||||||
*/
|
*/
|
||||||
ACQUIRE_LOCK(ip->i_ump);
|
ACQUIRE_LOCK(ip->i_ump);
|
||||||
if (!IS_SNAPSHOT(ip) && dep_current[D_DIRREM] > max_softdeps / 2)
|
while (!IS_SNAPSHOT(ip) && dep_current[D_DIRREM] > max_softdeps / 2 &&
|
||||||
|
ip->i_ump->softdep_curdeps[D_DIRREM] >
|
||||||
|
(max_softdeps / 2) / stat_flush_threads)
|
||||||
(void) request_cleanup(ITOV(dp)->v_mount, FLUSH_BLOCKS);
|
(void) request_cleanup(ITOV(dp)->v_mount, FLUSH_BLOCKS);
|
||||||
FREE_LOCK(ip->i_ump);
|
FREE_LOCK(ip->i_ump);
|
||||||
dirrem = malloc(sizeof(struct dirrem),
|
dirrem = malloc(sizeof(struct dirrem),
|
||||||
@ -9914,7 +10013,7 @@ initiate_write_filepage(pagedep, bp)
|
|||||||
* Wait for all journal remove dependencies to hit the disk.
|
* Wait for all journal remove dependencies to hit the disk.
|
||||||
* We can not allow any potentially conflicting directory adds
|
* We can not allow any potentially conflicting directory adds
|
||||||
* to be visible before removes and rollback is too difficult.
|
* to be visible before removes and rollback is too difficult.
|
||||||
* The soft updates lock may be dropped and re-acquired, however
|
* The per-filesystem lock may be dropped and re-acquired, however
|
||||||
* we hold the buf locked so the dependency can not go away.
|
* we hold the buf locked so the dependency can not go away.
|
||||||
*/
|
*/
|
||||||
LIST_FOREACH(dirrem, &pagedep->pd_dirremhd, dm_next)
|
LIST_FOREACH(dirrem, &pagedep->pd_dirremhd, dm_next)
|
||||||
@ -10378,7 +10477,6 @@ cancel_indirdep(indirdep, bp, freeblks)
|
|||||||
LIST_REMOVE(indirdep, ir_next);
|
LIST_REMOVE(indirdep, ir_next);
|
||||||
}
|
}
|
||||||
indirdep->ir_state |= GOINGAWAY;
|
indirdep->ir_state |= GOINGAWAY;
|
||||||
VFSTOUFS(indirdep->ir_list.wk_mp)->softdep_numindirdeps += 1;
|
|
||||||
/*
|
/*
|
||||||
* Pass in bp for blocks still have journal writes
|
* Pass in bp for blocks still have journal writes
|
||||||
* pending so we can cancel them on their own.
|
* pending so we can cancel them on their own.
|
||||||
@ -10805,7 +10903,7 @@ softdep_disk_write_complete(bp)
|
|||||||
ACQUIRE_LOCK(ump);
|
ACQUIRE_LOCK(ump);
|
||||||
while ((wk = LIST_FIRST(&bp->b_dep)) != NULL) {
|
while ((wk = LIST_FIRST(&bp->b_dep)) != NULL) {
|
||||||
WORKLIST_REMOVE(wk);
|
WORKLIST_REMOVE(wk);
|
||||||
dep_write[wk->wk_type]++;
|
atomic_add_long(&dep_write[wk->wk_type], 1);
|
||||||
if (wk == owk)
|
if (wk == owk)
|
||||||
panic("duplicate worklist: %p\n", wk);
|
panic("duplicate worklist: %p\n", wk);
|
||||||
owk = wk;
|
owk = wk;
|
||||||
@ -11488,7 +11586,7 @@ diradd_inode_written(dap, inodedep)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns true if the bmsafemap will have rollbacks when written. Must only
|
* Returns true if the bmsafemap will have rollbacks when written. Must only
|
||||||
* be called with the soft updates lock and the buf lock on the cg held.
|
* be called with the per-filesystem lock and the buf lock on the cg held.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
bmsafemap_backgroundwrite(bmsafemap, bp)
|
bmsafemap_backgroundwrite(bmsafemap, bp)
|
||||||
@ -12912,18 +13010,42 @@ softdep_slowdown(vp)
|
|||||||
if (journal_space(ump, 0) == 0)
|
if (journal_space(ump, 0) == 0)
|
||||||
jlow = 1;
|
jlow = 1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* If the system is under its limits and our filesystem is
|
||||||
|
* not responsible for more than our share of the usage and
|
||||||
|
* we are not low on journal space, then no need to slow down.
|
||||||
|
*/
|
||||||
max_softdeps_hard = max_softdeps * 11 / 10;
|
max_softdeps_hard = max_softdeps * 11 / 10;
|
||||||
if (dep_current[D_DIRREM] < max_softdeps_hard / 2 &&
|
if (dep_current[D_DIRREM] < max_softdeps_hard / 2 &&
|
||||||
dep_current[D_INODEDEP] < max_softdeps_hard &&
|
dep_current[D_INODEDEP] < max_softdeps_hard &&
|
||||||
VFSTOUFS(vp->v_mount)->softdep_numindirdeps < maxindirdeps &&
|
dep_current[D_INDIRDEP] < max_softdeps_hard / 1000 &&
|
||||||
dep_current[D_FREEBLKS] < max_softdeps_hard && jlow == 0) {
|
dep_current[D_FREEBLKS] < max_softdeps_hard && jlow == 0 &&
|
||||||
|
ump->softdep_curdeps[D_DIRREM] <
|
||||||
|
(max_softdeps_hard / 2) / stat_flush_threads &&
|
||||||
|
ump->softdep_curdeps[D_INODEDEP] <
|
||||||
|
max_softdeps_hard / stat_flush_threads &&
|
||||||
|
ump->softdep_curdeps[D_INDIRDEP] <
|
||||||
|
(max_softdeps_hard / 1000) / stat_flush_threads &&
|
||||||
|
ump->softdep_curdeps[D_FREEBLKS] <
|
||||||
|
max_softdeps_hard / stat_flush_threads) {
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
if (VFSTOUFS(vp->v_mount)->softdep_numindirdeps >= maxindirdeps || jlow)
|
/*
|
||||||
softdep_speedup();
|
* If the journal is low or our filesystem is over its limit
|
||||||
|
* then speedup the cleanup.
|
||||||
|
*/
|
||||||
|
if (ump->softdep_curdeps[D_INDIRDEP] <
|
||||||
|
(max_softdeps_hard / 1000) / stat_flush_threads || jlow)
|
||||||
|
softdep_speedup(ump);
|
||||||
stat_sync_limit_hit += 1;
|
stat_sync_limit_hit += 1;
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
|
/*
|
||||||
|
* We only slow down the rate at which new dependencies are
|
||||||
|
* generated if we are not using journaling. With journaling,
|
||||||
|
* the cleanup should always be sufficient to keep things
|
||||||
|
* under control.
|
||||||
|
*/
|
||||||
if (DOINGSUJ(vp))
|
if (DOINGSUJ(vp))
|
||||||
return (0);
|
return (0);
|
||||||
return (1);
|
return (1);
|
||||||
@ -12981,13 +13103,12 @@ softdep_request_cleanup(fs, vp, cred, resource)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* If we are in need of resources, consider pausing for
|
* If we are in need of resources, start by cleaning up
|
||||||
* tickdelay to give ourselves some breathing room.
|
* any block removals associated with our inode.
|
||||||
*/
|
*/
|
||||||
ACQUIRE_LOCK(ump);
|
ACQUIRE_LOCK(ump);
|
||||||
process_removes(vp);
|
process_removes(vp);
|
||||||
process_truncates(vp);
|
process_truncates(vp);
|
||||||
request_cleanup(UFSTOVFS(ump), resource);
|
|
||||||
FREE_LOCK(ump);
|
FREE_LOCK(ump);
|
||||||
/*
|
/*
|
||||||
* Now clean up at least as many resources as we will need.
|
* Now clean up at least as many resources as we will need.
|
||||||
@ -13120,7 +13241,7 @@ request_cleanup(mp, resource)
|
|||||||
* Next, we attempt to speed up the syncer process. If that
|
* Next, we attempt to speed up the syncer process. If that
|
||||||
* is successful, then we allow the process to continue.
|
* is successful, then we allow the process to continue.
|
||||||
*/
|
*/
|
||||||
if (softdep_speedup() &&
|
if (softdep_speedup(ump) &&
|
||||||
resource != FLUSH_BLOCKS_WAIT &&
|
resource != FLUSH_BLOCKS_WAIT &&
|
||||||
resource != FLUSH_INODES_WAIT)
|
resource != FLUSH_INODES_WAIT)
|
||||||
return(0);
|
return(0);
|
||||||
@ -13138,15 +13259,19 @@ request_cleanup(mp, resource)
|
|||||||
|
|
||||||
case FLUSH_INODES:
|
case FLUSH_INODES:
|
||||||
case FLUSH_INODES_WAIT:
|
case FLUSH_INODES_WAIT:
|
||||||
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
stat_ino_limit_push += 1;
|
stat_ino_limit_push += 1;
|
||||||
req_clear_inodedeps += 1;
|
req_clear_inodedeps += 1;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
stat_countp = &stat_ino_limit_hit;
|
stat_countp = &stat_ino_limit_hit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FLUSH_BLOCKS:
|
case FLUSH_BLOCKS:
|
||||||
case FLUSH_BLOCKS_WAIT:
|
case FLUSH_BLOCKS_WAIT:
|
||||||
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
stat_blk_limit_push += 1;
|
stat_blk_limit_push += 1;
|
||||||
req_clear_remove += 1;
|
req_clear_remove += 1;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
stat_countp = &stat_blk_limit_hit;
|
stat_countp = &stat_blk_limit_hit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -13157,6 +13282,8 @@ request_cleanup(mp, resource)
|
|||||||
* Hopefully the syncer daemon will catch up and awaken us.
|
* Hopefully the syncer daemon will catch up and awaken us.
|
||||||
* We wait at most tickdelay before proceeding in any case.
|
* We wait at most tickdelay before proceeding in any case.
|
||||||
*/
|
*/
|
||||||
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
|
FREE_LOCK(ump);
|
||||||
proc_waiting += 1;
|
proc_waiting += 1;
|
||||||
if (callout_pending(&softdep_callout) == FALSE)
|
if (callout_pending(&softdep_callout) == FALSE)
|
||||||
callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2,
|
callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2,
|
||||||
@ -13164,6 +13291,8 @@ request_cleanup(mp, resource)
|
|||||||
|
|
||||||
msleep((caddr_t)&proc_waiting, &lk, PPAUSE, "softupdate", 0);
|
msleep((caddr_t)&proc_waiting, &lk, PPAUSE, "softupdate", 0);
|
||||||
proc_waiting -= 1;
|
proc_waiting -= 1;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
|
ACQUIRE_LOCK(ump);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -13177,16 +13306,13 @@ pause_timer(arg)
|
|||||||
void *arg;
|
void *arg;
|
||||||
{
|
{
|
||||||
|
|
||||||
rw_assert(&lk, RA_WLOCKED);
|
GBLLOCK_OWNED(&lk);
|
||||||
/*
|
/*
|
||||||
* The callout_ API has acquired mtx and will hold it around this
|
* The callout_ API has acquired mtx and will hold it around this
|
||||||
* function call.
|
* function call.
|
||||||
*/
|
*/
|
||||||
*stat_countp += 1;
|
*stat_countp += proc_waiting;
|
||||||
wakeup_one(&proc_waiting);
|
wakeup(&proc_waiting);
|
||||||
if (proc_waiting > 0)
|
|
||||||
callout_reset(&softdep_callout, tickdelay > 2 ? tickdelay : 2,
|
|
||||||
pause_timer, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -13197,7 +13323,6 @@ check_clear_deps(mp)
|
|||||||
struct mount *mp;
|
struct mount *mp;
|
||||||
{
|
{
|
||||||
|
|
||||||
rw_assert(&lk, RA_WLOCKED);
|
|
||||||
/*
|
/*
|
||||||
* If we are suspended, it may be because of our using
|
* If we are suspended, it may be because of our using
|
||||||
* too many inodedeps, so help clear them out.
|
* too many inodedeps, so help clear them out.
|
||||||
@ -13207,16 +13332,22 @@ check_clear_deps(mp)
|
|||||||
/*
|
/*
|
||||||
* General requests for cleanup of backed up dependencies
|
* General requests for cleanup of backed up dependencies
|
||||||
*/
|
*/
|
||||||
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
if (req_clear_inodedeps) {
|
if (req_clear_inodedeps) {
|
||||||
req_clear_inodedeps -= 1;
|
req_clear_inodedeps -= 1;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
clear_inodedeps(mp);
|
clear_inodedeps(mp);
|
||||||
wakeup_one(&proc_waiting);
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
|
wakeup(&proc_waiting);
|
||||||
}
|
}
|
||||||
if (req_clear_remove) {
|
if (req_clear_remove) {
|
||||||
req_clear_remove -= 1;
|
req_clear_remove -= 1;
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
clear_remove(mp);
|
clear_remove(mp);
|
||||||
wakeup_one(&proc_waiting);
|
ACQUIRE_GBLLOCK(&lk);
|
||||||
|
wakeup(&proc_waiting);
|
||||||
}
|
}
|
||||||
|
FREE_GBLLOCK(&lk);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1025,7 +1025,7 @@ TAILQ_HEAD(indir_hashhead, freework);
|
|||||||
* Allocated at mount and freed at unmount.
|
* Allocated at mount and freed at unmount.
|
||||||
*/
|
*/
|
||||||
struct mount_softdeps {
|
struct mount_softdeps {
|
||||||
struct rwlock *sd_fslock; /* softdep lock */
|
struct rwlock sd_fslock; /* softdep lock */
|
||||||
struct workhead sd_workitem_pending; /* softdep work queue */
|
struct workhead sd_workitem_pending; /* softdep work queue */
|
||||||
struct worklist *sd_worklist_tail; /* Tail pointer for above */
|
struct worklist *sd_worklist_tail; /* Tail pointer for above */
|
||||||
struct workhead sd_journal_pending; /* journal work queue */
|
struct workhead sd_journal_pending; /* journal work queue */
|
||||||
@ -1046,14 +1046,23 @@ struct mount_softdeps {
|
|||||||
u_long sd_bmhashsize; /* bmsafemap hash table size-1*/
|
u_long sd_bmhashsize; /* bmsafemap hash table size-1*/
|
||||||
struct indir_hashhead *sd_indirhash; /* indir hash table */
|
struct indir_hashhead *sd_indirhash; /* indir hash table */
|
||||||
u_long sd_indirhashsize; /* indir hash table size-1 */
|
u_long sd_indirhashsize; /* indir hash table size-1 */
|
||||||
long sd_numindirdeps; /* outstanding indirdeps */
|
|
||||||
int sd_on_journal; /* Items on the journal list */
|
int sd_on_journal; /* Items on the journal list */
|
||||||
int sd_on_worklist; /* Items on the worklist */
|
int sd_on_worklist; /* Items on the worklist */
|
||||||
int sd_deps; /* Total dependency count */
|
int sd_deps; /* Total dependency count */
|
||||||
int sd_accdeps; /* accumulated dep count */
|
int sd_accdeps; /* accumulated dep count */
|
||||||
int sd_req; /* Wakeup when deps hits 0. */
|
int sd_req; /* Wakeup when deps hits 0. */
|
||||||
|
int sd_flags; /* comm with flushing thread */
|
||||||
|
int sd_cleanups; /* Calls to cleanup */
|
||||||
|
struct thread *sd_flushtd; /* thread handling flushing */
|
||||||
|
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 */
|
u_long sd_curdeps[D_LAST + 1]; /* count of current deps */
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
|
* Flags for communicating with the syncer thread.
|
||||||
|
*/
|
||||||
|
#define FLUSH_EXIT 0x0001 /* time to exit */
|
||||||
|
#define FLUSH_CLEANUP 0x0002 /* need to clear out softdep structures */
|
||||||
/*
|
/*
|
||||||
* Keep the old names from when these were in the ufsmount structure.
|
* Keep the old names from when these were in the ufsmount structure.
|
||||||
*/
|
*/
|
||||||
@ -1077,10 +1086,11 @@ struct mount_softdeps {
|
|||||||
#define bmsafemap_hash_size um_softdep->sd_bmhashsize
|
#define bmsafemap_hash_size um_softdep->sd_bmhashsize
|
||||||
#define indir_hashtbl um_softdep->sd_indirhash
|
#define indir_hashtbl um_softdep->sd_indirhash
|
||||||
#define indir_hash_size um_softdep->sd_indirhashsize
|
#define indir_hash_size um_softdep->sd_indirhashsize
|
||||||
#define softdep_numindirdeps um_softdep->sd_numindirdeps
|
|
||||||
#define softdep_on_journal um_softdep->sd_on_journal
|
#define softdep_on_journal um_softdep->sd_on_journal
|
||||||
#define softdep_on_worklist um_softdep->sd_on_worklist
|
#define softdep_on_worklist um_softdep->sd_on_worklist
|
||||||
#define softdep_deps um_softdep->sd_deps
|
#define softdep_deps um_softdep->sd_deps
|
||||||
#define softdep_accdeps um_softdep->sd_accdeps
|
#define softdep_accdeps um_softdep->sd_accdeps
|
||||||
#define softdep_req um_softdep->sd_req
|
#define softdep_req um_softdep->sd_req
|
||||||
|
#define softdep_flags um_softdep->sd_flags
|
||||||
|
#define softdep_flushtd um_softdep->sd_flushtd
|
||||||
#define softdep_curdeps um_softdep->sd_curdeps
|
#define softdep_curdeps um_softdep->sd_curdeps
|
||||||
|
Loading…
x
Reference in New Issue
Block a user