aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c91
1 files changed, 52 insertions, 39 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 50ec15927aab..8729347bcd1a 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -122,7 +122,6 @@
122#include <linux/module.h> 122#include <linux/module.h>
123#include <linux/security.h> 123#include <linux/security.h>
124#include <linux/slab.h> 124#include <linux/slab.h>
125#include <linux/smp_lock.h>
126#include <linux/syscalls.h> 125#include <linux/syscalls.h>
127#include <linux/time.h> 126#include <linux/time.h>
128#include <linux/rcupdate.h> 127#include <linux/rcupdate.h>
@@ -186,7 +185,7 @@ void locks_release_private(struct file_lock *fl)
186EXPORT_SYMBOL_GPL(locks_release_private); 185EXPORT_SYMBOL_GPL(locks_release_private);
187 186
188/* Free a lock which is not in use. */ 187/* Free a lock which is not in use. */
189static void locks_free_lock(struct file_lock *fl) 188void locks_free_lock(struct file_lock *fl)
190{ 189{
191 BUG_ON(waitqueue_active(&fl->fl_wait)); 190 BUG_ON(waitqueue_active(&fl->fl_wait));
192 BUG_ON(!list_empty(&fl->fl_block)); 191 BUG_ON(!list_empty(&fl->fl_block));
@@ -195,6 +194,7 @@ static void locks_free_lock(struct file_lock *fl)
195 locks_release_private(fl); 194 locks_release_private(fl);
196 kmem_cache_free(filelock_cache, fl); 195 kmem_cache_free(filelock_cache, fl);
197} 196}
197EXPORT_SYMBOL(locks_free_lock);
198 198
199void locks_init_lock(struct file_lock *fl) 199void locks_init_lock(struct file_lock *fl)
200{ 200{
@@ -234,11 +234,8 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl)
234 fl->fl_ops->fl_copy_lock(new, fl); 234 fl->fl_ops->fl_copy_lock(new, fl);
235 new->fl_ops = fl->fl_ops; 235 new->fl_ops = fl->fl_ops;
236 } 236 }
237 if (fl->fl_lmops) { 237 if (fl->fl_lmops)
238 if (fl->fl_lmops->fl_copy_lock)
239 fl->fl_lmops->fl_copy_lock(new, fl);
240 new->fl_lmops = fl->fl_lmops; 238 new->fl_lmops = fl->fl_lmops;
241 }
242} 239}
243 240
244/* 241/*
@@ -1371,20 +1368,22 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1371 struct inode *inode = dentry->d_inode; 1368 struct inode *inode = dentry->d_inode;
1372 int error, rdlease_count = 0, wrlease_count = 0; 1369 int error, rdlease_count = 0, wrlease_count = 0;
1373 1370
1371 lease = *flp;
1372
1373 error = -EACCES;
1374 if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE)) 1374 if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
1375 return -EACCES; 1375 goto out;
1376 error = -EINVAL;
1376 if (!S_ISREG(inode->i_mode)) 1377 if (!S_ISREG(inode->i_mode))
1377 return -EINVAL; 1378 goto out;
1378 error = security_file_lock(filp, arg); 1379 error = security_file_lock(filp, arg);
1379 if (error) 1380 if (error)
1380 return error; 1381 goto out;
1381 1382
1382 time_out_leases(inode); 1383 time_out_leases(inode);
1383 1384
1384 BUG_ON(!(*flp)->fl_lmops->fl_break); 1385 BUG_ON(!(*flp)->fl_lmops->fl_break);
1385 1386
1386 lease = *flp;
1387
1388 if (arg != F_UNLCK) { 1387 if (arg != F_UNLCK) {
1389 error = -EAGAIN; 1388 error = -EAGAIN;
1390 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) 1389 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
@@ -1425,8 +1424,9 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1425 goto out; 1424 goto out;
1426 1425
1427 if (my_before != NULL) { 1426 if (my_before != NULL) {
1428 *flp = *my_before;
1429 error = lease->fl_lmops->fl_change(my_before, arg); 1427 error = lease->fl_lmops->fl_change(my_before, arg);
1428 if (!error)
1429 *flp = *my_before;
1430 goto out; 1430 goto out;
1431 } 1431 }
1432 1432
@@ -1441,7 +1441,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1441 return 0; 1441 return 0;
1442 1442
1443out: 1443out:
1444 locks_free_lock(lease);
1445 return error; 1444 return error;
1446} 1445}
1447EXPORT_SYMBOL(generic_setlease); 1446EXPORT_SYMBOL(generic_setlease);
@@ -1493,21 +1492,19 @@ int vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
1493} 1492}
1494EXPORT_SYMBOL_GPL(vfs_setlease); 1493EXPORT_SYMBOL_GPL(vfs_setlease);
1495 1494
1496/** 1495static int do_fcntl_delete_lease(struct file *filp)
1497 * fcntl_setlease - sets a lease on an open file
1498 * @fd: open file descriptor
1499 * @filp: file pointer
1500 * @arg: type of lease to obtain
1501 *
1502 * Call this fcntl to establish a lease on the file.
1503 * Note that you also need to call %F_SETSIG to
1504 * receive a signal when the lease is broken.
1505 */
1506int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1507{ 1496{
1508 struct file_lock *fl; 1497 struct file_lock fl, *flp = &fl;
1498
1499 lease_init(filp, F_UNLCK, flp);
1500
1501 return vfs_setlease(filp, F_UNLCK, &flp);
1502}
1503
1504static int do_fcntl_add_lease(unsigned int fd, struct file *filp, long arg)
1505{
1506 struct file_lock *fl, *ret;
1509 struct fasync_struct *new; 1507 struct fasync_struct *new;
1510 struct inode *inode = filp->f_path.dentry->d_inode;
1511 int error; 1508 int error;
1512 1509
1513 fl = lease_alloc(filp, arg); 1510 fl = lease_alloc(filp, arg);
@@ -1519,10 +1516,16 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1519 locks_free_lock(fl); 1516 locks_free_lock(fl);
1520 return -ENOMEM; 1517 return -ENOMEM;
1521 } 1518 }
1519 ret = fl;
1522 lock_flocks(); 1520 lock_flocks();
1523 error = __vfs_setlease(filp, arg, &fl); 1521 error = __vfs_setlease(filp, arg, &ret);
1524 if (error || arg == F_UNLCK) 1522 if (error) {
1525 goto out_unlock; 1523 unlock_flocks();
1524 locks_free_lock(fl);
1525 goto out_free_fasync;
1526 }
1527 if (ret != fl)
1528 locks_free_lock(fl);
1526 1529
1527 /* 1530 /*
1528 * fasync_insert_entry() returns the old entry if any. 1531 * fasync_insert_entry() returns the old entry if any.
@@ -1530,26 +1533,36 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1530 * inserted it into the fasync list. Clear new so that 1533 * inserted it into the fasync list. Clear new so that
1531 * we don't release it here. 1534 * we don't release it here.
1532 */ 1535 */
1533 if (!fasync_insert_entry(fd, filp, &fl->fl_fasync, new)) 1536 if (!fasync_insert_entry(fd, filp, &ret->fl_fasync, new))
1534 new = NULL; 1537 new = NULL;
1535 1538
1536 if (error < 0) {
1537 /* remove lease just inserted by setlease */
1538 fl->fl_type = F_UNLCK | F_INPROGRESS;
1539 fl->fl_break_time = jiffies - 10;
1540 time_out_leases(inode);
1541 goto out_unlock;
1542 }
1543
1544 error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0); 1539 error = __f_setown(filp, task_pid(current), PIDTYPE_PID, 0);
1545out_unlock:
1546 unlock_flocks(); 1540 unlock_flocks();
1541
1542out_free_fasync:
1547 if (new) 1543 if (new)
1548 fasync_free(new); 1544 fasync_free(new);
1549 return error; 1545 return error;
1550} 1546}
1551 1547
1552/** 1548/**
1549 * fcntl_setlease - sets a lease on an open file
1550 * @fd: open file descriptor
1551 * @filp: file pointer
1552 * @arg: type of lease to obtain
1553 *
1554 * Call this fcntl to establish a lease on the file.
1555 * Note that you also need to call %F_SETSIG to
1556 * receive a signal when the lease is broken.
1557 */
1558int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1559{
1560 if (arg == F_UNLCK)
1561 return do_fcntl_delete_lease(filp);
1562 return do_fcntl_add_lease(fd, filp, arg);
1563}
1564
1565/**
1553 * flock_lock_file_wait - Apply a FLOCK-style lock to a file 1566 * flock_lock_file_wait - Apply a FLOCK-style lock to a file
1554 * @filp: The file to apply the lock to 1567 * @filp: The file to apply the lock to
1555 * @fl: The lock to be applied 1568 * @fl: The lock to be applied