diff options
author | Arnd Bergmann <arnd@arndb.de> | 2010-10-27 09:46:08 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2010-10-27 15:41:50 -0400 |
commit | c5b1f0d92c36851aca09ac6c7c0c4f9690ac14f3 (patch) | |
tree | c8aa4ad65aea3b97292135a4c23d512e6071dc8d /fs/locks.c | |
parent | a282a1fa6b23bd21ba0b86e53ed2a316b001836f (diff) |
locks/nfsd: allocate file lock outside of spinlock
As suggested by Christoph Hellwig, this moves allocation
of new file locks out of generic_setlease into the
callers, nfs4_open_delegation and fcntl_setlease in order
to allow GFP_KERNEL allocations when lock_flocks has
become a spinlock.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/locks.c')
-rw-r--r-- | fs/locks.c | 36 |
1 files changed, 12 insertions, 24 deletions
diff --git a/fs/locks.c b/fs/locks.c index 8b2b6ad56a09..0391d2ff5a4e 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -162,10 +162,11 @@ EXPORT_SYMBOL_GPL(unlock_flocks); | |||
162 | static struct kmem_cache *filelock_cache __read_mostly; | 162 | static struct kmem_cache *filelock_cache __read_mostly; |
163 | 163 | ||
164 | /* Allocate an empty lock structure. */ | 164 | /* Allocate an empty lock structure. */ |
165 | static struct file_lock *locks_alloc_lock(void) | 165 | struct file_lock *locks_alloc_lock(void) |
166 | { | 166 | { |
167 | return kmem_cache_alloc(filelock_cache, GFP_KERNEL); | 167 | return kmem_cache_alloc(filelock_cache, GFP_KERNEL); |
168 | } | 168 | } |
169 | EXPORT_SYMBOL_GPL(locks_alloc_lock); | ||
169 | 170 | ||
170 | void locks_release_private(struct file_lock *fl) | 171 | void locks_release_private(struct file_lock *fl) |
171 | { | 172 | { |
@@ -1365,7 +1366,6 @@ int fcntl_getlease(struct file *filp) | |||
1365 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | 1366 | int generic_setlease(struct file *filp, long arg, struct file_lock **flp) |
1366 | { | 1367 | { |
1367 | struct file_lock *fl, **before, **my_before = NULL, *lease; | 1368 | struct file_lock *fl, **before, **my_before = NULL, *lease; |
1368 | struct file_lock *new_fl = NULL; | ||
1369 | struct dentry *dentry = filp->f_path.dentry; | 1369 | struct dentry *dentry = filp->f_path.dentry; |
1370 | struct inode *inode = dentry->d_inode; | 1370 | struct inode *inode = dentry->d_inode; |
1371 | int error, rdlease_count = 0, wrlease_count = 0; | 1371 | int error, rdlease_count = 0, wrlease_count = 0; |
@@ -1385,11 +1385,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1385 | lease = *flp; | 1385 | lease = *flp; |
1386 | 1386 | ||
1387 | if (arg != F_UNLCK) { | 1387 | if (arg != F_UNLCK) { |
1388 | error = -ENOMEM; | ||
1389 | new_fl = locks_alloc_lock(); | ||
1390 | if (new_fl == NULL) | ||
1391 | goto out; | ||
1392 | |||
1393 | error = -EAGAIN; | 1388 | error = -EAGAIN; |
1394 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) | 1389 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) |
1395 | goto out; | 1390 | goto out; |
@@ -1434,7 +1429,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1434 | goto out; | 1429 | goto out; |
1435 | } | 1430 | } |
1436 | 1431 | ||
1437 | error = 0; | ||
1438 | if (arg == F_UNLCK) | 1432 | if (arg == F_UNLCK) |
1439 | goto out; | 1433 | goto out; |
1440 | 1434 | ||
@@ -1442,15 +1436,11 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
1442 | if (!leases_enable) | 1436 | if (!leases_enable) |
1443 | goto out; | 1437 | goto out; |
1444 | 1438 | ||
1445 | locks_copy_lock(new_fl, lease); | 1439 | locks_insert_lock(before, lease); |
1446 | locks_insert_lock(before, new_fl); | ||
1447 | |||
1448 | *flp = new_fl; | ||
1449 | return 0; | 1440 | return 0; |
1450 | 1441 | ||
1451 | out: | 1442 | out: |
1452 | if (new_fl != NULL) | 1443 | locks_free_lock(lease); |
1453 | locks_free_lock(new_fl); | ||
1454 | return error; | 1444 | return error; |
1455 | } | 1445 | } |
1456 | EXPORT_SYMBOL(generic_setlease); | 1446 | EXPORT_SYMBOL(generic_setlease); |
@@ -1514,26 +1504,24 @@ EXPORT_SYMBOL_GPL(vfs_setlease); | |||
1514 | */ | 1504 | */ |
1515 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | 1505 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) |
1516 | { | 1506 | { |
1517 | struct file_lock fl, *flp = &fl; | 1507 | struct file_lock *fl; |
1518 | struct inode *inode = filp->f_path.dentry->d_inode; | 1508 | struct inode *inode = filp->f_path.dentry->d_inode; |
1519 | int error; | 1509 | int error; |
1520 | 1510 | ||
1521 | locks_init_lock(&fl); | 1511 | fl = lease_alloc(filp, arg); |
1522 | error = lease_init(filp, arg, &fl); | 1512 | if (IS_ERR(fl)) |
1523 | if (error) | 1513 | return PTR_ERR(fl); |
1524 | return error; | ||
1525 | 1514 | ||
1526 | lock_flocks(); | 1515 | lock_flocks(); |
1527 | 1516 | error = __vfs_setlease(filp, arg, &fl); | |
1528 | error = __vfs_setlease(filp, arg, &flp); | ||
1529 | if (error || arg == F_UNLCK) | 1517 | if (error || arg == F_UNLCK) |
1530 | goto out_unlock; | 1518 | goto out_unlock; |
1531 | 1519 | ||
1532 | error = fasync_helper(fd, filp, 1, &flp->fl_fasync); | 1520 | error = fasync_helper(fd, filp, 1, &fl->fl_fasync); |
1533 | if (error < 0) { | 1521 | if (error < 0) { |
1534 | /* remove lease just inserted by setlease */ | 1522 | /* remove lease just inserted by setlease */ |
1535 | flp->fl_type = F_UNLCK | F_INPROGRESS; | 1523 | fl->fl_type = F_UNLCK | F_INPROGRESS; |
1536 | flp->fl_break_time = jiffies - 10; | 1524 | fl->fl_break_time = jiffies - 10; |
1537 | time_out_leases(inode); | 1525 | time_out_leases(inode); |
1538 | goto out_unlock; | 1526 | goto out_unlock; |
1539 | } | 1527 | } |