hammer2 - Add kernel-thread-based async bulk free
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 18 Aug 2017 23:00:54 +0000 (16:00 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 18 Aug 2017 23:00:54 +0000 (16:00 -0700)
* 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
sbin/hammer2/hammer2.h
sbin/hammer2/main.c
sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_admin.c
sys/vfs/hammer2/hammer2_bulkfree.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_ioctl.h
sys/vfs/hammer2/hammer2_subr.c
sys/vfs/hammer2/hammer2_synchro.c
sys/vfs/hammer2/hammer2_vfsops.c

index dc27394..657ae49 100644 (file)
@@ -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;
+}
index 6a91a37..4405fad 100644 (file)
@@ -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
index d21c8e3..520ed55 100644 (file)
@@ -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);
 }
index ecafffd..450918c 100644 (file)
@@ -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
index 0223153..a50640c 100644 (file)
 #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);
@@ -117,6 +120,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.
  *
@@ -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 */
 }
index 3744f38..c3585d4 100644 (file)
@@ -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)
 {
index 4335c31..4f4b8c9 100644 (file)
@@ -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;
 }
index a719c53..7664c7b 100644 (file)
@@ -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_ */
index daeb89d..f09e445 100644 (file)
@@ -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;
 }
index fcecb42..c7f9079 100644 (file)
@@ -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 */
 }
 
index 74e887e..6adb96f 100644 (file)
@@ -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 */