2 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3 * Copyright (C) 2004-2005 Red Hat, Inc. All rights reserved.
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.
12 const struct lm_lockops gdlm_ops
;
15 static struct gdlm_ls
*init_gdlm(lm_callback_t cb
, struct gfs2_sbd
*sdp
,
16 int flags
, char *table_name
)
21 ls
= kzalloc(sizeof(struct gdlm_ls
), GFP_KERNEL
);
28 spin_lock_init(&ls
->async_lock
);
29 INIT_LIST_HEAD(&ls
->delayed
);
30 INIT_LIST_HEAD(&ls
->submit
);
31 init_waitqueue_head(&ls
->thread_wait
);
32 init_waitqueue_head(&ls
->wait_control
);
35 strncpy(buf
, table_name
, 256);
40 log_info("invalid table_name \"%s\"", table_name
);
47 strncpy(ls
->clustername
, buf
, GDLM_NAME_LEN
);
48 strncpy(ls
->fsname
, p
, GDLM_NAME_LEN
);
53 static int make_args(struct gdlm_ls
*ls
, char *data_arg
, int *nodir
)
56 char *options
, *x
, *y
;
60 strncpy(data
, data_arg
, 255);
63 log_error("no mount options, (u)mount helpers not installed");
67 for (options
= data
; (x
= strsep(&options
, ":")); ) {
75 if (!strcmp(x
, "jid")) {
77 log_error("need argument to jid");
81 sscanf(y
, "%u", &ls
->jid
);
83 } else if (!strcmp(x
, "first")) {
85 log_error("need argument to first");
89 sscanf(y
, "%u", &ls
->first
);
91 } else if (!strcmp(x
, "id")) {
93 log_error("need argument to id");
97 sscanf(y
, "%u", &ls
->id
);
99 } else if (!strcmp(x
, "nodir")) {
101 log_error("need argument to nodir");
105 sscanf(y
, "%u", nodir
);
108 log_error("unkonwn option: %s", x
);
117 static int gdlm_mount(char *table_name
, char *host_data
,
118 lm_callback_t cb
, void *cb_data
,
119 unsigned int min_lvb_size
, int flags
,
120 struct lm_lockstruct
*lockstruct
,
121 struct kobject
*fskobj
)
124 int error
= -ENOMEM
, nodir
= 0;
126 if (min_lvb_size
> GDLM_LVB_SIZE
)
129 ls
= init_gdlm(cb
, cb_data
, flags
, table_name
);
133 error
= make_args(ls
, host_data
, &nodir
);
137 error
= gdlm_init_threads(ls
);
141 error
= gdlm_kobject_setup(ls
, fskobj
);
145 error
= dlm_new_lockspace(ls
->fsname
, strlen(ls
->fsname
),
147 DLM_LSFL_FS
| DLM_LSFL_NEWEXCL
|
148 (nodir
? DLM_LSFL_NODIR
: 0),
151 log_error("dlm_new_lockspace error %d", error
);
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
;
164 gdlm_kobject_release(ls
);
166 gdlm_release_threads(ls
);
173 static void gdlm_unmount(void *lockspace
)
175 struct gdlm_ls
*ls
= lockspace
;
177 log_debug("unmount flags %lx", ls
->flags
);
179 /* FIXME: serialize unmount and withdraw in case they
180 happen at once. Also, if unmount follows withdraw,
181 wait for withdraw to finish. */
183 if (test_bit(DFL_WITHDRAW
, &ls
->flags
))
186 gdlm_kobject_release(ls
);
187 dlm_release_lockspace(ls
->dlm_lockspace
, 2);
188 gdlm_release_threads(ls
);
189 BUG_ON(ls
->all_locks_count
);
194 static void gdlm_recovery_done(void *lockspace
, unsigned int jid
,
195 unsigned int message
)
199 char *envp
[] = { env_jid
, env_status
, NULL
};
200 struct gdlm_ls
*ls
= lockspace
;
201 ls
->recover_jid_done
= jid
;
202 ls
->recover_jid_status
= message
;
203 sprintf(env_jid
, "JID=%d", jid
);
204 sprintf(env_status
, "RECOVERY=%s",
205 message
== LM_RD_SUCCESS
? "Done" : "Failed");
206 kobject_uevent_env(&ls
->kobj
, KOBJ_CHANGE
, envp
);
209 static void gdlm_others_may_mount(void *lockspace
)
211 char *message
= "FIRSTMOUNT=Done";
212 char *envp
[] = { message
, NULL
};
213 struct gdlm_ls
*ls
= lockspace
;
215 kobject_uevent_env(&ls
->kobj
, KOBJ_CHANGE
, envp
);
218 /* Userspace gets the offline uevent, blocks new gfs locks on
219 other mounters, and lets us know (sets WITHDRAW flag). Then,
220 userspace leaves the mount group while we leave the lockspace. */
222 static void gdlm_withdraw(void *lockspace
)
224 struct gdlm_ls
*ls
= lockspace
;
226 kobject_uevent(&ls
->kobj
, KOBJ_OFFLINE
);
228 wait_event_interruptible(ls
->wait_control
,
229 test_bit(DFL_WITHDRAW
, &ls
->flags
));
231 dlm_release_lockspace(ls
->dlm_lockspace
, 2);
232 gdlm_release_threads(ls
);
233 gdlm_kobject_release(ls
);
236 static int gdlm_plock(void *lockspace
, struct lm_lockname
*name
,
237 struct file
*file
, int cmd
, struct file_lock
*fl
)
239 struct gdlm_ls
*ls
= lockspace
;
240 return dlm_posix_lock(ls
->dlm_lockspace
, name
->ln_number
, file
, cmd
, fl
);
243 static int gdlm_punlock(void *lockspace
, struct lm_lockname
*name
,
244 struct file
*file
, struct file_lock
*fl
)
246 struct gdlm_ls
*ls
= lockspace
;
247 return dlm_posix_unlock(ls
->dlm_lockspace
, name
->ln_number
, file
, fl
);
250 static int gdlm_plock_get(void *lockspace
, struct lm_lockname
*name
,
251 struct file
*file
, struct file_lock
*fl
)
253 struct gdlm_ls
*ls
= lockspace
;
254 return dlm_posix_get(ls
->dlm_lockspace
, name
->ln_number
, file
, fl
);
257 const struct lm_lockops gdlm_ops
= {
258 .lm_proto_name
= "lock_dlm",
259 .lm_mount
= gdlm_mount
,
260 .lm_others_may_mount
= gdlm_others_may_mount
,
261 .lm_unmount
= gdlm_unmount
,
262 .lm_withdraw
= gdlm_withdraw
,
263 .lm_get_lock
= gdlm_get_lock
,
264 .lm_put_lock
= gdlm_put_lock
,
265 .lm_lock
= gdlm_lock
,
266 .lm_unlock
= gdlm_unlock
,
267 .lm_plock
= gdlm_plock
,
268 .lm_punlock
= gdlm_punlock
,
269 .lm_plock_get
= gdlm_plock_get
,
270 .lm_cancel
= gdlm_cancel
,
271 .lm_hold_lvb
= gdlm_hold_lvb
,
272 .lm_unhold_lvb
= gdlm_unhold_lvb
,
273 .lm_recovery_done
= gdlm_recovery_done
,
274 .lm_owner
= THIS_MODULE
,