hammer2 - Initial synchronization thread
[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 /*
40  * Initialize the suspplied syncthr structure, starting the specified
41  * thread.
42  */
43 void
44 hammer2_syncthr_create(hammer2_syncthr_t *thr, hammer2_pfs_t *pmp,
45                        void (*func)(void *arg))
46 {
47         lockinit(&thr->lk, "h2syncthr", 0, 0);
48         thr->pmp = pmp;
49         lwkt_create(func, thr, &thr->td, NULL, 0, -1, "h2pfs");
50 }
51
52 /*
53  * Terminate a syncthr.  This function will silently return if the syncthr
54  * was never initialized or has already been deleted.
55  *
56  * This is accomplished by setting the STOP flag and waiting for the td
57  * structure to become NULL.
58  */
59 void
60 hammer2_syncthr_delete(hammer2_syncthr_t *thr)
61 {
62         if (thr->td == NULL)
63                 return;
64         lockmgr(&thr->lk, LK_EXCLUSIVE);
65         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_STOP);
66         wakeup(&thr->flags);
67         while (thr->td) {
68                 lksleep(thr, &thr->lk, 0, "h2thr", hz);
69         }
70         lockmgr(&thr->lk, LK_RELEASE);
71         thr->pmp = NULL;
72         lockuninit(&thr->lk);
73 }
74
75 void
76 hammer2_syncthr_remaster(hammer2_syncthr_t *thr)
77 {
78         if (thr->td == NULL)
79                 return;
80         lockmgr(&thr->lk, LK_EXCLUSIVE);
81         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_REMASTER);
82         wakeup(&thr->flags);
83         lockmgr(&thr->lk, LK_RELEASE);
84 }
85
86 void
87 hammer2_syncthr_freeze(hammer2_syncthr_t *thr)
88 {
89         if (thr->td == NULL)
90                 return;
91         lockmgr(&thr->lk, LK_EXCLUSIVE);
92         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_FREEZE);
93         wakeup(&thr->flags);
94         while ((thr->flags & HAMMER2_SYNCTHR_FROZEN) == 0) {
95                 lksleep(thr, &thr->lk, 0, "h2frz", hz);
96         }
97         lockmgr(&thr->lk, LK_RELEASE);
98 }
99
100 void
101 hammer2_syncthr_unfreeze(hammer2_syncthr_t *thr)
102 {
103         if (thr->td == NULL)
104                 return;
105         lockmgr(&thr->lk, LK_EXCLUSIVE);
106         atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_FROZEN);
107         wakeup(&thr->flags);
108         lockmgr(&thr->lk, LK_RELEASE);
109 }
110
111 /*
112  * Primary management thread
113  */
114 void
115 hammer2_syncthr_primary(void *arg)
116 {
117         hammer2_syncthr_t *thr = arg;
118
119         lockmgr(&thr->lk, LK_EXCLUSIVE);
120         while ((thr->flags & HAMMER2_SYNCTHR_STOP) == 0) {
121                 /*
122                  * Handle freeze request
123                  */
124                 if (thr->flags & HAMMER2_SYNCTHR_FREEZE) {
125                         atomic_set_int(&thr->flags, HAMMER2_SYNCTHR_FROZEN);
126                         atomic_clear_int(&thr->flags, HAMMER2_SYNCTHR_FREEZE);
127                 }
128
129                 /*
130                  * Force idle if frozen until unfrozen or stopped.
131                  */
132                 if (thr->flags & HAMMER2_SYNCTHR_FROZEN) {
133                         lksleep(&thr->flags, &thr->lk, 0, "h2idle", 0);
134                         continue;
135                 }
136                 lksleep(&thr->flags, &thr->lk, 0, "h2idle", 0);
137         }
138         thr->td = NULL;
139         wakeup(thr);
140         lockmgr(&thr->lk, LK_RELEASE);
141         /* thr structure can go invalid after this point */
142 }