diff options
author | J. Bruce Fields <bfields@redhat.com> | 2011-09-21 08:34:32 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2011-09-21 10:40:54 -0400 |
commit | 8335ebd94b3f5bed7875cc35848bbe46d8381695 (patch) | |
tree | 479659c4285c3dd6cb7a2c3da88c77bb939ac94c /fs/locks.c | |
parent | c856694e3d46976c76bf5b92091cb1efa211208d (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.c | 98 |
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 | /** | 1355 | int 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 | */ | ||
1366 | int 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) | |||
1446 | out: | 1416 | out: |
1447 | return error; | 1417 | return error; |
1448 | } | 1418 | } |
1419 | |||
1420 | int 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 | */ | ||
1447 | int 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 | } | ||
1449 | EXPORT_SYMBOL(generic_setlease); | 1475 | EXPORT_SYMBOL(generic_setlease); |
1450 | 1476 | ||
1451 | static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) | 1477 | static int __vfs_setlease(struct file *filp, long arg, struct file_lock **lease) |