diff options
Diffstat (limited to 'fs/dlm/user.c')
-rw-r--r-- | fs/dlm/user.c | 58 |
1 files changed, 36 insertions, 22 deletions
diff --git a/fs/dlm/user.c b/fs/dlm/user.c index 3870150b83a4..27a75ce571cf 100644 --- a/fs/dlm/user.c +++ b/fs/dlm/user.c | |||
@@ -286,11 +286,34 @@ static int device_user_unlock(struct dlm_user_proc *proc, | |||
286 | return error; | 286 | return error; |
287 | } | 287 | } |
288 | 288 | ||
289 | static int create_misc_device(struct dlm_ls *ls, char *name) | ||
290 | { | ||
291 | int error, len; | ||
292 | |||
293 | error = -ENOMEM; | ||
294 | len = strlen(name) + strlen(name_prefix) + 2; | ||
295 | ls->ls_device.name = kzalloc(len, GFP_KERNEL); | ||
296 | if (!ls->ls_device.name) | ||
297 | goto fail; | ||
298 | |||
299 | snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix, | ||
300 | name); | ||
301 | ls->ls_device.fops = &device_fops; | ||
302 | ls->ls_device.minor = MISC_DYNAMIC_MINOR; | ||
303 | |||
304 | error = misc_register(&ls->ls_device); | ||
305 | if (error) { | ||
306 | kfree(ls->ls_device.name); | ||
307 | } | ||
308 | fail: | ||
309 | return error; | ||
310 | } | ||
311 | |||
289 | static int device_create_lockspace(struct dlm_lspace_params *params) | 312 | static int device_create_lockspace(struct dlm_lspace_params *params) |
290 | { | 313 | { |
291 | dlm_lockspace_t *lockspace; | 314 | dlm_lockspace_t *lockspace; |
292 | struct dlm_ls *ls; | 315 | struct dlm_ls *ls; |
293 | int error, len; | 316 | int error; |
294 | 317 | ||
295 | if (!capable(CAP_SYS_ADMIN)) | 318 | if (!capable(CAP_SYS_ADMIN)) |
296 | return -EPERM; | 319 | return -EPERM; |
@@ -304,29 +327,14 @@ static int device_create_lockspace(struct dlm_lspace_params *params) | |||
304 | if (!ls) | 327 | if (!ls) |
305 | return -ENOENT; | 328 | return -ENOENT; |
306 | 329 | ||
307 | error = -ENOMEM; | 330 | error = create_misc_device(ls, params->name); |
308 | len = strlen(params->name) + strlen(name_prefix) + 2; | ||
309 | ls->ls_device.name = kzalloc(len, GFP_KERNEL); | ||
310 | if (!ls->ls_device.name) | ||
311 | goto fail; | ||
312 | snprintf((char *)ls->ls_device.name, len, "%s_%s", name_prefix, | ||
313 | params->name); | ||
314 | ls->ls_device.fops = &device_fops; | ||
315 | ls->ls_device.minor = MISC_DYNAMIC_MINOR; | ||
316 | |||
317 | error = misc_register(&ls->ls_device); | ||
318 | if (error) { | ||
319 | kfree(ls->ls_device.name); | ||
320 | goto fail; | ||
321 | } | ||
322 | |||
323 | error = ls->ls_device.minor; | ||
324 | dlm_put_lockspace(ls); | 331 | dlm_put_lockspace(ls); |
325 | return error; | ||
326 | 332 | ||
327 | fail: | 333 | if (error) |
328 | dlm_put_lockspace(ls); | 334 | dlm_release_lockspace(lockspace, 0); |
329 | dlm_release_lockspace(lockspace, 0); | 335 | else |
336 | error = ls->ls_device.minor; | ||
337 | |||
330 | return error; | 338 | return error; |
331 | } | 339 | } |
332 | 340 | ||
@@ -343,6 +351,10 @@ static int device_remove_lockspace(struct dlm_lspace_params *params) | |||
343 | if (!ls) | 351 | if (!ls) |
344 | return -ENOENT; | 352 | return -ENOENT; |
345 | 353 | ||
354 | /* Deregister the misc device first, so we don't have | ||
355 | * a device that's not attached to a lockspace. If | ||
356 | * dlm_release_lockspace fails then we can recreate it | ||
357 | */ | ||
346 | error = misc_deregister(&ls->ls_device); | 358 | error = misc_deregister(&ls->ls_device); |
347 | if (error) { | 359 | if (error) { |
348 | dlm_put_lockspace(ls); | 360 | dlm_put_lockspace(ls); |
@@ -361,6 +373,8 @@ static int device_remove_lockspace(struct dlm_lspace_params *params) | |||
361 | 373 | ||
362 | dlm_put_lockspace(ls); | 374 | dlm_put_lockspace(ls); |
363 | error = dlm_release_lockspace(lockspace, force); | 375 | error = dlm_release_lockspace(lockspace, force); |
376 | if (error) | ||
377 | create_misc_device(ls, ls->ls_name); | ||
364 | out: | 378 | out: |
365 | return error; | 379 | return error; |
366 | } | 380 | } |