]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - fs/gfs2/locking/dlm/mount.c
[DLM] lock_dlm recover_status patch
[mirror_ubuntu-jammy-kernel.git] / fs / gfs2 / locking / dlm / mount.c
CommitLineData
869d81df
DT
1/*
2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
4 *
5 * This copyrighted material is made available to anyone wishing to use,
6 * modify, copy, or redistribute it subject to the terms and conditions
7 * of the GNU General Public License v.2.
8 */
29b7998d
DT
9
10#include "lock_dlm.h"
11
12int gdlm_drop_count;
13int gdlm_drop_period;
14struct lm_lockops gdlm_ops;
15
16
17static struct gdlm_ls *init_gdlm(lm_callback_t cb, lm_fsdata_t *fsdata,
18 int flags, char *table_name)
19{
20 struct gdlm_ls *ls;
21 char buf[256], *p;
22
869d81df 23 ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
29b7998d
DT
24 if (!ls)
25 return NULL;
26
29b7998d
DT
27 ls->drop_locks_count = gdlm_drop_count;
28 ls->drop_locks_period = gdlm_drop_period;
29b7998d
DT
29 ls->fscb = cb;
30 ls->fsdata = fsdata;
31 ls->fsflags = flags;
29b7998d 32 spin_lock_init(&ls->async_lock);
29b7998d
DT
33 INIT_LIST_HEAD(&ls->complete);
34 INIT_LIST_HEAD(&ls->blocking);
35 INIT_LIST_HEAD(&ls->delayed);
36 INIT_LIST_HEAD(&ls->submit);
37 INIT_LIST_HEAD(&ls->all_locks);
29b7998d
DT
38 init_waitqueue_head(&ls->thread_wait);
39 init_waitqueue_head(&ls->wait_control);
40 ls->thread1 = NULL;
41 ls->thread2 = NULL;
42 ls->drop_time = jiffies;
43 ls->jid = -1;
44
45 strncpy(buf, table_name, 256);
46 buf[255] = '\0';
47
48 p = strstr(buf, ":");
49 if (!p) {
869d81df 50 log_info("invalid table_name \"%s\"", table_name);
29b7998d
DT
51 kfree(ls);
52 return NULL;
53 }
54 *p = '\0';
55 p++;
56
869d81df
DT
57 strncpy(ls->clustername, buf, GDLM_NAME_LEN);
58 strncpy(ls->fsname, p, GDLM_NAME_LEN);
29b7998d
DT
59
60 return ls;
61}
62
7aabffca 63static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
869d81df
DT
64{
65 char data[256];
66 char *options, *x, *y;
67 int error = 0;
68
69 memset(data, 0, 256);
70 strncpy(data, data_arg, 255);
71
72 for (options = data; (x = strsep(&options, ":")); ) {
73 if (!*x)
74 continue;
75
76 y = strchr(x, '=');
77 if (y)
78 *y++ = 0;
79
80 if (!strcmp(x, "jid")) {
81 if (!y) {
82 log_error("need argument to jid");
83 error = -EINVAL;
84 break;
85 }
86 sscanf(y, "%u", &ls->jid);
87
88 } else if (!strcmp(x, "first")) {
89 if (!y) {
90 log_error("need argument to first");
91 error = -EINVAL;
92 break;
93 }
94 sscanf(y, "%u", &ls->first);
95
96 } else if (!strcmp(x, "id")) {
97 if (!y) {
98 log_error("need argument to id");
99 error = -EINVAL;
100 break;
101 }
102 sscanf(y, "%u", &ls->id);
103
7aabffca
DT
104 } else if (!strcmp(x, "nodir")) {
105 if (!y) {
106 log_error("need argument to nodir");
107 error = -EINVAL;
108 break;
109 }
110 sscanf(y, "%u", nodir);
111
869d81df
DT
112 } else {
113 log_error("unkonwn option: %s", x);
114 error = -EINVAL;
115 break;
116 }
117 }
118
119 return error;
120}
121
29b7998d
DT
122static int gdlm_mount(char *table_name, char *host_data,
123 lm_callback_t cb, lm_fsdata_t *fsdata,
124 unsigned int min_lvb_size, int flags,
869d81df
DT
125 struct lm_lockstruct *lockstruct,
126 struct kobject *fskobj)
29b7998d
DT
127{
128 struct gdlm_ls *ls;
7aabffca 129 int error = -ENOMEM, nodir = 0;
29b7998d
DT
130
131 if (min_lvb_size > GDLM_LVB_SIZE)
132 goto out;
133
134 ls = init_gdlm(cb, fsdata, flags, table_name);
135 if (!ls)
136 goto out;
137
7aabffca
DT
138 error = make_args(ls, host_data, &nodir);
139 if (error)
140 goto out;
141
29b7998d
DT
142 error = gdlm_init_threads(ls);
143 if (error)
144 goto out_free;
145
146 error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
7aabffca
DT
147 &ls->dlm_lockspace,
148 nodir ? DLM_LSFL_NODIR : 0,
149 GDLM_LVB_SIZE);
29b7998d 150 if (error) {
869d81df 151 log_error("dlm_new_lockspace error %d", error);
29b7998d
DT
152 goto out_thread;
153 }
154
869d81df 155 error = gdlm_kobject_setup(ls, fskobj);
29b7998d
DT
156 if (error)
157 goto out_dlm;
29b7998d 158
29b7998d
DT
159 lockstruct->ls_jid = ls->jid;
160 lockstruct->ls_first = ls->first;
161 lockstruct->ls_lockspace = ls;
162 lockstruct->ls_ops = &gdlm_ops;
163 lockstruct->ls_flags = 0;
164 lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
165 return 0;
166
29b7998d
DT
167 out_dlm:
168 dlm_release_lockspace(ls->dlm_lockspace, 2);
169 out_thread:
170 gdlm_release_threads(ls);
171 out_free:
172 kfree(ls);
173 out:
174 return error;
175}
176
177static void gdlm_unmount(lm_lockspace_t *lockspace)
178{
179 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
180 int rv;
181
182 log_debug("unmount flags %lx", ls->flags);
183
869d81df
DT
184 /* FIXME: serialize unmount and withdraw in case they
185 happen at once. Also, if unmount follows withdraw,
186 wait for withdraw to finish. */
29b7998d 187
869d81df
DT
188 if (test_bit(DFL_WITHDRAW, &ls->flags))
189 goto out;
29b7998d
DT
190
191 gdlm_kobject_release(ls);
192 dlm_release_lockspace(ls->dlm_lockspace, 2);
193 gdlm_release_threads(ls);
194 rv = gdlm_release_all_locks(ls);
195 if (rv)
869d81df 196 log_info("gdlm_unmount: %d stray locks freed", rv);
29b7998d
DT
197 out:
198 kfree(ls);
199}
200
201static void gdlm_recovery_done(lm_lockspace_t *lockspace, unsigned int jid,
202 unsigned int message)
203{
204 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
869d81df 205 ls->recover_jid_done = jid;
6bd70aba 206 ls->recover_jid_status = message;
5ddec5b3 207 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
29b7998d
DT
208}
209
210static void gdlm_others_may_mount(lm_lockspace_t *lockspace)
211{
212 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
213 ls->first_done = 1;
5ddec5b3 214 kobject_uevent(&ls->kobj, KOBJ_CHANGE);
29b7998d
DT
215}
216
869d81df
DT
217/* Userspace gets the offline uevent, blocks new gfs locks on
218 other mounters, and lets us know (sets WITHDRAW flag). Then,
219 userspace leaves the mount group while we leave the lockspace. */
220
29b7998d
DT
221static void gdlm_withdraw(lm_lockspace_t *lockspace)
222{
223 struct gdlm_ls *ls = (struct gdlm_ls *) lockspace;
224
5ddec5b3 225 kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
29b7998d
DT
226
227 wait_event_interruptible(ls->wait_control,
228 test_bit(DFL_WITHDRAW, &ls->flags));
229
230 dlm_release_lockspace(ls->dlm_lockspace, 2);
231 gdlm_release_threads(ls);
232 gdlm_release_all_locks(ls);
869d81df 233 gdlm_kobject_release(ls);
29b7998d
DT
234}
235
236struct lm_lockops gdlm_ops = {
869d81df
DT
237 .lm_proto_name = "lock_dlm",
238 .lm_mount = gdlm_mount,
239 .lm_others_may_mount = gdlm_others_may_mount,
240 .lm_unmount = gdlm_unmount,
241 .lm_withdraw = gdlm_withdraw,
242 .lm_get_lock = gdlm_get_lock,
243 .lm_put_lock = gdlm_put_lock,
244 .lm_lock = gdlm_lock,
245 .lm_unlock = gdlm_unlock,
246 .lm_plock = gdlm_plock,
247 .lm_punlock = gdlm_punlock,
248 .lm_plock_get = gdlm_plock_get,
249 .lm_cancel = gdlm_cancel,
250 .lm_hold_lvb = gdlm_hold_lvb,
251 .lm_unhold_lvb = gdlm_unhold_lvb,
252 .lm_sync_lvb = gdlm_sync_lvb,
253 .lm_recovery_done = gdlm_recovery_done,
254 .lm_owner = THIS_MODULE,
29b7998d
DT
255};
256