[GFS2] Remove remote lock dropping code
[safe/jmp/linux-2.6] / fs / gfs2 / locking / dlm / mount.c
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 version 2.
8  */
9
10 #include "lock_dlm.h"
11
12 const struct lm_lockops gdlm_ops;
13
14
15 static struct gdlm_ls *init_gdlm(lm_callback_t cb, struct gfs2_sbd *sdp,
16                                  int flags, char *table_name)
17 {
18         struct gdlm_ls *ls;
19         char buf[256], *p;
20
21         ls = kzalloc(sizeof(struct gdlm_ls), GFP_KERNEL);
22         if (!ls)
23                 return NULL;
24
25         ls->fscb = cb;
26         ls->sdp = sdp;
27         ls->fsflags = flags;
28         spin_lock_init(&ls->async_lock);
29         INIT_LIST_HEAD(&ls->delayed);
30         INIT_LIST_HEAD(&ls->submit);
31         INIT_LIST_HEAD(&ls->all_locks);
32         init_waitqueue_head(&ls->thread_wait);
33         init_waitqueue_head(&ls->wait_control);
34         ls->jid = -1;
35
36         strncpy(buf, table_name, 256);
37         buf[255] = '\0';
38
39         p = strchr(buf, ':');
40         if (!p) {
41                 log_info("invalid table_name \"%s\"", table_name);
42                 kfree(ls);
43                 return NULL;
44         }
45         *p = '\0';
46         p++;
47
48         strncpy(ls->clustername, buf, GDLM_NAME_LEN);
49         strncpy(ls->fsname, p, GDLM_NAME_LEN);
50
51         return ls;
52 }
53
54 static int make_args(struct gdlm_ls *ls, char *data_arg, int *nodir)
55 {
56         char data[256];
57         char *options, *x, *y;
58         int error = 0;
59
60         memset(data, 0, 256);
61         strncpy(data, data_arg, 255);
62
63         if (!strlen(data)) {
64                 log_error("no mount options, (u)mount helpers not installed");
65                 return -EINVAL;
66         }
67
68         for (options = data; (x = strsep(&options, ":")); ) {
69                 if (!*x)
70                         continue;
71
72                 y = strchr(x, '=');
73                 if (y)
74                         *y++ = 0;
75
76                 if (!strcmp(x, "jid")) {
77                         if (!y) {
78                                 log_error("need argument to jid");
79                                 error = -EINVAL;
80                                 break;
81                         }
82                         sscanf(y, "%u", &ls->jid);
83
84                 } else if (!strcmp(x, "first")) {
85                         if (!y) {
86                                 log_error("need argument to first");
87                                 error = -EINVAL;
88                                 break;
89                         }
90                         sscanf(y, "%u", &ls->first);
91
92                 } else if (!strcmp(x, "id")) {
93                         if (!y) {
94                                 log_error("need argument to id");
95                                 error = -EINVAL;
96                                 break;
97                         }
98                         sscanf(y, "%u", &ls->id);
99
100                 } else if (!strcmp(x, "nodir")) {
101                         if (!y) {
102                                 log_error("need argument to nodir");
103                                 error = -EINVAL;
104                                 break;
105                         }
106                         sscanf(y, "%u", nodir);
107
108                 } else {
109                         log_error("unkonwn option: %s", x);
110                         error = -EINVAL;
111                         break;
112                 }
113         }
114
115         return error;
116 }
117
118 static int gdlm_mount(char *table_name, char *host_data,
119                         lm_callback_t cb, void *cb_data,
120                         unsigned int min_lvb_size, int flags,
121                         struct lm_lockstruct *lockstruct,
122                         struct kobject *fskobj)
123 {
124         struct gdlm_ls *ls;
125         int error = -ENOMEM, nodir = 0;
126
127         if (min_lvb_size > GDLM_LVB_SIZE)
128                 goto out;
129
130         ls = init_gdlm(cb, cb_data, flags, table_name);
131         if (!ls)
132                 goto out;
133
134         error = make_args(ls, host_data, &nodir);
135         if (error)
136                 goto out;
137
138         error = gdlm_init_threads(ls);
139         if (error)
140                 goto out_free;
141
142         error = gdlm_kobject_setup(ls, fskobj);
143         if (error)
144                 goto out_thread;
145
146         error = dlm_new_lockspace(ls->fsname, strlen(ls->fsname),
147                                   &ls->dlm_lockspace,
148                                   DLM_LSFL_FS | (nodir ? DLM_LSFL_NODIR : 0),
149                                   GDLM_LVB_SIZE);
150         if (error) {
151                 log_error("dlm_new_lockspace error %d", error);
152                 goto out_kobj;
153         }
154
155         lockstruct->ls_jid = ls->jid;
156         lockstruct->ls_first = ls->first;
157         lockstruct->ls_lockspace = ls;
158         lockstruct->ls_ops = &gdlm_ops;
159         lockstruct->ls_flags = 0;
160         lockstruct->ls_lvb_size = GDLM_LVB_SIZE;
161         return 0;
162
163 out_kobj:
164         gdlm_kobject_release(ls);
165 out_thread:
166         gdlm_release_threads(ls);
167 out_free:
168         kfree(ls);
169 out:
170         return error;
171 }
172
173 static void gdlm_unmount(void *lockspace)
174 {
175         struct gdlm_ls *ls = lockspace;
176         int rv;
177
178         log_debug("unmount flags %lx", ls->flags);
179
180         /* FIXME: serialize unmount and withdraw in case they
181            happen at once.  Also, if unmount follows withdraw,
182            wait for withdraw to finish. */
183
184         if (test_bit(DFL_WITHDRAW, &ls->flags))
185                 goto out;
186
187         gdlm_kobject_release(ls);
188         dlm_release_lockspace(ls->dlm_lockspace, 2);
189         gdlm_release_threads(ls);
190         rv = gdlm_release_all_locks(ls);
191         if (rv)
192                 log_info("gdlm_unmount: %d stray locks freed", rv);
193 out:
194         kfree(ls);
195 }
196
197 static void gdlm_recovery_done(void *lockspace, unsigned int jid,
198                                unsigned int message)
199 {
200         struct gdlm_ls *ls = lockspace;
201         ls->recover_jid_done = jid;
202         ls->recover_jid_status = message;
203         kobject_uevent(&ls->kobj, KOBJ_CHANGE);
204 }
205
206 static void gdlm_others_may_mount(void *lockspace)
207 {
208         struct gdlm_ls *ls = lockspace;
209         ls->first_done = 1;
210         kobject_uevent(&ls->kobj, KOBJ_CHANGE);
211 }
212
213 /* Userspace gets the offline uevent, blocks new gfs locks on
214    other mounters, and lets us know (sets WITHDRAW flag).  Then,
215    userspace leaves the mount group while we leave the lockspace. */
216
217 static void gdlm_withdraw(void *lockspace)
218 {
219         struct gdlm_ls *ls = lockspace;
220
221         kobject_uevent(&ls->kobj, KOBJ_OFFLINE);
222
223         wait_event_interruptible(ls->wait_control,
224                                  test_bit(DFL_WITHDRAW, &ls->flags));
225
226         dlm_release_lockspace(ls->dlm_lockspace, 2);
227         gdlm_release_threads(ls);
228         gdlm_release_all_locks(ls);
229         gdlm_kobject_release(ls);
230 }
231
232 static int gdlm_plock(void *lockspace, struct lm_lockname *name,
233                struct file *file, int cmd, struct file_lock *fl)
234 {
235         struct gdlm_ls *ls = lockspace;
236         return dlm_posix_lock(ls->dlm_lockspace, name->ln_number, file, cmd, fl);
237 }
238
239 static int gdlm_punlock(void *lockspace, struct lm_lockname *name,
240                  struct file *file, struct file_lock *fl)
241 {
242         struct gdlm_ls *ls = lockspace;
243         return dlm_posix_unlock(ls->dlm_lockspace, name->ln_number, file, fl);
244 }
245
246 static int gdlm_plock_get(void *lockspace, struct lm_lockname *name,
247                    struct file *file, struct file_lock *fl)
248 {
249         struct gdlm_ls *ls = lockspace;
250         return dlm_posix_get(ls->dlm_lockspace, name->ln_number, file, fl);
251 }
252
253 const struct lm_lockops gdlm_ops = {
254         .lm_proto_name = "lock_dlm",
255         .lm_mount = gdlm_mount,
256         .lm_others_may_mount = gdlm_others_may_mount,
257         .lm_unmount = gdlm_unmount,
258         .lm_withdraw = gdlm_withdraw,
259         .lm_get_lock = gdlm_get_lock,
260         .lm_put_lock = gdlm_put_lock,
261         .lm_lock = gdlm_lock,
262         .lm_unlock = gdlm_unlock,
263         .lm_plock = gdlm_plock,
264         .lm_punlock = gdlm_punlock,
265         .lm_plock_get = gdlm_plock_get,
266         .lm_cancel = gdlm_cancel,
267         .lm_hold_lvb = gdlm_hold_lvb,
268         .lm_unhold_lvb = gdlm_unhold_lvb,
269         .lm_recovery_done = gdlm_recovery_done,
270         .lm_owner = THIS_MODULE,
271 };
272