diff options
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 30 |
1 files changed, 19 insertions, 11 deletions
diff --git a/fs/locks.c b/fs/locks.c index dda83d6cd48b..6f99c0a6f836 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -446,15 +446,14 @@ static struct lock_manager_operations lease_manager_ops = { | |||
446 | */ | 446 | */ |
447 | static int lease_init(struct file *filp, int type, struct file_lock *fl) | 447 | static int lease_init(struct file *filp, int type, struct file_lock *fl) |
448 | { | 448 | { |
449 | if (assign_type(fl, type) != 0) | ||
450 | return -EINVAL; | ||
451 | |||
449 | fl->fl_owner = current->files; | 452 | fl->fl_owner = current->files; |
450 | fl->fl_pid = current->tgid; | 453 | fl->fl_pid = current->tgid; |
451 | 454 | ||
452 | fl->fl_file = filp; | 455 | fl->fl_file = filp; |
453 | fl->fl_flags = FL_LEASE; | 456 | fl->fl_flags = FL_LEASE; |
454 | if (assign_type(fl, type) != 0) { | ||
455 | locks_free_lock(fl); | ||
456 | return -EINVAL; | ||
457 | } | ||
458 | fl->fl_start = 0; | 457 | fl->fl_start = 0; |
459 | fl->fl_end = OFFSET_MAX; | 458 | fl->fl_end = OFFSET_MAX; |
460 | fl->fl_ops = NULL; | 459 | fl->fl_ops = NULL; |
@@ -466,16 +465,19 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl) | |||
466 | static int lease_alloc(struct file *filp, int type, struct file_lock **flp) | 465 | static int lease_alloc(struct file *filp, int type, struct file_lock **flp) |
467 | { | 466 | { |
468 | struct file_lock *fl = locks_alloc_lock(); | 467 | struct file_lock *fl = locks_alloc_lock(); |
469 | int error; | 468 | int error = -ENOMEM; |
470 | 469 | ||
471 | if (fl == NULL) | 470 | if (fl == NULL) |
472 | return -ENOMEM; | 471 | goto out; |
473 | 472 | ||
474 | error = lease_init(filp, type, fl); | 473 | error = lease_init(filp, type, fl); |
475 | if (error) | 474 | if (error) { |
476 | return error; | 475 | locks_free_lock(fl); |
476 | fl = NULL; | ||
477 | } | ||
478 | out: | ||
477 | *flp = fl; | 479 | *flp = fl; |
478 | return 0; | 480 | return error; |
479 | } | 481 | } |
480 | 482 | ||
481 | /* Check if two locks overlap each other. | 483 | /* Check if two locks overlap each other. |
@@ -1372,6 +1374,7 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1372 | goto out; | 1374 | goto out; |
1373 | 1375 | ||
1374 | if (my_before != NULL) { | 1376 | if (my_before != NULL) { |
1377 | *flp = *my_before; | ||
1375 | error = lease->fl_lmops->fl_change(my_before, arg); | 1378 | error = lease->fl_lmops->fl_change(my_before, arg); |
1376 | goto out; | 1379 | goto out; |
1377 | } | 1380 | } |
@@ -2230,7 +2233,12 @@ void steal_locks(fl_owner_t from) | |||
2230 | 2233 | ||
2231 | lock_kernel(); | 2234 | lock_kernel(); |
2232 | j = 0; | 2235 | j = 0; |
2233 | rcu_read_lock(); | 2236 | |
2237 | /* | ||
2238 | * We are not taking a ref to the file structures, so | ||
2239 | * we need to acquire ->file_lock. | ||
2240 | */ | ||
2241 | spin_lock(&files->file_lock); | ||
2234 | fdt = files_fdtable(files); | 2242 | fdt = files_fdtable(files); |
2235 | for (;;) { | 2243 | for (;;) { |
2236 | unsigned long set; | 2244 | unsigned long set; |
@@ -2248,7 +2256,7 @@ void steal_locks(fl_owner_t from) | |||
2248 | set >>= 1; | 2256 | set >>= 1; |
2249 | } | 2257 | } |
2250 | } | 2258 | } |
2251 | rcu_read_unlock(); | 2259 | spin_unlock(&files->file_lock); |
2252 | unlock_kernel(); | 2260 | unlock_kernel(); |
2253 | } | 2261 | } |
2254 | EXPORT_SYMBOL(steal_locks); | 2262 | EXPORT_SYMBOL(steal_locks); |