Skip to content

Commit c69ff40

Browse files
jtlaytonbrauner
authored andcommitted
filelock: split leases out of struct file_lock
Add a new struct file_lease and move the lease-specific fields from struct file_lock to it. Convert the appropriate API calls to take struct file_lease instead, and convert the callers to use them. There is zero overlap between the lock manager operations for file locks and the ones for file leases, so split the lease-related operations off into a new lease_manager_operations struct. Signed-off-by: Jeff Layton <[email protected]> Link: https://lore.kernel.org/r/[email protected] Reviewed-by: NeilBrown <[email protected]> Signed-off-by: Christian Brauner <[email protected]>
1 parent 282c30f commit c69ff40

File tree

11 files changed

+153
-98
lines changed

11 files changed

+153
-98
lines changed

fs/libfs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1580,7 +1580,7 @@ EXPORT_SYMBOL(alloc_anon_inode);
15801580
* All arguments are ignored and it just returns -EINVAL.
15811581
*/
15821582
int
1583-
simple_nosetlease(struct file *filp, int arg, struct file_lock **flp,
1583+
simple_nosetlease(struct file *filp, int arg, struct file_lease **flp,
15841584
void **priv)
15851585
{
15861586
return -EINVAL;

fs/locks.c

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,17 @@ static struct file_lock *file_lock(struct file_lock_core *flc)
7474
return container_of(flc, struct file_lock, c);
7575
}
7676

77-
static bool lease_breaking(struct file_lock *fl)
77+
static struct file_lease *file_lease(struct file_lock_core *flc)
78+
{
79+
return container_of(flc, struct file_lease, c);
80+
}
81+
82+
static bool lease_breaking(struct file_lease *fl)
7883
{
7984
return fl->c.flc_flags & (FL_UNLOCK_PENDING | FL_DOWNGRADE_PENDING);
8085
}
8186

82-
static int target_leasetype(struct file_lock *fl)
87+
static int target_leasetype(struct file_lease *fl)
8388
{
8489
if (fl->c.flc_flags & FL_UNLOCK_PENDING)
8590
return F_UNLCK;
@@ -166,6 +171,7 @@ static DEFINE_SPINLOCK(blocked_lock_lock);
166171

167172
static struct kmem_cache *flctx_cache __ro_after_init;
168173
static struct kmem_cache *filelock_cache __ro_after_init;
174+
static struct kmem_cache *filelease_cache __ro_after_init;
169175

170176
static struct file_lock_context *
171177
locks_get_lock_context(struct inode *inode, int type)
@@ -275,6 +281,18 @@ struct file_lock *locks_alloc_lock(void)
275281
}
276282
EXPORT_SYMBOL_GPL(locks_alloc_lock);
277283

284+
/* Allocate an empty lock structure. */
285+
struct file_lease *locks_alloc_lease(void)
286+
{
287+
struct file_lease *fl = kmem_cache_zalloc(filelease_cache, GFP_KERNEL);
288+
289+
if (fl)
290+
locks_init_lock_heads(&fl->c);
291+
292+
return fl;
293+
}
294+
EXPORT_SYMBOL_GPL(locks_alloc_lease);
295+
278296
void locks_release_private(struct file_lock *fl)
279297
{
280298
struct file_lock_core *flc = &fl->c;
@@ -336,15 +354,25 @@ void locks_free_lock(struct file_lock *fl)
336354
}
337355
EXPORT_SYMBOL(locks_free_lock);
338356

357+
/* Free a lease which is not in use. */
358+
void locks_free_lease(struct file_lease *fl)
359+
{
360+
kmem_cache_free(filelease_cache, fl);
361+
}
362+
EXPORT_SYMBOL(locks_free_lease);
363+
339364
static void
340365
locks_dispose_list(struct list_head *dispose)
341366
{
342-
struct file_lock *fl;
367+
struct file_lock_core *flc;
343368

344369
while (!list_empty(dispose)) {
345-
fl = list_first_entry(dispose, struct file_lock, c.flc_list);
346-
list_del_init(&fl->c.flc_list);
347-
locks_free_lock(fl);
370+
flc = list_first_entry(dispose, struct file_lock_core, flc_list);
371+
list_del_init(&flc->flc_list);
372+
if (flc->flc_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT))
373+
locks_free_lease(file_lease(flc));
374+
else
375+
locks_free_lock(file_lock(flc));
348376
}
349377
}
350378

@@ -355,6 +383,13 @@ void locks_init_lock(struct file_lock *fl)
355383
}
356384
EXPORT_SYMBOL(locks_init_lock);
357385

