2 * Copyright (c) 2015 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@dragonflybsd.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * This module implements various PFS-based helper threads.
39 static void hammer2_sync_slaves(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
40 hammer2_cluster_t **cparentp);
41 static void hammer2_update_pfs_status(hammer2_pfs_t *pmp,
42 hammer2_cluster_t *cparent);
45 * Initialize the suspplied syncthr structure, starting the specified
49 hammer2_syncthr_create(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
50 void (*func)(void *arg))
52 lockinit(&thr->lk, "h2syncthr", 0, 0);
54 lwkt_create(func, thr, &thr->td, NULL, 0, -1, "h2pfs");
58 * Terminate a syncthr. This function will silently return if the syncthr
59 * was never initialized or has already been deleted.
61 * This is accomplished by setting the STOP flag and waiting for the td
62 * structure to become NULL.
65 hammer2_syncthr_delete(hammer2_syncthr_t *thr)
69 lockmgr(&thr->lk, LK_EXCLUSIVE);
70 atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_STOP);
73 lksleep(thr, &thr->lk, 0, "h2thr", hz);
75 lockmgr(&thr->lk, LK_RELEASE);
81 * Asynchronous remaster request. Ask the synchronization thread to
82 * start over soon (as if it were frozen and unfrozen, but without waiting).
83 * The thread always recalculates mastership relationships when restarting.
86 hammer2_syncthr_remaster(hammer2_syncthr_t *thr)
90 lockmgr(&thr->lk, LK_EXCLUSIVE);
91 atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_REMASTER);
93 lockmgr(&thr->lk, LK_RELEASE);
97 hammer2_syncthr_freeze(hammer2_syncthr_t *thr)
101 lockmgr(&thr->lk, LK_EXCLUSIVE);
102 atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_FREEZE);
104 while ((thr->flags & HAMMER2_SYNCTHR_FROZEN) == 0) {
105 lksleep(thr, &thr->lk, 0, "h2frz", hz);
107 lockmgr(&thr->lk, LK_RELEASE);
111 hammer2_syncthr_unfreeze(hammer2_syncthr_t *thr)
115 lockmgr(&thr->lk, LK_EXCLUSIVE);
116 atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_FROZEN);
118 lockmgr(&thr->lk, LK_RELEASE);
122 * Primary management thread.
124 * On the SPMP - handles bulkfree and dedup operations
125 * On a PFS - handles remastering and synchronization
128 hammer2_syncthr_primary(void *arg)
130 hammer2_syncthr_t *thr = arg;
131 hammer2_cluster_t *cparent;
133 hammer2_trans_t trans;
137 lockmgr(&thr->lk, LK_EXCLUSIVE);
138 while ((thr->flags & HAMMER2_SYNCTHR_STOP) == 0) {
140 * Handle freeze request
142 if (thr->flags & HAMMER2_SYNCTHR_FREEZE) {
143 atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_FROZEN);
144 atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_FREEZE);
148 * Force idle if frozen until unfrozen or stopped.
150 if (thr->flags & HAMMER2_SYNCTHR_FROZEN) {
151 lksleep(&thr->flags, &thr->lk, 0, "h2idle", 0);
156 * Reset state on REMASTER request
158 if (thr->flags & HAMMER2_SYNCTHR_REMASTER) {
159 atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_REMASTER);
164 * Synchronization scan.
166 hammer2_trans_init(&trans, pmp, 0);
167 cparent = hammer2_inode_lock(pmp->iroot, HAMMER2_RESOLVE_NEVER);
168 hammer2_update_pfs_status(pmp, cparent);
169 hammer2_sync_slaves(thr, pmp, &cparent);
170 hammer2_inode_unlock(pmp->iroot, cparent);
171 hammer2_trans_done(&trans);
174 * Wait for event, or 5-second poll.
176 lksleep(&thr->flags, &thr->lk, 0, "h2idle", hz * 5);
180 lockmgr(&thr->lk, LK_RELEASE);
181 /* thr structure can go invalid after this point */
185 * Given a locked cluster created from pmp->iroot, update the PFS's
190 hammer2_update_pfs_status(hammer2_pfs_t *pmp, hammer2_cluster_t *cparent)
194 flags = cparent->flags & HAMMER2_CLUSTER_ZFLAGS;
195 if (pmp->status_flags == flags)
197 pmp->status_flags = flags;
199 kprintf("pfs %p", pmp);
200 if (flags & HAMMER2_CLUSTER_MSYNCED)
201 kprintf(" masters-all-good");
202 if (flags & HAMMER2_CLUSTER_SSYNCED)
203 kprintf(" slaves-all-good");
205 if (flags & HAMMER2_CLUSTER_WRHARD)
206 kprintf(" quorum/rw");
207 else if (flags & HAMMER2_CLUSTER_RDHARD)
208 kprintf(" quorum/ro");
210 if (flags & HAMMER2_CLUSTER_UNHARD)
211 kprintf(" out-of-sync-masters");
212 else if (flags & HAMMER2_CLUSTER_NOHARD)
213 kprintf(" no-masters-visible");
215 if (flags & HAMMER2_CLUSTER_WRSOFT)
217 else if (flags & HAMMER2_CLUSTER_RDSOFT)
220 if (flags & HAMMER2_CLUSTER_UNSOFT)
221 kprintf(" out-of-sync-slaves");
222 else if (flags & HAMMER2_CLUSTER_NOSOFT)
223 kprintf(" no-slaves-visible");
232 hammer2_sync_slaves(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
233 hammer2_cluster_t **cparentp)