Commit d56239a8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'vfs-6.12-rc6.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs

Pull filesystem fixes from Christian Brauner:
 "VFS:

   - Fix copy_page_from_iter_atomic() if KMAP_LOCAL_FORCE_MAP=y is set

   - Add a get_tree_bdev_flags() helper that allows to modify e.g.,
     whether errors are logged into the filesystem context during
     superblock creation. This is used by erofs to fix a userspace
     regression where an error is currently logged when its used on a
     regular file which is an new allowed mode in erofs.

  netfs:

   - Fix the sysfs debug path in the documentation.

   - Fix iov_iter_get_pages*() for folio queues by skipping the page
     extracation if we're at the end of a folio.

  afs:

   - Fix moving subdirectories to different parent directory.

  autofs:

   - Fix handling of AUTOFS_DEV_IOCTL_TIMEOUT_CMD ioctl in
     validate_dev_ioctl(). The actual ioctl number, not the ioctl
     command needs to be checked for autofs"

* tag 'vfs-6.12-rc6.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs:
  iov_iter: fix copy_page_from_iter_atomic() if KMAP_LOCAL_FORCE_MAP
  autofs: fix thinko in validate_dev_ioctl()
  iov_iter: Fix iov_iter_get_pages*() for folio_queue
  afs: Fix missing subdir edit when renamed between parent dirs
  doc: correcting the debug path for cachefiles
  erofs: use get_tree_bdev_flags() to avoid misleading messages
  fs/super.c: introduce get_tree_bdev_flags()
parents 6b492649 c749d9b7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ set up cache ready for use. The following script commands are available:

	This mask can also be set through sysfs, eg::

		echo 5 >/sys/modules/cachefiles/parameters/debug
		echo 5 > /sys/module/cachefiles/parameters/debug


Starting the Cache
+25 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include <linux/swap.h>
#include <linux/ctype.h>
#include <linux/sched.h>
#include <linux/iversion.h>
#include <linux/task_io_accounting_ops.h>
#include "internal.h"
#include "afs_fs.h"
@@ -1823,6 +1824,8 @@ static int afs_symlink(struct mnt_idmap *idmap, struct inode *dir,

static void afs_rename_success(struct afs_operation *op)
{
	struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry));

	_enter("op=%08x", op->debug_id);

	op->ctime = op->file[0].scb.status.mtime_client;
@@ -1832,6 +1835,22 @@ static void afs_rename_success(struct afs_operation *op)
		op->ctime = op->file[1].scb.status.mtime_client;
		afs_vnode_commit_status(op, &op->file[1]);
	}

	/* If we're moving a subdir between dirs, we need to update
	 * its DV counter too as the ".." will be altered.
	 */
	if (S_ISDIR(vnode->netfs.inode.i_mode) &&
	    op->file[0].vnode != op->file[1].vnode) {
		u64 new_dv;

		write_seqlock(&vnode->cb_lock);

		new_dv = vnode->status.data_version + 1;
		vnode->status.data_version = new_dv;
		inode_set_iversion_raw(&vnode->netfs.inode, new_dv);

		write_sequnlock(&vnode->cb_lock);
	}
}

