aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c114
1 files changed, 58 insertions, 56 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 431a8b871fce..310510637247 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -458,22 +458,20 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
458} 458}
459 459
460/* Allocate a file_lock initialised to this type of lease */ 460/* Allocate a file_lock initialised to this type of lease */
461static int lease_alloc(struct file *filp, int type, struct file_lock **flp) 461static struct file_lock *lease_alloc(struct file *filp, int type)
462{ 462{
463 struct file_lock *fl = locks_alloc_lock(); 463 struct file_lock *fl = locks_alloc_lock();
464 int error = -ENOMEM; 464 int error = -ENOMEM;
465 465
466 if (fl == NULL) 466 if (fl == NULL)
467 goto out; 467 return ERR_PTR(error);
468 468
469 error = lease_init(filp, type, fl); 469 error = lease_init(filp, type, fl);
470 if (error) { 470 if (error) {
471 locks_free_lock(fl); 471 locks_free_lock(fl);
472 fl = NULL; 472 return ERR_PTR(error);
473 } 473 }
474out: 474 return fl;
475 *flp = fl;
476 return error;
477} 475}
478 476
479/* Check if two locks overlap each other. 477/* Check if two locks overlap each other.
@@ -661,7 +659,7 @@ static int locks_block_on_timeout(struct file_lock *blocker, struct file_lock *w
661 return result; 659 return result;
662} 660}
663 661
664int 662void
665posix_test_lock(struct file *filp, struct file_lock *fl) 663posix_test_lock(struct file *filp, struct file_lock *fl)
666{ 664{
667 struct file_lock *cfl; 665 struct file_lock *cfl;
@@ -673,14 +671,12 @@ posix_test_lock(struct file *filp, struct file_lock *fl)
673 if (posix_locks_conflict(cfl, fl)) 671 if (posix_locks_conflict(cfl, fl))
674 break; 672 break;
675 } 673 }
676 if (cfl) { 674 if (cfl)
677 __locks_copy_lock(fl, cfl); 675 __locks_copy_lock(fl, cfl);
678 unlock_kernel(); 676 else
679 return 1;
680 } else
681 fl->fl_type = F_UNLCK; 677 fl->fl_type = F_UNLCK;
682 unlock_kernel(); 678 unlock_kernel();
683 return 0; 679 return;
684} 680}
685 681
686EXPORT_SYMBOL(posix_test_lock); 682EXPORT_SYMBOL(posix_test_lock);
@@ -1169,9 +1165,9 @@ static void time_out_leases(struct inode *inode)
1169 * @inode: the inode of the file to return 1165 * @inode: the inode of the file to return
1170 * @mode: the open mode (read or write) 1166 * @mode: the open mode (read or write)
1171 * 1167 *
1172 * break_lease (inlined for speed) has checked there already 1168 * break_lease (inlined for speed) has checked there already is at least
1173 * is a lease on this file. Leases are broken on a call to open() 1169 * some kind of lock (maybe a lease) on this file. Leases are broken on
1174 * or truncate(). This function can sleep unless you 1170 * a call to open() or truncate(). This function can sleep unless you
1175 * specified %O_NONBLOCK to your open(). 1171 * specified %O_NONBLOCK to your open().
1176 */ 1172 */
1177int __break_lease(struct inode *inode, unsigned int mode) 1173int __break_lease(struct inode *inode, unsigned int mode)
@@ -1179,12 +1175,10 @@ int __break_lease(struct inode *inode, unsigned int mode)
1179 int error = 0, future; 1175 int error = 0, future;
1180 struct file_lock *new_fl, *flock; 1176 struct file_lock *new_fl, *flock;
1181 struct file_lock *fl; 1177 struct file_lock *fl;
1182 int alloc_err;
1183 unsigned long break_time; 1178 unsigned long break_time;
1184 int i_have_this_lease = 0; 1179 int i_have_this_lease = 0;
1185 1180
1186 alloc_err = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK, 1181 new_fl = lease_alloc(NULL, mode & FMODE_WRITE ? F_WRLCK : F_RDLCK);
1187 &new_fl);
1188 1182
1189 lock_kernel(); 1183 lock_kernel();
1190 1184
@@ -1212,8 +1206,9 @@ int __break_lease(struct inode *inode, unsigned int mode)
1212 goto out; 1206 goto out;
1213 } 1207 }
1214 1208
1215 if (alloc_err && !i_have_this_lease && ((mode & O_NONBLOCK) == 0)) { 1209 if (IS_ERR(new_fl) && !i_have_this_lease
1216 error = alloc_err; 1210 && ((mode & O_NONBLOCK) == 0)) {
1211 error = PTR_ERR(new_fl);
1217 goto out; 1212 goto out;
1218 } 1213 }
1219 1214
@@ -1260,7 +1255,7 @@ restart:
1260 1255
1261out: 1256out:
1262 unlock_kernel(); 1257 unlock_kernel();
1263 if (!alloc_err) 1258 if (!IS_ERR(new_fl))
1264 locks_free_lock(new_fl); 1259 locks_free_lock(new_fl);
1265 return error; 1260 return error;
1266} 1261}
@@ -1329,7 +1324,7 @@ int fcntl_getlease(struct file *filp)
1329} 1324}
1330 1325
1331/** 1326/**
1332 * __setlease - sets a lease on an open file 1327 * setlease - sets a lease on an open file
1333 * @filp: file pointer 1328 * @filp: file pointer
1334 * @arg: type of lease to obtain 1329 * @arg: type of lease to obtain
1335 * @flp: input - file_lock to use, output - file_lock inserted 1330 * @flp: input - file_lock to use, output - file_lock inserted
@@ -1339,18 +1334,24 @@ int fcntl_getlease(struct file *filp)
1339 * 1334 *
1340 * Called with kernel lock held. 1335 * Called with kernel lock held.
1341 */ 1336 */
1342static int __setlease(struct file *filp, long arg, struct file_lock **flp) 1337int setlease(struct file *filp, long arg, struct file_lock **flp)
1343{ 1338{
1344 struct file_lock *fl, **before, **my_before = NULL, *lease; 1339 struct file_lock *fl, **before, **my_before = NULL, *lease;
1345 struct dentry *dentry = filp->f_path.dentry; 1340 struct dentry *dentry = filp->f_path.dentry;
1346 struct inode *inode = dentry->d_inode; 1341 struct inode *inode = dentry->d_inode;
1347 int error, rdlease_count = 0, wrlease_count = 0; 1342 int error, rdlease_count = 0, wrlease_count = 0;
1348 1343
1344 if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
1345 return -EACCES;
1346 if (!S_ISREG(inode->i_mode))
1347 return -EINVAL;
1348 error = security_file_lock(filp, arg);
1349 if (error)
1350 return error;
1351
1349 time_out_leases(inode); 1352 time_out_leases(inode);
1350 1353
1351 error = -EINVAL; 1354 BUG_ON(!(*flp)->fl_lmops->fl_break);
1352 if (!flp || !(*flp) || !(*flp)->fl_lmops || !(*flp)->fl_lmops->fl_break)
1353 goto out;
1354 1355
1355 lease = *flp; 1356 lease = *flp;
1356 1357
@@ -1418,39 +1419,49 @@ static int __setlease(struct file *filp, long arg, struct file_lock **flp)
1418out: 1419out:
1419 return error; 1420 return error;
1420} 1421}
1422EXPORT_SYMBOL(setlease);
1421 1423
1422 /** 1424 /**
1423 * setlease - sets a lease on an open file 1425 * vfs_setlease - sets a lease on an open file
1424 * @filp: file pointer 1426 * @filp: file pointer
1425 * @arg: type of lease to obtain 1427 * @arg: type of lease to obtain
1426 * @lease: file_lock to use 1428 * @lease: file_lock to use
1427 * 1429 *
1428 * Call this to establish a lease on the file. 1430 * Call this to establish a lease on the file.
1429 * The fl_lmops fl_break function is required by break_lease 1431 * The (*lease)->fl_lmops->fl_break operation must be set; if not,
1432 * break_lease will oops!
1433 *
1434 * This will call the filesystem's setlease file method, if
1435 * defined. Note that there is no getlease method; instead, the
1436 * filesystem setlease method should call back to setlease() to
1437 * add a lease to the inode's lease list, where fcntl_getlease() can
1438 * find it. Since fcntl_getlease() only reports whether the current
1439 * task holds a lease, a cluster filesystem need only do this for
1440 * leases held by processes on this node.
1441 *
1442 * There is also no break_lease method; filesystems that
1443 * handle their own leases shoud break leases themselves from the
1444 * filesystem's open, create, and (on truncate) setattr methods.
1445 *
1446 * Warning: the only current setlease methods exist only to disable
1447 * leases in certain cases. More vfs changes may be required to
1448 * allow a full filesystem lease implementation.
1430 */ 1449 */
1431 1450
1432int setlease(struct file *filp, long arg, struct file_lock **lease) 1451int vfs_setlease(struct file *filp, long arg, struct file_lock **lease)
1433{ 1452{
1434 struct dentry *dentry = filp->f_path.dentry;
1435 struct inode *inode = dentry->d_inode;
1436 int error; 1453 int error;
1437 1454
1438 if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
1439 return -EACCES;
1440 if (!S_ISREG(inode->i_mode))
1441 return -EINVAL;
1442 error = security_file_lock(filp, arg);
1443 if (error)
1444 return error;
1445
1446 lock_kernel(); 1455 lock_kernel();
1447 error = __setlease(filp, arg, lease); 1456 if (filp->f_op && filp->f_op->setlease)
1457 error = filp->f_op->setlease(filp, arg, lease);
1458 else
1459 error = setlease(filp, arg, lease);
1448 unlock_kernel(); 1460 unlock_kernel();
1449 1461
1450 return error; 1462 return error;
1451} 1463}
1452 1464EXPORT_SYMBOL_GPL(vfs_setlease);
1453EXPORT_SYMBOL(setlease);
1454 1465
1455/** 1466/**
1456 * fcntl_setlease - sets a lease on an open file 1467 * fcntl_setlease - sets a lease on an open file
@@ -1469,14 +1480,6 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1469 struct inode *inode = dentry->d_inode; 1480 struct inode *inode = dentry->d_inode;
1470 int error; 1481 int error;
1471 1482
1472 if ((current->fsuid != inode->i_uid) && !capable(CAP_LEASE))
1473 return -EACCES;
1474 if (!S_ISREG(inode->i_mode))
1475 return -EINVAL;
1476 error = security_file_lock(filp, arg);
1477 if (error)
1478 return error;
1479
1480 locks_init_lock(&fl); 1483 locks_init_lock(&fl);
1481 error = lease_init(filp, arg, &fl); 1484 error = lease_init(filp, arg, &fl);
1482 if (error) 1485 if (error)
@@ -1484,15 +1487,15 @@ int fcntl_setlease(unsigned int fd, struct file *filp, long arg)
1484 1487
1485 lock_kernel(); 1488 lock_kernel();
1486 1489
1487 error = __setlease(filp, arg, &flp); 1490 error = vfs_setlease(filp, arg, &flp);
1488 if (error || arg == F_UNLCK) 1491 if (error || arg == F_UNLCK)
1489 goto out_unlock; 1492 goto out_unlock;
1490 1493
1491 error = fasync_helper(fd, filp, 1, &flp->fl_fasync); 1494 error = fasync_helper(fd, filp, 1, &flp->fl_fasync);
1492 if (error < 0) { 1495 if (error < 0) {
1493 /* remove lease just inserted by __setlease */ 1496 /* remove lease just inserted by setlease */
1494 flp->fl_type = F_UNLCK | F_INPROGRESS; 1497 flp->fl_type = F_UNLCK | F_INPROGRESS;
1495 flp->fl_break_time = jiffies- 10; 1498 flp->fl_break_time = jiffies - 10;
1496 time_out_leases(inode); 1499 time_out_leases(inode);
1497 goto out_unlock; 1500 goto out_unlock;
1498 } 1501 }
@@ -1597,8 +1600,7 @@ asmlinkage long sys_flock(unsigned int fd, unsigned int cmd)
1597/** 1600/**
1598 * vfs_test_lock - test file byte range lock 1601 * vfs_test_lock - test file byte range lock
1599 * @filp: The file to test lock for 1602 * @filp: The file to test lock for
1600 * @fl: The lock to test 1603 * @fl: The lock to test; also used to hold result
1601 * @conf: Place to return a copy of the conflicting lock, if found
1602 * 1604 *
1603 * Returns -ERRNO on failure. Indicates presence of conflicting lock by 1605 * Returns -ERRNO on failure. Indicates presence of conflicting lock by
1604 * setting conf->fl_type to something other than F_UNLCK. 1606 * setting conf->fl_type to something other than F_UNLCK.
@@ -2274,7 +2276,7 @@ static int __init filelock_init(void)
2274{ 2276{
2275 filelock_cache = kmem_cache_create("file_lock_cache", 2277 filelock_cache = kmem_cache_create("file_lock_cache",
2276 sizeof(struct file_lock), 0, SLAB_PANIC, 2278 sizeof(struct file_lock), 0, SLAB_PANIC,
2277 init_once, NULL); 2279 init_once);
2278 return 0; 2280 return 0;
2279} 2281}
2280 2282