Skip to content

Commit 2bfe3e0

Browse files
committed
Merge tag 'vfs-6.19-rc5.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs
Pull vfs fixes from Christian Brauner: - Remove incorrect __user annotation from struct xattr_args::value - Documentation fix: Add missing kernel-doc description for the @isnew parameter in ilookup5_nowait() to silence Sphinx warnings - Documentation fix: Fix kernel-doc comment for __start_dirop() - the function name in the comment was wrong and the @State parameter was undocumented - Replace dynamic folio_batch allocation with stack allocation in iomap_zero_range(). The dynamic allocation was problematic for ext4-on-iomap work (didn't handle allocation failure properly) and triggered lockdep complaints. Uses a flag instead to control batch usage - Re-add #ifdef guards around PIDFD_GET_<ns-type>_NAMESPACE ioctls. When a namespace type is disabled, ns->ops is NULL, causes crashes during inode eviction when closing the fd. The ifdefs were removed in a recent simplification but are still needed - Fixe a race where a folio could be unlocked before the trailing zeros (for EOF within the page) were written - Split out a dedicated lease_dispose_list() helper since lease code paths always know they're disposing of leases. Removes unnecessary runtime flag checks and prepares for upcoming lease_manager enhancements - Fix userland delegation requests succeeding despite conflicting opens. Previously, FL_LAYOUT and FL_DELEG leases bypassed conflict checks (a hack for nfsd). Adds new ->lm_open_conflict() lease_manager operation so userland delegations get proper conflict checking while nfsd can continue its own conflict handling - Fix LOOKUP_CACHED path lookups incorrectly falling through to the slow path. After legitimize_links() calls were conditionally elided, the routine would always fail with LOOKUP_CACHED regardless of whether there were any links. Now the flag is checked at the two callsites before calling legitimize_links() - Fix bug in media fd allocation in media_request_alloc() - Fix mismatched API calls in ecryptfs_mknod(): was calling end_removing() instead of end_creating() after ecryptfs_start_creating_dentry() - Fix dentry reference count leak in ecryptfs_mkdir(): a dget() of the lower parent dir was added but never dput()'d, causing BUG during lower filesystem unmount due to the still-in-use dentry * tag 'vfs-6.19-rc5.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs: pidfs: protect PIDFD_GET_* ioctls() via ifdef ecryptfs: Release lower parent dentry after creating dir ecryptfs: Fix improper mknod pairing of start_creating()/end_removing() get rid of bogus __user in struct xattr_args::value VFS: fix __start_dirop() kernel-doc warnings fs: Describe @isnew parameter in ilookup5_nowait() fs: make sure to fail try_to_unlazy() and try_to_unlazy() for LOOKUP_CACHED netfs: Fix early read unlock of page with EOF in middle filelock: allow lease_managers to dictate what qualifies as a conflict filelock: add lease_dispose_list() helper iomap: replace folio_batch allocation with stack allocation media: mc: fix potential use-after-free in media_request_alloc()
2 parents 77d4c5d + 75ddaa4 commit 2bfe3e0

16 files changed

Lines changed: 196 additions & 97 deletions

File tree

Documentation/filesystems/locking.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ lm_change yes no no
416416
lm_breaker_owns_lease: yes no no
417417
lm_lock_expirable yes no no
418418
lm_expire_lock no no yes
419+
lm_open_conflict yes no no
419420
====================== ============= ================= =========
420421

421422
buffer_head

drivers/media/mc/mc-request.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,12 +315,12 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)
315315

316316
fd_prepare_file(fdf)->private_data = req;
317317

318-
*alloc_fd = fd_publish(fdf);
319-
320318
snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
321-
atomic_inc_return(&mdev->request_id), *alloc_fd);
319+
atomic_inc_return(&mdev->request_id), fd_prepare_fd(fdf));
322320
dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);
323321

322+
*alloc_fd = fd_publish(fdf);
323+
324324
return 0;
325325

326326
err_free_req:

fs/ecryptfs/inode.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,7 @@ static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
533533
fsstack_copy_inode_size(dir, lower_dir);
534534
set_nlink(dir, lower_dir->i_nlink);
535535
out:
536+
dput(lower_dir_dentry);
536537
end_creating(lower_dentry);
537538
if (d_really_is_negative(dentry))
538539
d_drop(dentry);
@@ -584,7 +585,7 @@ ecryptfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
584585
fsstack_copy_attr_times(dir, lower_dir);
585586
fsstack_copy_inode_size(dir, lower_dir);
586587
out:
587-
end_removing(lower_dentry);
588+
end_creating(lower_dentry);
588589
if (d_really_is_negative(dentry))
589590
d_drop(dentry);
590591
return rc;