static void afs_rename_edit_dir(struct afs_operation *op)
@@ -1873,6 +1892,12 @@ static void afs_rename_edit_dir(struct afs_operation *op)
				 &vnode->fid, afs_edit_dir_for_rename_2);
	}

	if (S_ISDIR(vnode->netfs.inode.i_mode) &&
	    new_dvnode != orig_dvnode &&
	    test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
		afs_edit_dir_update_dotdot(vnode, new_dvnode,
					   afs_edit_dir_for_rename_sub);

	new_inode = d_inode(new_dentry);
	if (new_inode) {
		spin_lock(&new_inode->i_lock);
+89 −2
Original line number Diff line number Diff line
@@ -127,10 +127,10 @@ static struct folio *afs_dir_get_folio(struct afs_vnode *vnode, pgoff_t index)
/*
 * Scan a directory block looking for a dirent of the right name.
 */
static int afs_dir_scan_block(union afs_xdr_dir_block *block, struct qstr *name,
static int afs_dir_scan_block(const union afs_xdr_dir_block *block, const struct qstr *name,
			      unsigned int blocknum)
{
	union afs_xdr_dirent *de;
	const union afs_xdr_dirent *de;
	u64 bitmap;
	int d, len, n;

@@ -492,3 +492,90 @@ void afs_edit_dir_remove(struct afs_vnode *vnode,
	clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
	goto out_unmap;
}

/*
 * Edit a subdirectory that has been moved between directories to update the
 * ".." entry.
 */
void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode,
				enum afs_edit_dir_reason why)
{
	union afs_xdr_dir_block *block;
	union afs_xdr_dirent *de;
	struct folio *folio;
	unsigned int nr_blocks, b;
	pgoff_t index;
	loff_t i_size;
	int slot;

	_enter("");

	i_size = i_size_read(&vnode->netfs.inode);
	if (i_size < AFS_DIR_BLOCK_SIZE) {
		clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
		return;
	}
	nr_blocks = i_size / AFS_DIR_BLOCK_SIZE;

	/* Find a block that has sufficient slots available.  Each folio
	 * contains two or more directory blocks.
	 */
	for (b = 0; b < nr_blocks; b++) {
		index = b / AFS_DIR_BLOCKS_PER_PAGE;
		folio = afs_dir_get_folio(vnode, index);
		if (!folio)
			goto error;

		block = kmap_local_folio(folio, b * AFS_DIR_BLOCK_SIZE - folio_pos(folio));

		/* Abandon the edit if we got a callback break. */
		if (!test_bit(AFS_VNODE_DIR_VALID, &vnode->flags))
			goto invalidated;

		slot = afs_dir_scan_block(block, &dotdot_name, b);
		if (slot >= 0)
			goto found_dirent;

		kunmap_local(block);
		folio_unlock(folio);
		folio_put(folio);
	}

	/* Didn't find the dirent to clobber.  Download the directory again. */
	trace_afs_edit_dir(vnode, why, afs_edit_dir_update_nodd,
			   0, 0, 0, 0, "..");
	clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
	goto out;

found_dirent:
	de = &block->dirents[slot];
	de->u.vnode  = htonl(new_dvnode->fid.vnode);
	de->u.unique = htonl(new_dvnode->fid.unique);

	trace_afs_edit_dir(vnode, why, afs_edit_dir_update_dd, b, slot,
			   ntohl(de->u.vnode), ntohl(de->u.unique), "..");

	kunmap_local(block);
	folio_unlock(folio);
	folio_put(folio);
	inode_set_iversion_raw(&vnode->netfs.inode, vnode->status.data_version);

out:
	_leave("");
	return;

invalidated:
	kunmap_local(block);
	folio_unlock(folio);
	folio_put(folio);
	trace_afs_edit_dir(vnode, why, afs_edit_dir_update_inval,
			   0, 0, 0, 0, "..");
	clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
	goto out;

error:
	trace_afs_edit_dir(vnode, why, afs_edit_dir_update_error,
			   0, 0, 0, 0, "..");
	clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
	goto out;
}
+2 −0
Original line number Diff line number Diff line
@@ -1073,6 +1073,8 @@ extern void afs_check_for_remote_deletion(struct afs_operation *);
extern void afs_edit_dir_add(struct afs_vnode *, struct qstr *, struct afs_fid *,
			     enum afs_edit_dir_reason);
extern void afs_edit_dir_remove(struct afs_vnode *, struct qstr *, enum afs_edit_dir_reason);
void afs_edit_dir_update_dotdot(struct afs_vnode *vnode, struct afs_vnode *new_dvnode,
				enum afs_edit_dir_reason why);

/*
 * dir_silly.c
+2 −3
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ static inline void free_dev_ioctl(struct autofs_dev_ioctl *param)
 */
static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
{
	unsigned int inr = _IOC_NR(cmd);
	int err;

	err = check_dev_ioctl_version(cmd, param);
@@ -133,7 +134,7 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
		 * check_name() return for AUTOFS_DEV_IOCTL_TIMEOUT_CMD.
		 */
		err = check_name(param->path);
		if (cmd == AUTOFS_DEV_IOCTL_TIMEOUT_CMD)
		if (inr == AUTOFS_DEV_IOCTL_TIMEOUT_CMD)
			err = err ? 0 : -EINVAL;
		if (err) {
			pr_warn("invalid path supplied for cmd(0x%08x)\n",
@@ -141,8 +142,6 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param)
			goto out;
		}
	} else {
		unsigned int inr = _IOC_NR(cmd);

		if (inr == AUTOFS_DEV_IOCTL_OPENMOUNT_CMD ||
		    inr == AUTOFS_DEV_IOCTL_REQUESTER_CMD ||
		    inr == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD) {
Loading