Commit 2bfe3e0d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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()
parents 77d4c5da 75ddaa4d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -416,6 +416,7 @@ lm_change yes no no
lm_breaker_owns_lease:	yes     	no			no
lm_lock_expirable	yes		no			no
lm_expire_lock		no		no			yes
lm_open_conflict	yes		no			no
======================	=============	=================	=========

buffer_head
+3 −3
Original line number Diff line number Diff line
@@ -315,12 +315,12 @@ int media_request_alloc(struct media_device *mdev, int *alloc_fd)

	fd_prepare_file(fdf)->private_data = req;

	*alloc_fd = fd_publish(fdf);

	snprintf(req->debug_str, sizeof(req->debug_str), "%u:%d",
		 atomic_inc_return(&mdev->request_id), *alloc_fd);
		 atomic_inc_return(&mdev->request_id), fd_prepare_fd(fdf));
	dev_dbg(mdev->dev, "request: allocated %s\n", req->debug_str);

	*alloc_fd = fd_publish(fdf);

	return 0;

err_free_req:
+2 −1
Original line number Diff line number Diff line
@@ -533,6 +533,7 @@ static struct dentry *ecryptfs_mkdir(struct mnt_idmap *idmap, struct inode *dir,
	fsstack_copy_inode_size(dir, lower_dir);
	set_nlink(dir, lower_dir->i_nlink);
out:
	dput(lower_dir_dentry);
	end_creating(lower_dentry);
	if (d_really_is_negative(dentry))
		d_drop(dentry);
@@ -584,7 +585,7 @@ ecryptfs_mknod(struct mnt_idmap *idmap, struct inode *dir,
	fsstack_copy_attr_times(dir, lower_dir);
	fsstack_copy_inode_size(dir, lower_dir);
out:
	end_removing(lower_dentry);
	end_creating(lower_dentry);
	if (d_really_is_negative(dentry))
		d_drop(dentry);
	return rc;
+3 −0
Original line number Diff line number Diff line
@@ -1593,6 +1593,9 @@ EXPORT_SYMBOL(igrab);
 * @hashval:	hash value (usually inode number) to search for
 * @test:	callback used for comparisons between inodes
 * @data:	opaque data pointer to pass to @test
 * @isnew:	return argument telling whether I_NEW was set when
 *		the inode was found in hash (the caller needs to
 *		wait for I_NEW to clear)
 *
 * Search for the inode specified by @hashval and @data in the inode cache.
 * If the inode is in the cache, the inode is returned with an incremented
+35 −15
Original line number Diff line number Diff line
@@ -832,7 +832,7 @@ static struct folio *__iomap_get_folio(struct iomap_iter *iter,
	if (!mapping_large_folio_support(iter->inode->i_mapping))
		len = min_t(size_t, len, PAGE_SIZE - offset_in_page(pos));

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

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

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

loff_t
/**
 * iomap_fill_dirty_folios - fill a folio batch with dirty folios
 * @iter: Iteration structure
 * @start: Start offset of range. Updated based on lookup progress.
 * @end: End offset of range
 * @iomap_flags: Flags to set on the associated iomap to track the batch.
 *
 * Returns the folio count directly. Also returns the associated control flag if
 * the the batch lookup is performed and the expected offset of a subsequent
 * lookup via out params. The caller is responsible to set the flag on the
 * associated iomap.
 */
unsigned int
iomap_fill_dirty_folios(
	struct iomap_iter	*iter,
	loff_t			offset,
	loff_t			length)
	loff_t			*start,
	loff_t			end,
	unsigned int		*iomap_flags)
{
	struct address_space	*mapping = iter->inode->i_mapping;
	pgoff_t			start = offset >> PAGE_SHIFT;
	pgoff_t			end = (offset + length - 1) >> PAGE_SHIFT;
	pgoff_t			pstart = *start >> PAGE_SHIFT;
	pgoff_t			pend = (end - 1) >> PAGE_SHIFT;
	unsigned int		count;

	iter->fbatch = kmalloc(sizeof(struct folio_batch), GFP_KERNEL);
	if (!iter->fbatch)
		return offset + length;
	folio_batch_init(iter->fbatch);
	if (!iter->fbatch) {
		*start = end;
		return 0;
	}

	filemap_get_folios_dirty(mapping, &start, end, iter->fbatch);
	return (start << PAGE_SHIFT);
	count = filemap_get_folios_dirty(mapping, &pstart, pend, iter->fbatch);
	*start = (pstart << PAGE_SHIFT);
	*iomap_flags |= IOMAP_F_FOLIO_BATCH;
	return count;
}
EXPORT_SYMBOL_GPL(iomap_fill_dirty_folios);

@@ -1569,17 +1585,21 @@ iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero,
		const struct iomap_ops *ops,
		const struct iomap_write_ops *write_ops, void *private)
{
	struct folio_batch fbatch;
	struct iomap_iter iter = {
		.inode		= inode,
		.pos		= pos,
		.len		= len,
		.flags		= IOMAP_ZERO,
		.private	= private,
		.fbatch		= &fbatch,
	};
	struct address_space *mapping = inode->i_mapping;
	int ret;
	bool range_dirty;

	folio_batch_init(&fbatch);

	/*
	 * To avoid an unconditional flush, check pagecache state and only flush
	 * 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,
	while ((ret = iomap_iter(&iter, ops)) > 0) {
		const struct iomap *srcmap = iomap_iter_srcmap(&iter);

		if (WARN_ON_ONCE(iter.fbatch &&
		if (WARN_ON_ONCE((iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
				 srcmap->type != IOMAP_UNWRITTEN))
			return -EIO;

		if (!iter.fbatch &&
		if (!(iter.iomap.flags & IOMAP_F_FOLIO_BATCH) &&
		    (srcmap->type == IOMAP_HOLE ||
		     srcmap->type == IOMAP_UNWRITTEN)) {
			s64 status;
Loading