386+
void locks_init_lease(struct file_lease *fl)
387+
{
388+
memset(fl, 0, sizeof(*fl));
389+
locks_init_lock_heads(&fl->c);
390+
}
391+
EXPORT_SYMBOL(locks_init_lease);
392+
358393
/*
359394
* Initialize a new lock from an existing file_lock structure.
360395
*/
@@ -518,14 +553,14 @@ static int flock_to_posix_lock(struct file *filp, struct file_lock *fl,
518553

519554
/* default lease lock manager operations */
520555
static bool
521-
lease_break_callback(struct file_lock *fl)
556+
lease_break_callback(struct file_lease *fl)
522557
{
523558
kill_fasync(&fl->fl_fasync, SIGIO, POLL_MSG);
524559
return false;
525560
}
526561

527562
static void
528-
lease_setup(struct file_lock *fl, void **priv)
563+
lease_setup(struct file_lease *fl, void **priv)
529564
{
530565
struct file *filp = fl->c.flc_file;
531566
struct fasync_struct *fa = *priv;
@@ -541,7 +576,7 @@ lease_setup(struct file_lock *fl, void **priv)
541576
__f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
542577
}
543578

544-
static const struct lock_manager_operations lease_manager_ops = {
579+
static const struct lease_manager_operations lease_manager_ops = {
545580
.lm_break = lease_break_callback,
546581
.lm_change = lease_modify,
547582
.lm_setup = lease_setup,
@@ -550,7 +585,7 @@ static const struct lock_manager_operations lease_manager_ops = {
550585
/*
551586
* Initialize a lease, use the default lock manager operations
552587
*/
553-
static int lease_init(struct file *filp, int type, struct file_lock *fl)
588+
static int lease_init(struct file *filp, int type, struct file_lease *fl)
554589
{
555590
if (assign_type(&fl->c, type) != 0)
556591
return -EINVAL;
@@ -560,25 +595,22 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
560595

561596
fl->c.flc_file = filp;
562597
fl->c.flc_flags = FL_LEASE;
563-
fl->fl_start = 0;
564-
fl->fl_end = OFFSET_MAX;
565-
fl->fl_ops = NULL;
566598
fl->fl_lmops = &lease_manager_ops;
567599
return 0;
568600
}
569601

570602
/* Allocate a file_lock initialised to this type of lease */
571-
static struct file_lock *lease_alloc(struct file *filp, int type)
603+
static struct file_lease *lease_alloc(struct file *filp, int type)
572604
{
573-
struct file_lock *fl = locks_alloc_lock();
605+
struct file_lease *fl = locks_alloc_lease();
574606
int error = -ENOMEM;
575607

576608
if (fl == NULL)
577609
return ERR_PTR(error);
578610

579611
error = lease_init(filp, type, fl);
580612
if (error) {
581-
locks_free_lock(fl);
613+
locks_free_lease(fl);
582614
return ERR_PTR(error);
583615
}
584616
return fl;
@@ -1395,7 +1427,7 @@ static int posix_lock_inode_wait(struct inode *inode, struct file_lock *fl)
13951427
return error;
13961428
}
13971429

1398-
static void lease_clear_pending(struct file_lock *fl, int arg)
1430+
static void lease_clear_pending(struct file_lease *fl, int arg)
13991431
{
14001432
switch (arg) {
14011433
case F_UNLCK:
@@ -1407,7 +1439,7 @@ static void lease_clear_pending(struct file_lock *fl, int arg)
14071439
}
14081440

14091441
/* We already had a lease on this file; just change its type */
1410-
int lease_modify(struct file_lock *fl, int arg, struct list_head *dispose)
1442+
int lease_modify(struct file_lease *fl, int arg, struct list_head *dispose)
14111443
{
14121444
int error = assign_type(&fl->c, arg);
14131445

@@ -1442,7 +1474,7 @@ static bool past_time(unsigned long then)
14421474
static void time_out_leases(struct inode *inode, struct list_head *dispose)
14431475
{
14441476
struct file_lock_context *ctx = inode->i_flctx;
1445-
struct file_lock *fl, *tmp;
1477+
struct file_lease *fl, *tmp;
14461478

14471479
lockdep_assert_held(&ctx->flc_lock);
14481480

@@ -1458,8 +1490,8 @@ static void time_out_leases(struct inode *inode, struct list_head *dispose)
14581490
static bool leases_conflict(struct file_lock_core *lc, struct file_lock_core *bc)
14591491
{
14601492
bool rc;
1461-
struct file_lock *lease = file_lock(lc);
1462-
struct file_lock *breaker = file_lock(bc);
1493+
struct file_lease *lease = file_lease(lc);
1494+
struct file_lease *breaker = file_lease(bc);
14631495

14641496
if (lease->fl_lmops->lm_breaker_owns_lease
14651497
&& lease->fl_lmops->lm_breaker_owns_lease(lease))
@@ -1480,7 +1512,7 @@ static bool leases_conflict(struct file_lock_core *lc, struct file_lock_core *bc
14801512
}
14811513

14821514
static bool
1483-
any_leases_conflict(struct inode *inode, struct file_lock *breaker)
1515+
any_leases_conflict(struct inode *inode, struct file_lease *breaker)
14841516
{
14851517
struct file_lock_context *ctx = inode->i_flctx;
14861518
struct file_lock_core *flc;
@@ -1511,7 +1543,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
15111543
{
15121544
int error = 0;
15131545
struct file_lock_context *ctx;
1514-
struct file_lock *new_fl, *fl, *tmp;
1546+
struct file_lease *new_fl, *fl, *tmp;
15151547
unsigned long break_time;
15161548
int want_write = (mode & O_ACCMODE) != O_RDONLY;
15171549
LIST_HEAD(dispose);
@@ -1571,7 +1603,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
15711603
}
15721604

15731605
restart:
1574-
fl = list_first_entry(&ctx->flc_lease, struct file_lock, c.flc_list);
1606+
fl = list_first_entry(&ctx->flc_lease, struct file_lease, c.flc_list);
15751607
break_time = fl->fl_break_time;
15761608
if (break_time != 0)
15771609
break_time -= jiffies;
@@ -1590,7 +1622,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
15901622
percpu_down_read(&file_rwsem);
15911623
spin_lock(&ctx->flc_lock);
15921624
trace_break_lease_unblock(inode, new_fl);
1593-
locks_delete_block(new_fl);
1625+
__locks_delete_block(&new_fl->c);
15941626
if (error >= 0) {
15951627
/*
15961628
* Wait for the next conflicting lease that has not been
@@ -1607,7 +1639,7 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type)
16071639
percpu_up_read(&file_rwsem);
16081640
locks_dispose_list(&dispose);
16091641
free_lock:
1610-
locks_free_lock(new_fl);
1642+
locks_free_lease(new_fl);
16111643
return error;
16121644
}
16131645
EXPORT_SYMBOL(__break_lease);
@@ -1625,14 +1657,14 @@ void lease_get_mtime(struct inode *inode, struct timespec64 *time)
16251657
{
16261658
bool has_lease = false;
16271659
struct file_lock_context *ctx;
1628-
struct file_lock *fl;
1660+
struct file_lock_core *flc;
16291661

16301662
ctx = locks_inode_context(inode);
16311663
if (ctx && !list_empty_careful(&ctx->flc_lease)) {
16321664
spin_lock(&ctx->flc_lock);
1633-
fl = list_first_entry_or_null(&ctx->flc_lease,
1634-
struct file_lock, c.flc_list);
1635-
if (fl && lock_is_write(fl))
1665+
flc = list_first_entry_or_null(&ctx->flc_lease,
1666+
struct file_lock_core, flc_list);
1667+
if (flc && flc->flc_type == F_WRLCK)
16361668
has_lease = true;
16371669
spin_unlock(&ctx->flc_lock);
16381670
}
@@ -1667,7 +1699,7 @@ EXPORT_SYMBOL(lease_get_mtime);
16671699
*/
16681700
int fcntl_getlease(struct file *filp)
16691701
{
1670-
struct file_lock *fl;
1702+
struct file_lease *fl;
16711703
struct inode *inode = file_inode(filp);
16721704
struct file_lock_context *ctx;
16731705
int type = F_UNLCK;
@@ -1739,9 +1771,9 @@ check_conflicting_open(struct file *filp, const int arg, int flags)
17391771
}
17401772

17411773
static int
1742-
generic_add_lease(struct file *filp, int arg, struct file_lock **flp, void **priv)
1774+
generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **priv)
17431775
{
1744-
struct file_lock *fl, *my_fl = NULL, *lease;
1776+
struct file_lease *fl, *my_fl = NULL, *lease;
17451777
struct inode *inode = file_inode(filp);
17461778
struct file_lock_context *ctx;
17471779
bool is_deleg = (*flp)->c.flc_flags & FL_DELEG;
@@ -1850,7 +1882,7 @@ generic_add_lease(struct file *filp, int arg, struct file_lock **flp, void **pri
18501882
static int generic_delete_lease(struct file *filp, void *owner)
18511883
{
18521884
int error = -EAGAIN;
1853-
struct file_lock *fl, *victim = NULL;
1885+
struct file_lease *fl, *victim = NULL;
18541886
struct inode *inode = file_inode(filp);
18551887
struct file_lock_context *ctx;
18561888
LIST_HEAD(dispose);
@@ -1890,7 +1922,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
18901922
* The (input) flp->fl_lmops->lm_break function is required
18911923
* by break_lease().
18921924
*/
1893-
int generic_setlease(struct file *filp, int arg, struct file_lock **flp,
1925+
int generic_setlease(struct file *filp, int arg, struct file_lease **flp,
18941926
void **priv)
18951927
{
18961928
struct inode *inode = file_inode(filp);
@@ -1937,7 +1969,7 @@ lease_notifier_chain_init(void)
19371969
}
19381970

19391971
static inline void
1940-
setlease_notifier(int arg, struct file_lock *lease)
1972+
setlease_notifier(int arg, struct file_lease *lease)
19411973
{
19421974
if (arg != F_UNLCK)
19431975
srcu_notifier_call_chain(&lease_notifier_chain, arg, lease);
@@ -1973,7 +2005,7 @@ EXPORT_SYMBOL_GPL(lease_unregister_notifier);
19732005
* may be NULL if the lm_setup operation doesn't require it.
19742006
*/
19752007
int
1976-
vfs_setlease(struct file *filp, int arg, struct file_lock **lease, void **priv)
2008+
vfs_setlease(struct file *filp, int arg, struct file_lease **lease, void **priv)
19772009
{
19782010
if (lease)
19792011
setlease_notifier(arg, *lease);
@@ -1986,7 +2018,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease);
19862018

19872019
static int do_fcntl_add_lease(unsigned int fd, struct file *filp, int arg)
19882020
{
1989-
struct file_lock *fl;
2021+
struct file_lease *fl;
19902022
struct fasync_struct *new;
19912023
int error;
19922024

@@ -1996,14 +2028,14 @@ static int do_fcntl_add_lease(unsigned int fd, struct file *filp, int arg)
19962028

19972029
new = fasync_alloc();
19982030
if (!new) {
1999-
locks_free_lock(fl);
2031+
locks_free_lease(fl);
20002032
return -ENOMEM;
20012033
}
20022034
new->fa_fd = fd;
20032035

20042036
error = vfs_setlease(filp, arg, &fl, (void **)&new);
20052037
if (fl)
2006-
locks_free_lock(fl);
2038+
locks_free_lease(fl);
20072039
if (new)
20082040
fasync_free(new);
20092041
return error;
@@ -2626,7 +2658,7 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
26262658
static void
26272659
locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
26282660
{
2629-
struct file_lock *fl, *tmp;
2661+
struct file_lease *fl, *tmp;
26302662
LIST_HEAD(dispose);
26312663

26322664
if (list_empty(&ctx->flc_lease))
@@ -2755,14 +2787,16 @@ static void lock_get_status(struct seq_file *f, struct file_lock_core *flc,
27552787
} else if (flc->flc_flags & FL_FLOCK) {
27562788
seq_puts(f, "FLOCK ADVISORY ");
27572789
} else if (flc->flc_flags & (FL_LEASE|FL_DELEG|FL_LAYOUT)) {
2758-
type = target_leasetype(fl);
2790+
struct file_lease *lease = file_lease(flc);
2791+
2792+
type = target_leasetype(lease);
27592793

27602794
if (flc->flc_flags & FL_DELEG)
27612795
seq_puts(f, "DELEG ");
27622796
else
27632797
seq_puts(f, "LEASE ");
27642798

2765-
if (lease_breaking(fl))
2799+
if (lease_breaking(lease))
27662800
seq_puts(f, "BREAKING ");
27672801
else if (flc->flc_file)
27682802
seq_puts(f, "ACTIVE ");
@@ -2945,6 +2979,9 @@ static int __init filelock_init(void)
29452979
filelock_cache = kmem_cache_create("file_lock_cache",
29462980
sizeof(struct file_lock), 0, SLAB_PANIC, NULL);
29472981

2982+
filelease_cache = kmem_cache_create("file_lock_cache",
2983+
sizeof(struct file_lease), 0, SLAB_PANIC, NULL);
2984+
29482985
for_each_possible_cpu(i) {
29492986
struct file_lock_list_struct *fll = per_cpu_ptr(&file_lock_list, i);
29502987

fs/nfs/nfs4_fs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ extern int update_open_stateid(struct nfs4_state *state,
330330
const nfs4_stateid *deleg_stateid,
331331
fmode_t fmode);
332332
extern int nfs4_proc_setlease(struct file *file, int arg,
333-
struct file_lock **lease, void **priv);
333+
struct file_lease **lease, void **priv);
334334
extern int nfs4_proc_get_lease_time(struct nfs_client *clp,
335335
struct nfs_fsinfo *fsinfo);
336336
extern void nfs4_update_changeattr(struct inode *dir,

0 commit comments

Comments
 (0)