hammer2 - update documentation, cleanup
[dragonfly.git] / sys / vfs / hammer2 / hammer2_syncthr.c
1 /*
2  * Copyright (c) 2015 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@dragonflybsd.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
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
16  *    distribution.
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.
20  *
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
32  * SUCH DAMAGE.
33  */
34 /*
35  * This module implements various PFS-based helper threads.
36  */
37 #include "hammer2.h"
38
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);
43
44 /*
45  * Initialize the suspplied syncthr structure, starting the specified
46  * thread.
47  */
48 void
49 hammer2_syncthr_create(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
50                        void (*func)(void *arg))
51 {
52         lockinit(&thr->lk, "h2syncthr", 0, 0);
53         thr->pmp = pmp;
54         lwkt_create(func, thr, &thr->td, NULL, 0, -1, "h2pfs");
55 }
56
57 /*
58  * Terminate a syncthr.  This function will silently return if the syncthr
59  * was never initialized or has already been deleted.
60  *
61  * This is accomplished by setting the STOP flag and waiting for the td
62  * structure to become NULL.
63  */
64 void
65 hammer2_syncthr_delete(hammer2_syncthr_t *thr)
66 {
67         if (thr->td == NULL)
68                 return;
69         lockmgr(&thr->lk, LK_EXCLUSIVE);
70         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_STOP);
71         wakeup(&thr->flags);
72         while (thr->td) {
73                 lksleep(thr, &thr->lk, 0, "h2thr", hz);
74         }
75         lockmgr(&thr->lk, LK_RELEASE);
76         thr->pmp = NULL;
77         lockuninit(&thr->lk);
78 }
79
80 /*
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.
84  */
85 void
86 hammer2_syncthr_remaster(hammer2_syncthr_t *thr)
87 {
88         if (thr->td == NULL)
89                 return;
90         lockmgr(&thr->lk, LK_EXCLUSIVE);
91         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_REMASTER);
92         wakeup(&thr->flags);
93         lockmgr(&thr->lk, LK_RELEASE);
94 }
95
96 void
97 hammer2_syncthr_freeze(hammer2_syncthr_t *thr)
98 {
99         if (thr->td == NULL)
100                 return;
101         lockmgr(&thr->lk, LK_EXCLUSIVE);
102         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_FREEZE);
103         wakeup(&thr->flags);
104         while ((thr->flags & HAMMER2_SYNCTHR_FROZEN) == 0) {
105                 lksleep(thr, &thr->lk, 0, "h2frz", hz);
106         }
107         lockmgr(&thr->lk, LK_RELEASE);
108 }
109
110 void
111 hammer2_syncthr_unfreeze(hammer2_syncthr_t *thr)
112 {
113         if (thr->td == NULL)
114                 return;
115         lockmgr(&thr->lk, LK_EXCLUSIVE);
116         atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_FROZEN);
117         wakeup(&thr->flags);
118         lockmgr(&thr->lk, LK_RELEASE);
119 }
120
121 /*
122  * Primary management thread.
123  *
124  * On the SPMP - handles bulkfree and dedup operations
125  * On a PFS    - handles remastering and synchronization
126  */
127 void
128 hammer2_syncthr_primary(void *arg)
129 {
130         hammer2_syncthr_t *thr = arg;
131         hammer2_cluster_t *cparent;
132         hammer2_pfs_t *pmp;
133         hammer2_trans_t trans;
134
135         pmp = thr->pmp;
136
137         lockmgr(&thr->lk, LK_EXCLUSIVE);
138         while ((thr->flags & HAMMER2_SYNCTHR_STOP) == 0) {
139                 /*
140                  * Handle freeze request
141                  */
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);
145                 }
146
147                 /*
148                  * Force idle if frozen until unfrozen or stopped.
149                  */
150                 if (thr->flags & HAMMER2_SYNCTHR_FROZEN) {
151                         lksleep(&thr->flags, &thr->lk, 0, "h2idle", 0);
152                         continue;
153                 }
154
155                 /*
156                  * Reset state on REMASTER request
157                  */
158                 if (thr->flags & HAMMER2_SYNCTHR_REMASTER) {
159                         atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_REMASTER);
160                         /* reset state */
161                 }
162
163                 /*
164                  * Synchronization scan.
165                  */
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);
172
173                 /*
174                  * Wait for event, or 5-second poll.
175                  */
176                 lksleep(&thr->flags, &thr->lk, 0, "h2idle", hz * 5);
177         }
178         thr->td = NULL;
179         wakeup(thr);
180         lockmgr(&thr->lk, LK_RELEASE);
181         /* thr structure can go invalid after this point */
182 }
183
184 /*
185  * Given a locked cluster created from pmp->iroot, update the PFS's
186  * reporting status.
187  */
188 static
189 void
190 hammer2_update_pfs_status(hammer2_pfs_t *pmp, hammer2_cluster_t *cparent)
191 {
192         uint32_t flags;
193
194         flags = cparent->flags & HAMMER2_CLUSTER_ZFLAGS;
195         if (pmp->status_flags == flags)
196                 return;
197         pmp->status_flags = flags;
198
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");
204
205         if (flags & HAMMER2_CLUSTER_WRHARD)
206                 kprintf(" quorum/rw");
207         else if (flags & HAMMER2_CLUSTER_RDHARD)
208                 kprintf(" quorum/ro");
209
210         if (flags & HAMMER2_CLUSTER_UNHARD)
211                 kprintf(" out-of-sync-masters");
212         else if (flags & HAMMER2_CLUSTER_NOHARD)
213                 kprintf(" no-masters-visible");
214
215         if (flags & HAMMER2_CLUSTER_WRSOFT)
216                 kprintf(" soft/rw");
217         else if (flags & HAMMER2_CLUSTER_RDSOFT)
218                 kprintf(" soft/ro");
219
220         if (flags & HAMMER2_CLUSTER_UNSOFT)
221                 kprintf(" out-of-sync-slaves");
222         else if (flags & HAMMER2_CLUSTER_NOSOFT)
223                 kprintf(" no-slaves-visible");
224         kprintf("\n");
225 }
226
227 /*
228  *
229  */
230 static
231 void
232 hammer2_sync_slaves(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
233                     hammer2_cluster_t **cparentp)
234 {
235
236
237 }