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

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

Pull vfs fixes from Christian Brauner:

 - Fix unitialized variable in statmount_string()

 - Fix hostfs mounting when passing host root during boot

 - Fix dynamic lookup to fail on cell lookup failure

 - Fix missing file type when reading bfs inodes from disk

 - Enforce checking of sb_min_blocksize() calls and update all callers
   accordingly

 - Restore write access before closing files opened by open_exec() in
   binfmt_misc

 - Always freeze efivarfs during suspend/hibernate cycles

 - Fix statmount()'s and listmount()'s grab_requested_mnt_ns() helper to
   actually allow mount namespace file descriptor in addition to mount
   namespace ids

 - Fix tmpfs remount when noswap is specified

 - Switch Landlock to iput_not_last() to remove false-positives from
   might_sleep() annotations in iput()

 - Remove dead node_to_mnt_ns() code

 - Ensure that per-queue kobjects are successfully created

* tag 'vfs-6.18-rc7.fixes' of gitolite.kernel.org:pub/scm/linux/kernel/git/vfs/vfs:
  landlock: fix splats from iput() after it started calling might_sleep()
  fs: add iput_not_last()
  shmem: fix tmpfs reconfiguration (remount) when noswap is set
  fs/namespace: correctly handle errors returned by grab_requested_mnt_ns
  power: always freeze efivarfs
  binfmt_misc: restore write access before closing files opened by open_exec()
  block: add __must_check attribute to sb_min_blocksize()
  virtio-fs: fix incorrect check for fsvq->kobj
  xfs: check the return value of sb_min_blocksize() in xfs_fs_fill_super
  isofs: check the return value of sb_min_blocksize() in isofs_fill_super
  exfat: check return value of sb_min_blocksize in exfat_read_boot_sector
  vfat: fix missing sb_min_blocksize() return value checks
  mnt: Remove dead code which might prevent from building
  bfs: Reconstruct file type when loading from disk
  afs: Fix dynamic lookup to fail on cell lookup failure
  hostfs: Fix only passing host root in boot stage with new mount
  fs: Fix uninitialized 'offp' in statmount_string()
parents 418592a0 e9d50b78
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -231,7 +231,7 @@ int sb_set_blocksize(struct super_block *sb, int size)

EXPORT_SYMBOL(sb_set_blocksize);

