From 9dca9515d47eeb36c9696bb04c0112bafd8efe38 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Fri, 18 Aug 2017 16:00:54 -0700 Subject: [PATCH] hammer2 - Add kernel-thread-based async bulk free * Add an async bulk-free feature and a kernel thread to allow the hammer2 vfs itself to run bulk frees. * Revamp the hammer2 thread management code a bit to support the new use, and clean-up the API. --- sbin/hammer2/cmd_bulkfree.c | 22 +++++++ sbin/hammer2/hammer2.h | 1 + sbin/hammer2/main.c | 10 ++++ sys/vfs/hammer2/hammer2.h | 23 +++++--- sys/vfs/hammer2/hammer2_admin.c | 118 ++++++++++++++++++++++--------------- sys/vfs/hammer2/hammer2_bulkfree.c | 59 +++++++++++++++++++ sys/vfs/hammer2/hammer2_ioctl.c | 20 ++++++- sys/vfs/hammer2/hammer2_ioctl.h | 1 + sys/vfs/hammer2/hammer2_subr.c | 18 ++++-- sys/vfs/hammer2/hammer2_synchro.c | 10 ++-- sys/vfs/hammer2/hammer2_vfsops.c | 5 +- 11 files changed, 219 insertions(+), 68 deletions(-) diff --git a/sbin/hammer2/cmd_bulkfree.c b/sbin/hammer2/cmd_bulkfree.c index dc273943f7..657ae49fd3 100644 --- a/sbin/hammer2/cmd_bulkfree.c +++ b/sbin/hammer2/cmd_bulkfree.c @@ -55,3 +55,25 @@ cmd_bulkfree(const char *sel_path) ecode = 0; return ecode; } + +int +cmd_bulkfree_async(const char *sel_path) +{ + hammer2_ioc_bulkfree_t bfi; + int ecode; + int fd; + int res; + + bzero(&bfi, sizeof(bfi)); + bfi.size = 8192 * 1024; + + if ((fd = hammer2_ioctl_handle(sel_path)) < 0) + return 1; + res = ioctl(fd, HAMMER2IOC_BULKFREE_ASYNC, &bfi); + if (res) { + perror("ioctl"); + ecode = 1; + } + ecode = 0; + return ecode; +} diff --git a/sbin/hammer2/hammer2.h b/sbin/hammer2/hammer2.h index 6a91a37d0a..4405fadd86 100644 --- a/sbin/hammer2/hammer2.h +++ b/sbin/hammer2/hammer2.h @@ -150,6 +150,7 @@ int cmd_rsadec(const char **keys, int nkeys); int cmd_setcomp(const char *comp_str, char **paths); int cmd_setcheck(const char *comp_str, char **paths); int cmd_bulkfree(const char *dir_path); +int cmd_bulkfree_async(const char *dir_path); /* * Misc functions diff --git a/sbin/hammer2/main.c b/sbin/hammer2/main.c index d21c8e3f18..520ed55f64 100644 --- a/sbin/hammer2/main.c +++ b/sbin/hammer2/main.c @@ -422,6 +422,14 @@ main(int ac, char **av) } else { ecode = cmd_bulkfree(av[1]); } + } else if (strcmp(av[0], "bulkfree-async") == 0) { + if (ac != 2) { + fprintf(stderr, + "bulkfree-async: requires path to mount\n"); + usage(1); + } else { + ecode = cmd_bulkfree_async(av[1]); + } } else { fprintf(stderr, "Unrecognized command: %s\n", av[0]); usage(1); @@ -504,6 +512,8 @@ usage(int code) "Set check algo to sha192\n" " bulkfree path... " "Run bulkfree pass\n" + " bulkfree-async path... " + "Run bulkfree pass asynchronously\n" ); exit(code); } diff --git a/sys/vfs/hammer2/hammer2.h b/sys/vfs/hammer2/hammer2.h index ecafffdc12..450918c257 100644 --- a/sys/vfs/hammer2/hammer2.h +++ b/sys/vfs/hammer2/hammer2.h @@ -794,6 +794,7 @@ typedef struct hammer2_trans hammer2_trans_t; */ struct hammer2_thread { struct hammer2_pfs *pmp; + struct hammer2_dev *hmp; hammer2_xop_list_t xopq; thread_t td; uint32_t flags; @@ -815,7 +816,6 @@ typedef struct hammer2_thread hammer2_thread_t; #define HAMMER2_THREAD_XOPQ 0x0080 /* work pending */ #define HAMMER2_THREAD_STOPPED 0x0100 /* thread has stopped */ #define HAMMER2_THREAD_UNFREEZE 0x0200 -#define HAMMER2_THREAD_CLIENTWAIT 0x0400 #define HAMMER2_THREAD_WAKEUP_MASK (HAMMER2_THREAD_UNMOUNTING | \ HAMMER2_THREAD_REMASTER | \ @@ -1070,15 +1070,18 @@ struct hammer2_dev { hammer2_chain_t vchain; /* anchor chain (topology) */ hammer2_chain_t fchain; /* anchor chain (freemap) */ struct spinlock list_spin; - struct h2_flush_list flushq; /* flush seeds */ + struct h2_flush_list flushq; /* flush seeds */ struct hammer2_pfs *spmp; /* super-root pmp for transactions */ - struct lock bulklk; /* bulkfree lock */ struct lock vollk; /* lockmgr lock */ + struct lock bulklk; /* bulkfree operation lock */ + struct lock bflock; /* bulk-free manual function lock */ hammer2_off_t heur_freemap[HAMMER2_FREEMAP_HEUR_SIZE]; hammer2_dedup_t heur_dedup[HAMMER2_DEDUP_HEUR_SIZE]; int volhdrno; /* last volhdrno written */ - int hflags; /* HMNT2 flags applicable to device */ + uint32_t hflags; /* HMNT2 flags applicable to device */ + hammer2_thread_t bfthr; /* bulk-free thread */ char devrepname[64]; /* for kprintf */ + hammer2_ioc_bulkfree_t bflast; /* stats for last bulkfree run */ hammer2_volume_data_t voldata; hammer2_volume_data_t volsync; /* synchronized voldata */ }; @@ -1529,10 +1532,13 @@ void hammer2_io_crc_clrmask(hammer2_io_t *dio, uint64_t mask); * hammer2_thread.c */ void hammer2_thr_signal(hammer2_thread_t *thr, uint32_t flags); -void hammer2_thr_return(hammer2_thread_t *thr, uint32_t flags); +void hammer2_thr_signal2(hammer2_thread_t *thr, + uint32_t pflags, uint32_t nflags); void hammer2_thr_wait(hammer2_thread_t *thr, uint32_t flags); void hammer2_thr_wait_neg(hammer2_thread_t *thr, uint32_t flags); -void hammer2_thr_create(hammer2_thread_t *thr, hammer2_pfs_t *pmp, +int hammer2_thr_wait_any(hammer2_thread_t *thr, uint32_t flags, int timo); +void hammer2_thr_create(hammer2_thread_t *thr, + hammer2_pfs_t *pmp, hammer2_dev_t *hmp, const char *id, int clindex, int repidx, void (*func)(void *arg)); void hammer2_thr_delete(hammer2_thread_t *thr); @@ -1642,8 +1648,9 @@ void hammer2_cluster_resolve(hammer2_cluster_t *cluster); void hammer2_cluster_forcegood(hammer2_cluster_t *cluster); void hammer2_cluster_unlock(hammer2_cluster_t *cluster); -int hammer2_bulkfree_pass(hammer2_dev_t *hmp, - struct hammer2_ioc_bulkfree *bfi); +void hammer2_bulkfree_init(hammer2_dev_t *hmp); +void hammer2_bulkfree_uninit(hammer2_dev_t *hmp); +int hammer2_bulkfree_pass(hammer2_dev_t *hmp, struct hammer2_ioc_bulkfree *bfi); /* * hammer2_iocom.c diff --git a/sys/vfs/hammer2/hammer2_admin.c b/sys/vfs/hammer2/hammer2_admin.c index 0223153c5b..a50640cd65 100644 --- a/sys/vfs/hammer2/hammer2_admin.c +++ b/sys/vfs/hammer2/hammer2_admin.c @@ -38,39 +38,42 @@ #include "hammer2.h" /* - * Signal that the thread has work. + * Set flags and wakeup any waiters. + * + * WARNING! During teardown (thr) can disappear the instant our cmpset + * succeeds. */ void hammer2_thr_signal(hammer2_thread_t *thr, uint32_t flags) { uint32_t oflags; + uint32_t nflags; for (;;) { oflags = thr->flags; cpu_ccfence(); + nflags = (oflags | flags) & ~HAMMER2_THREAD_WAITING; + if (oflags & HAMMER2_THREAD_WAITING) { - if (atomic_cmpset_int(&thr->flags, oflags, - (oflags | flags) & ~HAMMER2_THREAD_WAITING)) { + if (atomic_cmpset_int(&thr->flags, oflags, nflags)) { wakeup(&thr->flags); break; } } else { - if (atomic_cmpset_int(&thr->flags, oflags, - oflags | flags)) { + if (atomic_cmpset_int(&thr->flags, oflags, nflags)) break; - } } } } /* - * Return status to waiting client(s) + * Set and clear flags and wakeup any waiters. * * WARNING! During teardown (thr) can disappear the instant our cmpset * succeeds. */ void -hammer2_thr_return(hammer2_thread_t *thr, uint32_t flags) +hammer2_thr_signal2(hammer2_thread_t *thr, uint32_t posflags, uint32_t negflags) { uint32_t oflags; uint32_t nflags; @@ -78,9 +81,9 @@ hammer2_thr_return(hammer2_thread_t *thr, uint32_t flags) for (;;) { oflags = thr->flags; cpu_ccfence(); - nflags = (oflags | flags) & ~HAMMER2_THREAD_CLIENTWAIT; - - if (oflags & HAMMER2_THREAD_CLIENTWAIT) { + nflags = (oflags | posflags) & + ~(negflags | HAMMER2_THREAD_WAITING); + if (oflags & HAMMER2_THREAD_WAITING) { if (atomic_cmpset_int(&thr->flags, oflags, nflags)) { wakeup(&thr->flags); break; @@ -93,7 +96,7 @@ hammer2_thr_return(hammer2_thread_t *thr, uint32_t flags) } /* - * Wait until the bits in flags are set. + * Wait until all the bits in flags are set. * * WARNING! During teardown (thr) can disappear the instant our cmpset * succeeds. @@ -109,7 +112,7 @@ hammer2_thr_wait(hammer2_thread_t *thr, uint32_t flags) cpu_ccfence(); if ((oflags & flags) == flags) break; - nflags = oflags | HAMMER2_THREAD_CLIENTWAIT; + nflags = oflags | HAMMER2_THREAD_WAITING; tsleep_interlock(&thr->flags, 0); if (atomic_cmpset_int(&thr->flags, oflags, nflags)) { tsleep(&thr->flags, PINTERLOCKED, "h2twait", hz*60); @@ -118,6 +121,37 @@ hammer2_thr_wait(hammer2_thread_t *thr, uint32_t flags) } /* + * Wait until any of the bits in flags are set, with timeout. + * + * WARNING! During teardown (thr) can disappear the instant our cmpset + * succeeds. + */ +int +hammer2_thr_wait_any(hammer2_thread_t *thr, uint32_t flags, int timo) +{ + uint32_t oflags; + uint32_t nflags; + int error; + + error = 0; + for (;;) { + oflags = thr->flags; + cpu_ccfence(); + if (oflags & flags) + break; + nflags = oflags | HAMMER2_THREAD_WAITING; + tsleep_interlock(&thr->flags, 0); + if (atomic_cmpset_int(&thr->flags, oflags, nflags)) { + error = tsleep(&thr->flags, PINTERLOCKED, + "h2twait", timo); + } + if (error == ETIMEDOUT) + break; + } + return error; +} + +/* * Wait until the bits in flags are clear. * * WARNING! During teardown (thr) can disappear the instant our cmpset @@ -134,7 +168,7 @@ hammer2_thr_wait_neg(hammer2_thread_t *thr, uint32_t flags) cpu_ccfence(); if ((oflags & flags) == 0) break; - nflags = oflags | HAMMER2_THREAD_CLIENTWAIT; + nflags = oflags | HAMMER2_THREAD_WAITING; tsleep_interlock(&thr->flags, 0); if (atomic_cmpset_int(&thr->flags, oflags, nflags)) { tsleep(&thr->flags, PINTERLOCKED, "h2twait", hz*60); @@ -151,10 +185,12 @@ hammer2_thr_wait_neg(hammer2_thread_t *thr, uint32_t flags) */ void hammer2_thr_create(hammer2_thread_t *thr, hammer2_pfs_t *pmp, + hammer2_dev_t *hmp, const char *id, int clindex, int repidx, void (*func)(void *arg)) { - thr->pmp = pmp; + thr->pmp = pmp; /* xop helpers */ + thr->hmp = hmp; /* bulkfree */ thr->clindex = clindex; thr->repidx = repidx; TAILQ_INIT(&thr->xopq); @@ -167,9 +203,11 @@ hammer2_thr_create(hammer2_thread_t *thr, hammer2_pfs_t *pmp, if (repidx >= 0) { lwkt_create(func, thr, &thr->td, NULL, 0, repidx % ncpus, "%s-%s.%02d", id, pmp->pfs_names[clindex], repidx); - } else { + } else if (pmp) { lwkt_create(func, thr, &thr->td, NULL, 0, -1, "%s-%s", id, pmp->pfs_names[clindex]); + } else { + lwkt_create(func, thr, &thr->td, NULL, 0, -1, "%s", id); } } @@ -363,7 +401,8 @@ hammer2_xop_helper_create(hammer2_pfs_t *pmp) for (j = 0; j < HAMMER2_XOPGROUPS; ++j) { if (pmp->xop_groups[j].thrs[i].td) continue; - hammer2_thr_create(&pmp->xop_groups[j].thrs[i], pmp, + hammer2_thr_create(&pmp->xop_groups[j].thrs[i], + pmp, NULL, "h2xop", i, j, hammer2_primary_xops_thread); } @@ -977,40 +1016,26 @@ hammer2_primary_xops_thread(void *arg) * Handle freeze request */ if (flags & HAMMER2_THREAD_FREEZE) { - nflags = (flags & ~(HAMMER2_THREAD_FREEZE | - HAMMER2_THREAD_CLIENTWAIT)) | - HAMMER2_THREAD_FROZEN; - if (!atomic_cmpset_int(&thr->flags, flags, nflags)) - continue; - if (flags & HAMMER2_THREAD_CLIENTWAIT) - wakeup(&thr->flags); - flags = nflags; - /* fall through */ + hammer2_thr_signal2(thr, HAMMER2_THREAD_FROZEN, + HAMMER2_THREAD_FREEZE); + continue; } if (flags & HAMMER2_THREAD_UNFREEZE) { - nflags = flags & ~(HAMMER2_THREAD_UNFREEZE | - HAMMER2_THREAD_FROZEN | - HAMMER2_THREAD_CLIENTWAIT); - if (!atomic_cmpset_int(&thr->flags, flags, nflags)) - continue; - if (flags & HAMMER2_THREAD_CLIENTWAIT) - wakeup(&thr->flags); - flags = nflags; - /* fall through */ + hammer2_thr_signal2(thr, 0, + HAMMER2_THREAD_FROZEN | + HAMMER2_THREAD_UNFREEZE); + continue; } /* * Force idle if frozen until unfrozen or stopped. */ if (flags & HAMMER2_THREAD_FROZEN) { - nflags = flags | HAMMER2_THREAD_WAITING; - tsleep_interlock(&thr->flags, 0); - if (atomic_cmpset_int(&thr->flags, flags, nflags)) { - tsleep(&thr->flags, PINTERLOCKED, "frozen", 0); - atomic_clear_int(&thr->flags, - HAMMER2_THREAD_WAITING); - } + hammer2_thr_wait_any(thr, + HAMMER2_THREAD_UNFREEZE | + HAMMER2_THREAD_STOP, + 0); continue; } @@ -1018,10 +1043,8 @@ hammer2_primary_xops_thread(void *arg) * Reset state on REMASTER request */ if (flags & HAMMER2_THREAD_REMASTER) { - nflags = flags & ~HAMMER2_THREAD_REMASTER; - if (atomic_cmpset_int(&thr->flags, flags, nflags)) { - /* reset state here */ - } + hammer2_thr_signal2(thr, 0, HAMMER2_THREAD_REMASTER); + /* reset state here */ continue; } @@ -1067,7 +1090,6 @@ hammer2_primary_xops_thread(void *arg) tsleep_interlock(&thr->flags, 0); if (atomic_cmpset_int(&thr->flags, flags, nflags)) { tsleep(&thr->flags, PINTERLOCKED, "h2idle", hz*30); - atomic_clear_int(&thr->flags, HAMMER2_THREAD_WAITING); } } @@ -1083,6 +1105,6 @@ hammer2_primary_xops_thread(void *arg) } #endif thr->td = NULL; - hammer2_thr_return(thr, HAMMER2_THREAD_STOPPED); + hammer2_thr_signal(thr, HAMMER2_THREAD_STOPPED); /* thr structure can go invalid after this point */ } diff --git a/sys/vfs/hammer2/hammer2_bulkfree.c b/sys/vfs/hammer2/hammer2_bulkfree.c index 3744f389f7..c3585d46b9 100644 --- a/sys/vfs/hammer2/hammer2_bulkfree.c +++ b/sys/vfs/hammer2/hammer2_bulkfree.c @@ -244,6 +244,7 @@ hammer2_bulk_scan(hammer2_chain_t *parent, /* * Bulkfree callback info */ +static void hammer2_bulkfree_thread(void *arg __unused); static void cbinfo_bmap_init(hammer2_bulkfree_info_t *cbinfo, size_t size); static int h2_bulkfree_callback(hammer2_bulkfree_info_t *cbinfo, hammer2_blockref_t *bref); @@ -252,6 +253,64 @@ static void h2_bulkfree_sync_adjust(hammer2_bulkfree_info_t *cbinfo, hammer2_off_t data_off, hammer2_bmap_data_t *live, hammer2_bmap_data_t *bmap, int nofree); +void +hammer2_bulkfree_init(hammer2_dev_t *hmp) +{ + hammer2_thr_create(&hmp->bfthr, NULL, hmp, + hmp->devrepname, -1, -1, + hammer2_bulkfree_thread); +} + +void +hammer2_bulkfree_uninit(hammer2_dev_t *hmp) +{ + hammer2_thr_delete(&hmp->bfthr); +} + +static void +hammer2_bulkfree_thread(void *arg) +{ + hammer2_thread_t *thr = arg; + hammer2_ioc_bulkfree_t bfi; + uint32_t flags; + + for (;;) { + hammer2_thr_wait_any(thr, + HAMMER2_THREAD_STOP | + HAMMER2_THREAD_FREEZE | + HAMMER2_THREAD_UNFREEZE | + HAMMER2_THREAD_REMASTER, + hz * 60); + + flags = thr->flags; + cpu_ccfence(); + if (flags & HAMMER2_THREAD_STOP) + break; + if (flags & HAMMER2_THREAD_FREEZE) { + hammer2_thr_signal2(thr, HAMMER2_THREAD_FROZEN, + HAMMER2_THREAD_FREEZE); + continue; + } + if (flags & HAMMER2_THREAD_UNFREEZE) { + hammer2_thr_signal2(thr, 0, + HAMMER2_THREAD_FROZEN | + HAMMER2_THREAD_UNFREEZE); + continue; + } + if (flags & HAMMER2_THREAD_FROZEN) + continue; + if (flags & HAMMER2_THREAD_REMASTER) { + hammer2_thr_signal2(thr, 0, HAMMER2_THREAD_REMASTER); + bzero(&bfi, sizeof(bfi)); + bfi.size = 8192 * 1024; + hammer2_bulkfree_pass(thr->hmp, &bfi); + } + } + thr->td = NULL; + hammer2_thr_signal(thr, HAMMER2_THREAD_STOPPED); + /* structure can go invalid at this point */ +} + int hammer2_bulkfree_pass(hammer2_dev_t *hmp, hammer2_ioc_bulkfree_t *bfi) { diff --git a/sys/vfs/hammer2/hammer2_ioctl.c b/sys/vfs/hammer2/hammer2_ioctl.c index 4335c31b28..4f4b8c9a18 100644 --- a/sys/vfs/hammer2/hammer2_ioctl.c +++ b/sys/vfs/hammer2/hammer2_ioctl.c @@ -137,6 +137,9 @@ hammer2_ioctl(hammer2_inode_t *ip, u_long com, void *data, int fflag, case HAMMER2IOC_BULKFREE_SCAN: error = hammer2_ioctl_bulkfree_scan(ip, data); break; + case HAMMER2IOC_BULKFREE_ASYNC: + error = hammer2_ioctl_bulkfree_scan(ip, NULL); + break; /*case HAMMER2IOC_INODE_COMP_SET: error = hammer2_ioctl_inode_comp_set(ip, data); break; @@ -928,7 +931,22 @@ hammer2_ioctl_bulkfree_scan(hammer2_inode_t *ip, void *data) if (hmp == NULL) return (EINVAL); - error = hammer2_bulkfree_pass(hmp, bfi); + /* + * Negotiate for manual access. The hammer2_bulkfree_pass() itself + * also has its own lock and will deal with a manual override when + * an automatic bulkfree is already running. + */ + error = lockmgr(&hmp->bflock, LK_EXCLUSIVE | LK_PCATCH); + if (error) + return error; + if (bfi) { + hammer2_thr_freeze(&hmp->bfthr); + error = hammer2_bulkfree_pass(hmp, bfi); + hammer2_thr_unfreeze(&hmp->bfthr); + } else { + hammer2_thr_remaster(&hmp->bfthr); + } + lockmgr(&hmp->bflock, LK_RELEASE); return error; } diff --git a/sys/vfs/hammer2/hammer2_ioctl.h b/sys/vfs/hammer2/hammer2_ioctl.h index a719c5399e..7664c7b181 100644 --- a/sys/vfs/hammer2/hammer2_ioctl.h +++ b/sys/vfs/hammer2/hammer2_ioctl.h @@ -166,5 +166,6 @@ typedef struct hammer2_ioc_bulkfree hammer2_ioc_bulkfree_t; #define HAMMER2IOC_INODE_COMP_REC_SET2 _IOWR('h', 90, struct hammer2_ioc_inode)*/ #define HAMMER2IOC_DEBUG_DUMP _IOWR('h', 91, int) #define HAMMER2IOC_BULKFREE_SCAN _IOWR('h', 92, struct hammer2_ioc_bulkfree) +#define HAMMER2IOC_BULKFREE_ASYNC _IOWR('h', 93, struct hammer2_ioc_bulkfree) #endif /* !_VFS_HAMMER2_IOCTL_H_ */ diff --git a/sys/vfs/hammer2/hammer2_subr.c b/sys/vfs/hammer2/hammer2_subr.c index daeb89df19..f09e445c65 100644 --- a/sys/vfs/hammer2/hammer2_subr.c +++ b/sys/vfs/hammer2/hammer2_subr.c @@ -398,16 +398,24 @@ hammer2_adjreadcounter(hammer2_blockref_t *bref, size_t bytes) *counterp += bytes; } +/* + * Check for pending signal to allow interruption. This function will + * return immediately if the calling thread is a kernel thread and not + * a user thread. + */ int hammer2_signal_check(time_t *timep) { + thread_t td = curthread; int error = 0; - lwkt_user_yield(); - if (*timep != time_second) { - *timep = time_second; - if (CURSIG_NOBLOCK(curthread->td_lwp) != 0) - error = EINTR; + if (td->td_lwp) { + lwkt_user_yield(); + if (*timep != time_second) { + *timep = time_second; + if (CURSIG_NOBLOCK(curthread->td_lwp) != 0) + error = EINTR; + } } return error; } diff --git a/sys/vfs/hammer2/hammer2_synchro.c b/sys/vfs/hammer2/hammer2_synchro.c index fcecb4238b..c7f9079c65 100644 --- a/sys/vfs/hammer2/hammer2_synchro.c +++ b/sys/vfs/hammer2/hammer2_synchro.c @@ -125,11 +125,11 @@ hammer2_primary_sync_thread(void *arg) */ if (flags & HAMMER2_THREAD_FREEZE) { nflags = (flags & ~(HAMMER2_THREAD_FREEZE | - HAMMER2_THREAD_CLIENTWAIT)) | + HAMMER2_THREAD_WAITING)) | HAMMER2_THREAD_FROZEN; if (!atomic_cmpset_int(&thr->flags, flags, nflags)) continue; - if (flags & HAMMER2_THREAD_CLIENTWAIT) + if (flags & HAMMER2_THREAD_WAITING) wakeup(&thr->flags); flags = nflags; /* fall through */ @@ -138,10 +138,10 @@ hammer2_primary_sync_thread(void *arg) if (flags & HAMMER2_THREAD_UNFREEZE) { nflags = flags & ~(HAMMER2_THREAD_UNFREEZE | HAMMER2_THREAD_FROZEN | - HAMMER2_THREAD_CLIENTWAIT); + HAMMER2_THREAD_WAITING); if (!atomic_cmpset_int(&thr->flags, flags, nflags)) continue; - if (flags & HAMMER2_THREAD_CLIENTWAIT) + if (flags & HAMMER2_THREAD_WAITING) wakeup(&thr->flags); flags = nflags; /* fall through */ @@ -255,7 +255,7 @@ hammer2_primary_sync_thread(void *arg) } } thr->td = NULL; - hammer2_thr_return(thr, HAMMER2_THREAD_STOPPED); + hammer2_thr_signal(thr, HAMMER2_THREAD_STOPPED); /* thr structure can go invalid after this point */ } diff --git a/sys/vfs/hammer2/hammer2_vfsops.c b/sys/vfs/hammer2/hammer2_vfsops.c index 74e887e233..6adb96f448 100644 --- a/sys/vfs/hammer2/hammer2_vfsops.c +++ b/sys/vfs/hammer2/hammer2_vfsops.c @@ -518,7 +518,7 @@ hammer2_pfsalloc(hammer2_chain_t *chain, * Sync support thread */ if (pmp->sync_thrs[i].td == NULL) { - hammer2_thr_create(&pmp->sync_thrs[i], pmp, + hammer2_thr_create(&pmp->sync_thrs[i], pmp, NULL, "h2nod", i, -1, hammer2_primary_sync_thread); } @@ -1068,6 +1068,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data, lockinit(&hmp->vollk, "h2vol", 0, 0); lockinit(&hmp->bulklk, "h2bulk", 0, 0); + lockinit(&hmp->bflock, "h2bflk", 0, 0); /* * vchain setup. vchain.data is embedded. @@ -1215,6 +1216,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data, } hammer2_update_pmps(hmp); hammer2_iocom_init(hmp); + hammer2_bulkfree_init(hmp); /* * Ref the cluster management messaging descriptor. The mount @@ -1600,6 +1602,7 @@ again: if (hmp->mount_count) return; + hammer2_bulkfree_uninit(hmp); hammer2_pfsfree_scan(hmp); hammer2_dev_exlock(hmp); /* XXX order */ -- 2.11.4.GIT