Commit 0a7b0ace authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull vfs fixes from Christian Brauner:
 "This contains a few small fixes for this merge window:

   - Undo the hiding of silly-rename files in afs. If they're hidden
     they can't be deleted by rm manually anymore causing regressions

   - Avoid caching the preferred address for an afs server to avoid
     accidently overriding an explicitly specified preferred server
     address

   - Fix bad stat() and rmdir() interaction in afs

   - Take a passive reference on the superblock when opening a block
     device so the holder is available to concurrent callers from the
     block layer

   - Clear private data pointer in fscache_begin_operation() to avoid it
     being falsely treated as valid"

* tag 'vfs-6.9-rc1.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
  fscache: Fix error handling in fscache_begin_operation()
  fs,block: get holder during claim
  afs: Fix occasional rmdir-then-VNOVNODE with generic/011
  afs: Don't cache preferred address
  afs: Revert "afs: Hide silly-rename files from userspace"
parents 4ae3dc83 449ac551
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -583,6 +583,9 @@ static void bd_finish_claiming(struct block_device *bdev, void *holder,
	mutex_unlock(&bdev->bd_holder_lock);
	bd_clear_claiming(whole, holder);
	mutex_unlock(&bdev_lock);

	if (hops && hops->get_holder)
		hops->get_holder(holder);
}

/**
@@ -605,6 +608,7 @@ EXPORT_SYMBOL(bd_abort_claiming);
static void bd_end_claim(struct block_device *bdev, void *holder)
{
	struct block_device *whole = bdev_whole(bdev);
	const struct blk_holder_ops *hops = bdev->bd_holder_ops;
	bool unblock = false;

	/*
@@ -627,6 +631,9 @@ static void bd_end_claim(struct block_device *bdev, void *holder)
		whole->bd_holder = NULL;
	mutex_unlock(&bdev_lock);

	if (hops && hops->put_holder)
		hops->put_holder(holder);

	/*
	 * If this was the last claim, remove holder link and unblock evpoll if
	 * it was a write holder.
+0 −10
Original line number Diff line number Diff line
@@ -474,16 +474,6 @@ static int afs_dir_iterate_block(struct afs_vnode *dvnode,
			continue;
		}

		/* Don't expose silly rename entries to userspace. */
		if (nlen > 6 &&
		    dire->u.name[0] == '.' &&
		    ctx->actor != afs_lookup_filldir &&
		    ctx->actor != afs_lookup_one_filldir &&
		    memcmp(dire->u.name, ".__afs", 6) == 0) {
			ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
			continue;
		}

		/* found the next entry */
		if (!dir_emit(ctx, dire->u.name, nlen,
			      ntohl(dire->u.vnode),
+4 −17
Original line number Diff line number Diff line
@@ -602,6 +602,8 @@ bool afs_select_fileserver(struct afs_operation *op)
		goto wait_for_more_probe_results;

	alist = op->estate->addresses;
	best_prio = -1;
	addr_index = 0;
	for (i = 0; i < alist->nr_addrs; i++) {
		if (alist->addrs[i].prio > best_prio) {
			addr_index = i;
@@ -609,9 +611,7 @@ bool afs_select_fileserver(struct afs_operation *op)
		}
	}

	addr_index = READ_ONCE(alist->preferred);
	if (!test_bit(addr_index, &set))
		addr_index = __ffs(set);
	alist->preferred = addr_index;

	op->addr_index = addr_index;
	set_bit(addr_index, &op->addr_tried);
@@ -656,12 +656,6 @@ bool afs_select_fileserver(struct afs_operation *op)
next_server:
	trace_afs_rotate(op, afs_rotate_trace_next_server, 0);
	_debug("next");
	ASSERT(op->estate);
	alist = op->estate->addresses;
	if (op->call_responded &&
	    op->addr_index != READ_ONCE(alist->preferred) &&
	    test_bit(alist->preferred, &op->addr_tried))
		WRITE_ONCE(alist->preferred, op->addr_index);
	op->estate = NULL;
	goto pick_server;

@@ -690,14 +684,7 @@ bool afs_select_fileserver(struct afs_operation *op)
failed:
	trace_afs_rotate(op, afs_rotate_trace_failed, 0);
	op->flags |= AFS_OPERATION_STOP;
	if (op->estate) {
		alist = op->estate->addresses;
		if (op->call_responded &&
		    op->addr_index != READ_ONCE(alist->preferred) &&
		    test_bit(alist->preferred, &op->addr_tried))
			WRITE_ONCE(alist->preferred, op->addr_index);
	op->estate = NULL;
	}
	_leave(" = f [failed %d]", afs_op_error(op));
	return false;
}
+9 −7
Original line number Diff line number Diff line
@@ -122,6 +122,9 @@ bool afs_check_validity(const struct afs_vnode *vnode)
	const struct afs_volume *volume = vnode->volume;
	time64_t deadline = ktime_get_real_seconds() + 10;

	if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
		return true;

	if (atomic_read(&volume->cb_v_check) != atomic_read(&volume->cb_v_break) ||
	    atomic64_read(&vnode->cb_expires_at)  <= deadline ||
	    volume->cb_expires_at <= deadline ||
@@ -389,12 +392,17 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
	       key_serial(key));

	if (afs_check_validity(vnode))
		return 0;
		return test_bit(AFS_VNODE_DELETED, &vnode->flags) ? -ESTALE : 0;

	ret = down_write_killable(&vnode->validate_lock);
	if (ret < 0)
		goto error;

	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
		ret = -ESTALE;
		goto error_unlock;
	}

	/* Validate a volume after the v_break has changed or the volume
	 * callback expired.  We only want to do this once per volume per
	 * v_break change.  The actual work will be done when parsing the
@@ -448,12 +456,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
	vnode->cb_ro_snapshot = cb_ro_snapshot;
	vnode->cb_scrub = cb_scrub;

	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
		_debug("file already deleted");
		ret = -ESTALE;
		goto error_unlock;
	}

	/* if the vnode's data version number changed then its contents are
	 * different */
	zap |= test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags);
+3 −1
Original line number Diff line number Diff line
@@ -83,8 +83,10 @@ static int fscache_begin_operation(struct netfs_cache_resources *cres,
	cres->debug_id		= cookie->debug_id;
	cres->inval_counter	= cookie->inval_counter;

	if (!fscache_begin_cookie_access(cookie, why))
	if (!fscache_begin_cookie_access(cookie, why)) {
		cres->cache_priv = NULL;
		return -ENOBUFS;
	}

again:
	spin_lock(&cookie->lock);
Loading