Skip to content

Commit 11afe9f

Browse files
author
Christoph Hellwig
committed
fs: add FL_LAYOUT lease type
This (ab-)uses the file locking code to allow filesystems to recall outstanding pNFS layouts on a file. This new lease type is similar but not quite the same as FL_DELEG. A FL_LAYOUT lease can always be granted, an a per-filesystem lock (XFS iolock for the initial implementation) ensures not FL_LAYOUT leases granted when we would need to recall them. Also included are changes that allow multiple outstanding read leases of different types on the same file as long as they have a differnt owner. This wasn't a problem until now as nfsd never set FL_LEASE leases, and no one else used FL_DELEG leases, but given that nfsd will also issues FL_LAYOUT leases we will have to handle it now. Signed-off-by: Christoph Hellwig <hch@lst.de>
1 parent 2ab99ee commit 11afe9f

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

fs/locks.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137

138138
#define IS_POSIX(fl) (fl->fl_flags & FL_POSIX)
139139
#define IS_FLOCK(fl) (fl->fl_flags & FL_FLOCK)
140-
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG))
140+
#define IS_LEASE(fl) (fl->fl_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
141141
#define IS_OFDLCK(fl) (fl->fl_flags & FL_OFDLCK)
142142

143143
static bool lease_breaking(struct file_lock *fl)
@@ -1371,6 +1371,8 @@ static void time_out_leases(struct inode *inode, struct list_head *dispose)
13711371

13721372
static bool leases_conflict(struct file_lock *lease, struct file_lock *breaker)
13731373
{
1374+
if ((breaker->fl_flags & FL_LAYOUT) != (lease->fl_flags & FL_LAYOUT))
1375+
return false;
13741376
if ((breaker->fl_flags & FL_DELEG) && (lease->fl_flags & FL_LEASE))
13751377
return false;
13761378
return locks_conflict(breaker, lease);
@@ -1594,11 +1596,14 @@ int fcntl_getlease(struct file *filp)
15941596
* conflict with the lease we're trying to set.
15951597
*/
15961598
static int
1597-
check_conflicting_open(const struct dentry *dentry, const long arg)
1599+
check_conflicting_open(const struct dentry *dentry, const long arg, int flags)
15981600
{
15991601
int ret = 0;
16001602
struct inode *inode = dentry->d_inode;
16011603

1604+
if (flags & FL_LAYOUT)
1605+
return 0;
1606+
16021607
if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0))
16031608
return -EAGAIN;
16041609

@@ -1647,7 +1652,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
16471652

16481653
spin_lock(&ctx->flc_lock);
16491654
time_out_leases(inode, &dispose);
1650-
error = check_conflicting_open(dentry, arg);
1655+
error = check_conflicting_open(dentry, arg, lease->fl_flags);
16511656
if (error)
16521657
goto out;
16531658

@@ -1703,7 +1708,7 @@ generic_add_lease(struct file *filp, long arg, struct file_lock **flp, void **pr
17031708
* precedes these checks.
17041709
*/
17051710
smp_mb();
1706-
error = check_conflicting_open(dentry, arg);
1711+
error = check_conflicting_open(dentry, arg, lease->fl_flags);
17071712
if (error) {
17081713
locks_unlink_lock_ctx(lease, &ctx->flc_lease_cnt);
17091714
goto out;
@@ -1787,6 +1792,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp,
17871792
WARN_ON_ONCE(1);
17881793
return -ENOLCK;
17891794
}
1795+
17901796
return generic_add_lease(filp, arg, flp, priv);
17911797
default:
17921798
return -EINVAL;

include/linux/fs.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -875,6 +875,7 @@ static inline struct file *get_file(struct file *f)
875875
#define FL_DOWNGRADE_PENDING 256 /* Lease is being downgraded */
876876
#define FL_UNLOCK_PENDING 512 /* Lease is being broken */
877877
#define FL_OFDLCK 1024 /* lock is "owned" by struct file */
878+
#define FL_LAYOUT 2048 /* outstanding pNFS layout */
878879

879880
/*
880881
* Special return value from posix_lock_file() and vfs_lock_file() for
@@ -2037,6 +2038,16 @@ static inline int break_deleg_wait(struct inode **delegated_inode)
20372038
return ret;
20382039
}
20392040

2041+
static inline int break_layout(struct inode *inode, bool wait)
2042+
{
2043+
smp_mb();
2044+
if (inode->i_flctx && !list_empty_careful(&inode->i_flctx->flc_lease))
2045+
return __break_lease(inode,
2046+
wait ? O_WRONLY : O_WRONLY | O_NONBLOCK,
2047+
FL_LAYOUT);
2048+
return 0;
2049+
}
2050+
20402051
#else /* !CONFIG_FILE_LOCKING */
20412052
static inline int locks_mandatory_locked(struct file *file)
20422053
{
@@ -2092,6 +2103,11 @@ static inline int break_deleg_wait(struct inode **delegated_inode)
20922103
return 0;
20932104
}
20942105

2106+
static inline int break_layout(struct inode *inode, bool wait)
2107+
{
2108+
return 0;
2109+
}
2110+
20952111
#endif /* CONFIG_FILE_LOCKING */
20962112

20972113
/* fs/open.c */

0 commit comments

Comments
 (0)