fs/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,6 +1593,9 @@ EXPORT_SYMBOL(igrab);
15931593
* @hashval: hash value (usually inode number) to search for
15941594
* @test: callback used for comparisons between inodes
15951595
* @data: opaque data pointer to pass to @test
1596+
* @isnew: return argument telling whether I_NEW was set when
1597+
* the inode was found in hash (the caller needs to
1598+
* wait for I_NEW to clear)
15961599
*
15971600
* Search for the inode specified by @hashval and @data in the inode cache.
15981601
* If the inode is in the cache, the inode is returned with an incremented

fs/iomap/buffered-io.c

Lines changed: 35 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ static struct folio *__iomap_get_folio(struct iomap_iter *iter,
832832
if (!mapping_large_folio_support(iter->inode->i_mapping))
833833
len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));
834834

835-
if (iter->fbatch) {
835+
if (iter->iomap.flags & IOMAP_F_FOLIO_BATCH) {
836836
struct folio *folio = folio_batch_next(iter->fbatch);
837837

838838
if (!folio)
@@ -929,7 +929,7 @@ static int iomap_write_begin(struct iomap_iter *iter,
929929
* process so return and let the caller iterate and refill the batch.
930930
*/
931931
if (!folio) {
932-
WARN_ON_ONCE(!iter->fbatch);
932+
WARN_ON_ONCE(!(iter->iomap.flags & IOMAP_F_FOLIO_BATCH));
933933
return 0;
934934
}
935935

@@ -1544,23 +1544,39 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero,
15441544
return status;
15451545
}
15461546

1547-
loff_t
1547+
/**
1548+
* iomap_fill_dirty_folios - fill a folio batch with dirty folios
1549+
* @iter: Iteration structure
1550+
* @start: Start offset of range. Updated based on lookup progress.
1551+
* @end: End offset of range
1552+
* @iomap_flags: Flags to set on the associated iomap to track the batch.
1553+
*
1554+
* Returns the folio count directly. Also returns the associated control flag if
1555+
* the the batch lookup is performed and the expected offset of a subsequent
1556+
* lookup via out params. The caller is responsible to set the flag on the
1557+
* associated iomap.
1558+
*/
1559+
unsigned int
15481560
iomap_fill_dirty_folios(
15491561
struct iomap_iter *iter,
1550-
loff_t offset,
1551-
loff_t length)
1562+
loff_t *start,
1563+
loff_t end,
1564+
unsigned int *iomap_flags)
15521565
{
15531566
struct address_space *mapping = iter->inode->i_mapping;
1554-
pgoff_t start = offset >> PAGE_SHIFT;
1555-
pgoff_t end = (offset + length - 1) >> PAGE_SHIFT;
1567+
pgoff_t pstart = *start >> PAGE_SHIFT;
1568+
pgoff_t pend = (end - 1) >> PAGE_SHIFT;
1569+
unsigned int count;
15561570

1557-
iter->fbatch = kmalloc(sizeof(struct folio_batch), GFP_KERNEL);
1558-
if (!iter->fbatch)
1559-
return offset + length;
1560-
folio_batch_init(iter->fbatch);
1571+
if (!iter->fbatch) {
1572+
*start = end;
1573+
return 0;
1574+
}
15611575

1562-
filemap_get_folios_dirty(mapping, &start, end, iter->fbatch);
1563-
return (start << PAGE_SHIFT);
1576+
count = filemap_get_folios_dirty(mapping, &pstart, pend, iter->fbatch);
1577+
*start = (pstart << PAGE_SHIFT);
1578+
*iomap_flags |= IOMAP_F_FOLIO_BATCH;
1579+
return count;
15641580
}
15651581
EXPORT_SYMBOL_GPL(iomap_fill_dirty_folios);
15661582

@@ -1569,17 +1585,21 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
15691585
const struct iomap_ops *ops,
15701586
const struct iomap_write_ops *write_ops, void *private)
15711587
{
1588+
struct folio_batch fbatch;
15721589
struct iomap_iter iter = {
15731590
.inode = inode,
15741591
.pos = pos,
15751592
.len = len,
15761593
.flags = IOMAP_ZERO,
15771594
.private = private,
1595+
.fbatch = &fbatch,
15781596
};
15791597
struct address_space *mapping = inode->i_mapping;
15801598
int ret;
15811599
bool range_dirty;
15821600

1601+
folio_batch_init(&fbatch);
1602+
15831603
/*
15841604
* To avoid an unconditional flush, check pagecache state and only flush
15851605
* if dirty and the fs returns a mapping that might convert on
@@ -1590,11 +1610,11 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
15901610
while ((ret = iomap_iter(&iter, ops)) > 0) {
15911611
const struct iomap *srcmap = iomap_iter_srcmap(&iter);
15921612

1593-
if (WARN_ON_ONCE(iter.fbatch &&
1613+
if (WARN_ON_ONCE((iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
15941614
srcmap->type != IOMAP_UNWRITTEN))
15951615
return -EIO;
15961616

1597-
if (!iter.fbatch &&
1617+
if (!(iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
15981618
(srcmap->type == IOMAP_HOLE ||
15991619
srcmap->type == IOMAP_UNWRITTEN)) {
16001620
s64 status;

fs/iomap/iter.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88

99
static inline void iomap_iter_reset_iomap(struct iomap_iter *iter)
1010
{
11-
if (iter->fbatch) {
11+
if (iter->iomap.flags & IOMAP_F_FOLIO_BATCH) {
1212
folio_batch_release(iter->fbatch);
13-
kfree(iter->fbatch);
14-
iter->fbatch = NULL;
13+
folio_batch_reinit(iter->fbatch);
14+
iter->iomap.flags &= ~IOMAP_F_FOLIO_BATCH;
1515
}
1616

1717
iter->status = 0;

fs/locks.c

Lines changed: 61 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -369,10 +369,19 @@ locks_dispose_list(struct list_head *dispose)
369369
while (!list_empty(dispose)) {
370370
flc = list_first_entry(dispose, struct file_lock_core, flc_list);
371371
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));
372+
locks_free_lock(file_lock(flc));
373+
}
374+
}
375+
376+
static void
377+
lease_dispose_list(struct list_head *dispose)
378+
{
379+
struct file_lock_core *flc;
380+
381+
while (!list_empty(dispose)) {
382+
flc = list_first_entry(dispose, struct file_lock_core, flc_list);
383+
list_del_init(&flc->flc_list);
384+
locks_free_lease(file_lease(flc));
376385
}
377386
}
378387

@@ -576,10 +585,50 @@ lease_setup(struct file_lease *fl, void **priv)
576585
__f_setown(filp, task_pid(current), PIDTYPE_TGID, 0);
577586
}
578587

588+
/**
589+
* lease_open_conflict - see if the given file points to an inode that has
590+
* an existing open that would conflict with the
591+
* desired lease.
592+
* @filp: file to check
593+
* @arg: type of lease that we're trying to acquire
594+
*
595+
* Check to see if there's an existing open fd on this file that would
596+
* conflict with the lease we're trying to set.
597+
*/
598+
static int
599+
lease_open_conflict(struct file *filp, const int arg)
600+
{
601+
struct inode *inode = file_inode(filp);
602+
int self_wcount = 0, self_rcount = 0;
603+
604+
if (arg == F_RDLCK)
605+
return inode_is_open_for_write(inode) ? -EAGAIN : 0;
606+
else if (arg != F_WRLCK)
607+
return 0;
608+
609+
/*
610+
* Make sure that only read/write count is from lease requestor.
611+
* Note that this will result in denying write leases when i_writecount
612+
* is negative, which is what we want. (We shouldn't grant write leases
613+
* on files open for execution.)
614+
*/
615+
if (filp->f_mode & FMODE_WRITE)
616+
self_wcount = 1;
617+
else if (filp->f_mode & FMODE_READ)
618+
self_rcount = 1;
619+
620+
if (atomic_read(&inode->i_writecount) != self_wcount ||
621+
atomic_read(&inode->i_readcount) != self_rcount)
622+
return -EAGAIN;
623+
624+
return 0;
625+
}
626+
579627
static const struct lease_manager_operations lease_manager_ops = {
580628
.lm_break = lease_break_callback,
581629
.lm_change = lease_modify,
582630
.lm_setup = lease_setup,
631+
.lm_open_conflict = lease_open_conflict,
583632
};
584633

585634
/*
@@ -1620,7 +1669,7 @@ int __break_lease(struct inode *inode, unsigned int flags)
16201669
spin_unlock(&ctx->flc_lock);
16211670
percpu_up_read(&file_rwsem);
16221671

1623-
locks_dispose_list(&dispose);
1672+
lease_dispose_list(&dispose);
16241673
error = wait_event_interruptible_timeout(new_fl->c.flc_wait,
16251674
list_empty(&new_fl->c.flc_blocked_member),
16261675
break_time);
@@ -1643,7 +1692,7 @@ int __break_lease(struct inode *inode, unsigned int flags)
16431692
out:
16441693
spin_unlock(&ctx->flc_lock);
16451694
percpu_up_read(&file_rwsem);
1646-
locks_dispose_list(&dispose);
1695+
lease_dispose_list(&dispose);
16471696
free_lock:
16481697
locks_free_lease(new_fl);
16491698
return error;
@@ -1727,7 +1776,7 @@ static int __fcntl_getlease(struct file *filp, unsigned int flavor)
17271776
spin_unlock(&ctx->flc_lock);
17281777
percpu_up_read(&file_rwsem);
17291778

1730-
locks_dispose_list(&dispose);
1779+
lease_dispose_list(&dispose);
17311780
}
17321781
return type;
17331782
}
@@ -1745,52 +1794,6 @@ int fcntl_getdeleg(struct file *filp, struct delegation *deleg)
17451794
return 0;
17461795
}
17471796

1748-
/**
1749-
* check_conflicting_open - see if the given file points to an inode that has
1750-
* an existing open that would conflict with the
1751-
* desired lease.
1752-
* @filp: file to check
1753-
* @arg: type of lease that we're trying to acquire
1754-
* @flags: current lock flags
1755-
*
1756-
* Check to see if there's an existing open fd on this file that would
1757-
* conflict with the lease we're trying to set.
1758-
*/
1759-
static int
1760-
check_conflicting_open(struct file *filp, const int arg, int flags)
1761-
{
1762-
struct inode *inode = file_inode(filp);
1763-
int self_wcount = 0, self_rcount = 0;
1764-
1765-
if (flags & FL_LAYOUT)
1766-
return 0;
1767-
if (flags & FL_DELEG)
1768-
/* We leave these checks to the caller */
1769-
return 0;
1770-
1771-
if (arg == F_RDLCK)
1772-
return inode_is_open_for_write(inode) ? -EAGAIN : 0;
1773-
else if (arg != F_WRLCK)
1774-
return 0;
1775-
1776-
/*
1777-
* Make sure that only read/write count is from lease requestor.
1778-
* Note that this will result in denying write leases when i_writecount
1779-
* is negative, which is what we want. (We shouldn't grant write leases
1780-
* on files open for execution.)
1781-
*/
1782-
if (filp->f_mode & FMODE_WRITE)
1783-
self_wcount = 1;
1784-
else if (filp->f_mode & FMODE_READ)
1785-
self_rcount = 1;
1786-
1787-
if (atomic_read(&inode->i_writecount) != self_wcount ||
1788-
atomic_read(&inode->i_readcount) != self_rcount)
1789-
return -EAGAIN;
1790-
1791-
return 0;
1792-
}
1793-
17941797
static int
17951798
generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **priv)
17961799
{
@@ -1827,7 +1830,7 @@ generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **pr
18271830
percpu_down_read(&file_rwsem);
18281831
spin_lock(&ctx->flc_lock);
18291832
time_out_leases(inode, &dispose);
1830-
error = check_conflicting_open(filp, arg, lease->c.flc_flags);
1833+
error = lease->fl_lmops->lm_open_conflict(filp, arg);
18311834
if (error)
18321835
goto out;
18331836

@@ -1884,7 +1887,7 @@ generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **pr
18841887
* precedes these checks.
18851888
*/
18861889
smp_mb();
1887-
error = check_conflicting_open(filp, arg, lease->c.flc_flags);
1890+
error = lease->fl_lmops->lm_open_conflict(filp, arg);
18881891
if (error) {
18891892
locks_unlink_lock_ctx(&lease->c);
18901893
goto out;
@@ -1896,7 +1899,7 @@ generic_add_lease(struct file *filp, int arg, struct file_lease **flp, void **pr
18961899
out:
18971900
spin_unlock(&ctx->flc_lock);
18981901
percpu_up_read(&file_rwsem);
1899-
locks_dispose_list(&dispose);
1902+
lease_dispose_list(&dispose);
19001903
if (is_deleg)
19011904
inode_unlock(inode);
19021905
if (!error && !my_fl)
@@ -1932,7 +1935,7 @@ static int generic_delete_lease(struct file *filp, void *owner)
19321935
error = fl->fl_lmops->lm_change(victim, F_UNLCK, &dispose);
19331936
spin_unlock(&ctx->flc_lock);
19341937
percpu_up_read(&file_rwsem);
1935-
locks_dispose_list(&dispose);
1938+
lease_dispose_list(&dispose);
19361939
return error;
19371940
}
19381941

@@ -2735,7 +2738,7 @@ locks_remove_lease(struct file *filp, struct file_lock_context *ctx)
27352738
spin_unlock(&ctx->flc_lock);
27362739
percpu_up_read(&file_rwsem);
27372740

2738-
locks_dispose_list(&dispose);
2741+
lease_dispose_list(&dispose);
27392742
}
27402743

27412744
/*

0 commit comments

Comments
 (0)