int sb_min_blocksize(struct super_block *sb, int size)
int __must_check sb_min_blocksize(struct super_block *sb, int size)
{
	int minsize = bdev_logical_block_size(sb->s_bdev);
	if (size < minsize)
+66 −12
Original line number Diff line number Diff line
@@ -229,7 +229,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
 * @name:	The name of the cell.
 * @namesz:	The strlen of the cell name.
 * @vllist:	A colon/comma separated list of numeric IP addresses or NULL.
 * @excl:	T if an error should be given if the cell name already exists.
 * @reason:	The reason we're doing the lookup
 * @trace:	The reason to be logged if the lookup is successful.
 *
 * Look up a cell record by name and query the DNS for VL server addresses if
@@ -239,7 +239,8 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
 */
struct afs_cell *afs_lookup_cell(struct afs_net *net,
				 const char *name, unsigned int namesz,
				 const char *vllist, bool excl,
				 const char *vllist,
				 enum afs_lookup_cell_for reason,
				 enum afs_cell_trace trace)
{
	struct afs_cell *cell, *candidate, *cursor;
@@ -247,13 +248,19 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
	enum afs_cell_state state;
	int ret, n;

	_enter("%s,%s", name, vllist);
	_enter("%s,%s,%u", name, vllist, reason);

	if (!excl) {
	if (reason != AFS_LOOKUP_CELL_PRELOAD) {
		cell = afs_find_cell(net, name, namesz, trace);
		if (!IS_ERR(cell))
		if (!IS_ERR(cell)) {
			if (reason == AFS_LOOKUP_CELL_DYNROOT)
				goto no_wait;
			if (cell->state == AFS_CELL_SETTING_UP ||
			    cell->state == AFS_CELL_UNLOOKED)
				goto lookup_cell;
			goto wait_for_cell;
		}
	}

	/* Assume we're probably going to create a cell and preallocate and
	 * mostly set up a candidate record.  We can then use this to stash the
@@ -298,26 +305,69 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
	rb_insert_color(&cell->net_node, &net->cells);
	up_write(&net->cells_lock);

lookup_cell:
	if (reason != AFS_LOOKUP_CELL_PRELOAD &&
	    reason != AFS_LOOKUP_CELL_ROOTCELL) {
		set_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags);
		afs_queue_cell(cell, afs_cell_trace_queue_new);
	}

wait_for_cell:
	_debug("wait_for_cell");
	state = smp_load_acquire(&cell->state); /* vs error */
	if (state != AFS_CELL_ACTIVE &&
	    state != AFS_CELL_DEAD) {
	switch (state) {
	case AFS_CELL_ACTIVE:
	case AFS_CELL_DEAD:
		break;
	case AFS_CELL_UNLOOKED:
	default:
		if (reason == AFS_LOOKUP_CELL_PRELOAD ||
		    reason == AFS_LOOKUP_CELL_ROOTCELL)
			break;
		_debug("wait_for_cell");
		afs_see_cell(cell, afs_cell_trace_wait);
		wait_var_event(&cell->state,
			       ({
				       state = smp_load_acquire(&cell->state); /* vs error */
				       state == AFS_CELL_ACTIVE || state == AFS_CELL_DEAD;
			       }));
		_debug("waited_for_cell %d %d", cell->state, cell->error);
	}

no_wait:
	/* Check the state obtained from the wait check. */
	state = smp_load_acquire(&cell->state); /* vs error */
	if (state == AFS_CELL_DEAD) {
		ret = cell->error;
		goto error;
	}
	if (state == AFS_CELL_ACTIVE) {
		switch (cell->dns_status) {
		case DNS_LOOKUP_NOT_DONE:
			if (cell->dns_source == DNS_RECORD_FROM_CONFIG) {
				ret = 0;
				break;
			}
			fallthrough;
		default:
			ret = -EIO;
			goto error;
		case DNS_LOOKUP_GOOD:
		case DNS_LOOKUP_GOOD_WITH_BAD:
			ret = 0;
			break;
		case DNS_LOOKUP_GOT_NOT_FOUND:
			ret = -ENOENT;
			goto error;
		case DNS_LOOKUP_BAD:
			ret = -EREMOTEIO;
			goto error;
		case DNS_LOOKUP_GOT_LOCAL_FAILURE:
		case DNS_LOOKUP_GOT_TEMP_FAILURE:
		case DNS_LOOKUP_GOT_NS_FAILURE:
			ret = -EDESTADDRREQ;
			goto error;
		}
	}

	_leave(" = %p [cell]", cell);
	return cell;
@@ -325,7 +375,7 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
cell_already_exists:
	_debug("cell exists");
	cell = cursor;
	if (excl) {
	if (reason == AFS_LOOKUP_CELL_PRELOAD) {
		ret = -EEXIST;
	} else {
		afs_use_cell(cursor, trace);
@@ -384,7 +434,8 @@ int afs_cell_init(struct afs_net *net, const char *rootcell)
		return -EINVAL;

	/* allocate a cell record for the root/workstation cell */
	new_root = afs_lookup_cell(net, rootcell, len, vllist, false,
	new_root = afs_lookup_cell(net, rootcell, len, vllist,
				   AFS_LOOKUP_CELL_ROOTCELL,
				   afs_cell_trace_use_lookup_ws);
	if (IS_ERR(new_root)) {
		_leave(" = %ld", PTR_ERR(new_root));
@@ -777,6 +828,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
	switch (cell->state) {
	case AFS_CELL_SETTING_UP:
		goto set_up_cell;
	case AFS_CELL_UNLOOKED:
	case AFS_CELL_ACTIVE:
		goto cell_is_active;
	case AFS_CELL_REMOVING:
@@ -797,7 +849,7 @@ static bool afs_manage_cell(struct afs_cell *cell)
		goto remove_cell;
	}

	afs_set_cell_state(cell, AFS_CELL_ACTIVE);
	afs_set_cell_state(cell, AFS_CELL_UNLOOKED);

cell_is_active:
	if (afs_has_cell_expired(cell, &next_manage))
@@ -807,6 +859,8 @@ static bool afs_manage_cell(struct afs_cell *cell)
		ret = afs_update_cell(cell);
		if (ret < 0)
			cell->error = ret;
		if (cell->state == AFS_CELL_UNLOOKED)
			afs_set_cell_state(cell, AFS_CELL_ACTIVE);
	}

	if (next_manage < TIME64_MAX && cell->net->live) {
+2 −1
Original line number Diff line number Diff line
@@ -108,7 +108,8 @@ static struct dentry *afs_dynroot_lookup_cell(struct inode *dir, struct dentry *
		dotted = true;
	}

	cell = afs_lookup_cell(net, name, len, NULL, false,
	cell = afs_lookup_cell(net, name, len, NULL,
			       AFS_LOOKUP_CELL_DYNROOT,
			       afs_cell_trace_use_lookup_dynroot);
	if (IS_ERR(cell)) {
		ret = PTR_ERR(cell);
+11 −1
Original line number Diff line number Diff line
@@ -343,6 +343,7 @@ extern const char afs_init_sysname[];

enum afs_cell_state {
	AFS_CELL_SETTING_UP,
	AFS_CELL_UNLOOKED,
	AFS_CELL_ACTIVE,
	AFS_CELL_REMOVING,
	AFS_CELL_DEAD,
@@ -1049,9 +1050,18 @@ static inline bool afs_cb_is_broken(unsigned int cb_break,
extern int afs_cell_init(struct afs_net *, const char *);
extern struct afs_cell *afs_find_cell(struct afs_net *, const char *, unsigned,
				      enum afs_cell_trace);
enum afs_lookup_cell_for {
	AFS_LOOKUP_CELL_DYNROOT,
	AFS_LOOKUP_CELL_MOUNTPOINT,
	AFS_LOOKUP_CELL_DIRECT_MOUNT,
	AFS_LOOKUP_CELL_PRELOAD,
	AFS_LOOKUP_CELL_ROOTCELL,
	AFS_LOOKUP_CELL_ALIAS_CHECK,
};
struct afs_cell *afs_lookup_cell(struct afs_net *net,
				 const char *name, unsigned int namesz,
				 const char *vllist, bool excl,
				 const char *vllist,
				 enum afs_lookup_cell_for reason,
				 enum afs_cell_trace trace);
extern struct afs_cell *afs_use_cell(struct afs_cell *, enum afs_cell_trace);
void afs_unuse_cell(struct afs_cell *cell, enum afs_cell_trace reason);
+2 −1
Original line number Diff line number Diff line
@@ -107,7 +107,8 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
		if (size > AFS_MAXCELLNAME)
			return -ENAMETOOLONG;

		cell = afs_lookup_cell(ctx->net, p, size, NULL, false,
		cell = afs_lookup_cell(ctx->net, p, size, NULL,
				       AFS_LOOKUP_CELL_MOUNTPOINT,
				       afs_cell_trace_use_lookup_mntpt);
		if (IS_ERR(cell)) {
			pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
Loading