aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-18 21:27:00 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-18 21:27:00 -0400
commita8dcf12f9e8ba113251c04d602f1695d537fb142 (patch)
tree1b36a19e34a8471e847bfea88dc66ee6683b7b07 /fs
parentd796e641a3eea2109381d6b0af533454f44916fa (diff)
parent6924c55492c904695f13c552c461c2211f4fdd6a (diff)
Merge branch 'for-linus' of git://linux-nfs.org/~bfields/linux
* 'for-linus' of git://linux-nfs.org/~bfields/linux: locks: fix vfs_test_lock() comment locks: make posix_test_lock() interface more consistent nfs: disable leases over NFS gfs2: stop giving out non-cluster-coherent leases locks: export setlease to filesystems locks: provide a file lease method enabling cluster-coherent leases locks: rename lease functions to reflect locks.c conventions locks: share more common lease code locks: clean up lease_alloc() locks: convert an -EINVAL return to a BUG leases: minor break_lease() comment clarification
Diffstat (limited to 'fs')
-rw-r--r--fs/gfs2/ops_file.c24
-rw-r--r--fs/locks.c112
-rw-r--r--fs/nfs/file.c16
-rw-r--r--fs/nfsd/nfs4state.c10
4 files changed, 101 insertions, 61 deletions
diff --git a/fs/gfs2/ops_file.c b/fs/gfs2/ops_file.c
index 196d83266e34..1a5e8e893d75 100644
--- a/fs/gfs2/ops_file.c
+++ b/fs/gfs2/ops_file.c
@@ -489,6 +489,29 @@ static int gfs2_fsync(struct file *file, struct dentry *dentry, int datasync)
489} 489}
490 490
491/** 491/**
492 * gfs2_setlease - acquire/release a file lease
493 * @file: the file pointer
494 * @arg: lease type
495 * @fl: file lock
496 *
497 * Returns: errno
498 */
499
500static int gfs2_setlease(struct file *file, long arg, struct file_lock **fl)
501{
502 struct gfs2_sbd *sdp = GFS2_SB(file->f_mapping->host);
503
504 /*
505 * We don't currently have a way to enforce a lease across the whole
506 * cluster; until we do, disable leases (by just returning -EINVAL),
507 * unless the administrator has requested purely local locking.
508 */
509 if (!sdp->sd_args.ar_localflocks)
510 return -EINVAL;
511 return setlease(file, arg, fl);
512}
513
514/**
492 * gfs2_lock - acquire/release a posix lock on a file 515 * gfs2_lock - acquire/release a posix lock on a file
493 * @file: the file pointer 516 * @file: the file pointer
494 * @cmd: either modify or retrieve lock state, possibly wait 517 * @cmd: either modify or retrieve lock state, possibly wait
@@ -638,6 +661,7 @@ const struct file_operations gfs2_file_fops = {
638 .flock = gfs2_flock, 661 .flock = gfs2_flock,
639 .splice_read = generic_file_splice_read, 662 .splice_read = generic_file_splice_read,
640 .splice_write = generic_file_splice_write, 663 .splice_write = generic_file_splice_write,
664 .setlease = gfs2_setlease,
641}; 665};
642 666
643const struct file_operations gfs2_dir_fops = { 667const struct file_operations gfs2_dir_fops = {
diff --git a/fs/locks.c b/fs/locks.c
index 431a8b871fce..4f2d749ac624 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.
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 8689b736fdd9..c87dc713b5d7 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -53,6 +53,7 @@ static int nfs_fsync(struct file *, struct dentry *dentry, int datasync);
53static int nfs_check_flags(int flags); 53static int nfs_check_flags(int flags);
54static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); 54static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl);
55static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl); 55static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl);
56static int nfs_setlease(struct file *file, long arg, struct file_lock **fl);
56 57
57const struct file_operations nfs_file_operations = { 58const struct file_operations nfs_file_operations = {
58 .llseek = nfs_file_llseek, 59 .llseek = nfs_file_llseek,
@@ -69,6 +70,7 @@ const struct file_operations nfs_file_operations = {
69 .flock = nfs_flock, 70 .flock = nfs_flock,
70 .splice_read = nfs_file_splice_read, 71 .splice_read = nfs_file_splice_read,
71 .check_flags = nfs_check_flags, 72 .check_flags = nfs_check_flags,
73 .setlease = nfs_setlease,
72}; 74};
73 75
74const struct inode_operations nfs_file_inode_operations = { 76const struct inode_operations nfs_file_inode_operations = {
@@ -400,7 +402,9 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
400 402
401 lock_kernel(); 403 lock_kernel();
402 /* Try local locking first */ 404 /* Try local locking first */
403 if (posix_test_lock(filp, fl)) { 405 posix_test_lock(filp, fl);
406 if (fl->fl_type != F_UNLCK) {
407 /* found a conflict */
404 goto out; 408 goto out;
405 } 409 }
406 410
@@ -558,3 +562,13 @@ static int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
558 return do_unlk(filp, cmd, fl); 562 return do_unlk(filp, cmd, fl);
559 return do_setlk(filp, cmd, fl); 563 return do_setlk(filp, cmd, fl);
560} 564}
565
566static int nfs_setlease(struct file *file, long arg, struct file_lock **fl)
567{
568 /*
569 * There is no protocol support for leases, so we have no way
570 * to implement them correctly in the face of opens by other
571 * clients.
572 */
573 return -EINVAL;
574}
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index e4a4c87ec8c6..6284807bd37e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -256,7 +256,7 @@ nfs4_close_delegation(struct nfs4_delegation *dp)
256 /* The following nfsd_close may not actually close the file, 256 /* The following nfsd_close may not actually close the file,
257 * but we want to remove the lease in any case. */ 257 * but we want to remove the lease in any case. */
258 if (dp->dl_flock) 258 if (dp->dl_flock)
259 setlease(filp, F_UNLCK, &dp->dl_flock); 259 vfs_setlease(filp, F_UNLCK, &dp->dl_flock);
260 nfsd_close(filp); 260 nfsd_close(filp);
261} 261}
262 262
@@ -1402,7 +1402,7 @@ void nfsd_release_deleg_cb(struct file_lock *fl)
1402/* 1402/*
1403 * Set the delegation file_lock back pointer. 1403 * Set the delegation file_lock back pointer.
1404 * 1404 *
1405 * Called from __setlease() with lock_kernel() held. 1405 * Called from setlease() with lock_kernel() held.
1406 */ 1406 */
1407static 1407static
1408void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl) 1408void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
@@ -1416,7 +1416,7 @@ void nfsd_copy_lock_deleg_cb(struct file_lock *new, struct file_lock *fl)
1416} 1416}
1417 1417
1418/* 1418/*
1419 * Called from __setlease() with lock_kernel() held 1419 * Called from setlease() with lock_kernel() held
1420 */ 1420 */
1421static 1421static
1422int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try) 1422int nfsd_same_client_deleg_cb(struct file_lock *onlist, struct file_lock *try)
@@ -1716,10 +1716,10 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1716 fl.fl_file = stp->st_vfs_file; 1716 fl.fl_file = stp->st_vfs_file;
1717 fl.fl_pid = current->tgid; 1717 fl.fl_pid = current->tgid;
1718 1718
1719 /* setlease checks to see if delegation should be handed out. 1719 /* vfs_setlease checks to see if delegation should be handed out.
1720 * the lock_manager callbacks fl_mylease and fl_change are used 1720 * the lock_manager callbacks fl_mylease and fl_change are used
1721 */ 1721 */
1722 if ((status = setlease(stp->st_vfs_file, 1722 if ((status = vfs_setlease(stp->st_vfs_file,
1723 flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) { 1723 flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
1724 dprintk("NFSD: setlease failed [%d], no delegation\n", status); 1724 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
1725 unhash_delegation(dp); 1725 unhash_delegation(dp);