aboutsummaryrefslogtreecommitdiffstats
path: root/fs/locks.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-09-21 08:34:32 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-09-21 10:40:54 -0400
commit8335ebd94b3f5bed7875cc35848bbe46d8381695 (patch)
tree479659c4285c3dd6cb7a2c3da88c77bb939ac94c /fs/locks.c
parentc856694e3d46976c76bf5b92091cb1efa211208d (diff)
leases: split up generic_setlease into lock/unlock cases
Eventually we should probably do the same thing to the file operations as well. Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/locks.c')
-rw-r--r--fs/locks.c98
1 files changed, 62 insertions, 36 deletions
diff --git a/fs/locks.c b/fs/locks.c
index 9b8408eb694..b342902c38b 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1352,18 +1352,7 @@ int fcntl_getlease(struct file *filp)
1352 return type; 1352 return type;
1353} 1353}
1354 1354
1355/** 1355int generic_add_lease(struct file *filp, long arg, struct file_lock **flp)
1356 * generic_setlease - sets a lease on an open file
1357 * @filp: file pointer
1358 * @arg: type of lease to obtain
1359 * @flp: input - file_lock to use, output - file_lock inserted
1360 *
1361 * The (input) flp->fl_lmops->lm_break function is required
1362 * by break_lease().
1363 *
1364 * Called with file_lock_lock held.
1365 */
1366int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1367{ 1356{
1368 struct file_lock *fl, **before, **my_before = NULL, *lease; 1357 struct file_lock *fl, **before, **my_before = NULL, *lease;
1369 struct dentry *dentry = filp->f_path.dentry; 1358 struct dentry *dentry = filp->f_path.dentry;
@@ -1372,30 +1361,14 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1372 1361
1373 lease = *flp; 1362 lease = *flp;
1374 1363
1375 error = -EACCES; 1364 error = -EAGAIN;
1376 if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE)) 1365 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1377 goto out;
1378 error = -EINVAL;
1379 if (!S_ISREG(inode->i_mode))
1380 goto out; 1366 goto out;
1381 error = security_file_lock(filp, arg); 1367 if ((arg == F_WRLCK)
1382 if (error) 1368 && ((dentry->d_count > 1)
1369 || (atomic_read(&inode->i_count) > 1)))
1383 goto out; 1370 goto out;
1384 1371
1385 time_out_leases(inode);
1386
1387 BUG_ON(!(*flp)->fl_lmops->lm_break);
1388
1389 if (arg != F_UNLCK) {
1390 error = -EAGAIN;
1391 if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
1392 goto out;
1393 if ((arg == F_WRLCK)
1394 && ((dentry->d_count > 1)
1395 || (atomic_read(&inode->i_count) > 1)))
1396 goto out;
1397 }
1398
1399 /* 1372 /*
1400 * At this point, we know that if there is an exclusive 1373 * At this point, we know that if there is an exclusive
1401 * lease on this file, then we hold it on this filp 1374 * lease on this file, then we hold it on this filp
@@ -1433,9 +1406,6 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1433 goto out; 1406 goto out;
1434 } 1407 }
1435 1408
1436 if (arg == F_UNLCK)
1437 goto out;
1438
1439 error = -EINVAL; 1409 error = -EINVAL;
1440 if (!leases_enable) 1410 if (!leases_enable)
1441 goto out; 1411 goto out;
@@ -1446,6 +1416,62 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1446out: 1416out:
1447 return error; 1417 return error;
1448} 1418}
1419
1420int generic_delete_lease(struct file *filp, struct file_lock **flp)
1421{
1422 struct file_lock *fl, **before;
1423 struct dentry *dentry = filp->f_path.dentry;
1424 struct inode *inode = dentry->d_inode;
1425
1426 for (before = &inode->i_flock;
1427 ((fl = *before) != NULL) && IS_LEASE(fl);
1428 before = &fl->fl_next) {
1429 if (fl->fl_file != filp)
1430 continue;
1431 return (*flp)->fl_lmops->lm_change(before, F_UNLCK);
1432 }
1433 return -EAGAIN;
1434}
1435
1436/**
1437 * generic_setlease - sets a lease on an open file
1438 * @filp: file pointer
1439 * @arg: type of lease to obtain
1440 * @flp: input - file_lock to use, output - file_lock inserted
1441 *
1442 * The (input) flp->fl_lmops->lm_break function is required
1443 * by break_lease().
1444 *
1445 * Called with file_lock_lock held.
1446 */
1447int generic_setlease(struct file *filp, long arg, struct file_lock **flp)
1448{
1449 struct dentry *dentry = filp->f_path.dentry;
1450 struct inode *inode = dentry->d_inode;
1451 int error;
1452
1453 if ((current_fsuid() != inode->i_uid) && !capable(CAP_LEASE))
1454 return -EACCES;
1455 if (!S_ISREG(inode->i_mode))
1456 return -EINVAL;
1457 error = security_file_lock(filp, arg);
1458 if (error)
1459 return error;
1460
1461 time_out_leases(inode);
1462
1463 BUG_ON(!(*flp)->fl_lmops->lm_break);
1464
1465 switch (arg) {
1466 case F_UNLCK:
1467 return generic_delete_lease(filp, flp);
1468 case F_RDLCK:
1469 case F_WRLCK:
1470 return generic_add_lease(filp, arg, flp);
1471 default:
1472 BUG();
1473 }
1474}
1449EXPORT_SYMBOL(generic_setlease); 1475EXPORT_SYMBOL(generic_setlease);
1450 1476
1451static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) 1477static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease)