Commit 445f9b69 authored by David Howells's avatar David Howells
Browse files

afs: Defer volume record destruction to a workqueue



Defer volume record destruction to a workqueue so that afs_put_volume()
isn't going to run the destruction process in the callback workqueue whilst
the server is holding up other clients whilst waiting for us to reply to a
CB.CallBack notification RPC.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
parent ca0e79a4
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -818,7 +818,7 @@ static void afs_manage_cell(struct afs_cell *cell)

final_destruction:
	/* The root volume is pinning the cell */
	afs_put_volume(cell->net, cell->root_volume, afs_volume_trace_put_cell_root);
	afs_put_volume(cell->root_volume, afs_volume_trace_put_cell_root);
	cell->root_volume = NULL;
	afs_put_cell(cell, afs_cell_trace_put_destroy);
}
+1 −1
Original line number Diff line number Diff line
@@ -265,7 +265,7 @@ int afs_put_operation(struct afs_operation *op)
	}

	afs_put_serverlist(op->net, op->server_list);
	afs_put_volume(op->net, op->volume, afs_volume_trace_put_put_op);
	afs_put_volume(op->volume, afs_volume_trace_put_put_op);
	key_put(op->key);
	kfree(op);
	return ret;
+2 −1
Original line number Diff line number Diff line
@@ -636,6 +636,7 @@ struct afs_volume {
	struct rb_node		cell_node;	/* Link in cell->volumes */
	struct hlist_node	proc_link;	/* Link in cell->proc_volumes */
	struct super_block __rcu *sb;		/* Superblock on which inodes reside */
	struct work_struct	destructor;	/* Deferred destructor */
	unsigned long		flags;
#define AFS_VOLUME_NEEDS_UPDATE	0	/* - T if an update needs performing */
#define AFS_VOLUME_UPDATING	1	/* - T if an update is in progress */
@@ -1613,7 +1614,7 @@ extern int afs_activate_volume(struct afs_volume *);
extern void afs_deactivate_volume(struct afs_volume *);
bool afs_try_get_volume(struct afs_volume *volume, enum afs_volume_trace reason);
extern struct afs_volume *afs_get_volume(struct afs_volume *, enum afs_volume_trace);
extern void afs_put_volume(struct afs_net *, struct afs_volume *, enum afs_volume_trace);
void afs_put_volume(struct afs_volume *volume, enum afs_volume_trace reason);
extern int afs_check_volume_status(struct afs_volume *, struct afs_operation *);

/*
+3 −4
Original line number Diff line number Diff line
@@ -381,8 +381,7 @@ static int afs_validate_fc(struct fs_context *fc)
		ctx->key = key;

		if (ctx->volume) {
			afs_put_volume(ctx->net, ctx->volume,
				       afs_volume_trace_put_validate_fc);
			afs_put_volume(ctx->volume, afs_volume_trace_put_validate_fc);
			ctx->volume = NULL;
		}

@@ -529,7 +528,7 @@ static void afs_destroy_sbi(struct afs_super_info *as)
{
	if (as) {
		struct afs_net *net = afs_net(as->net_ns);
		afs_put_volume(net, as->volume, afs_volume_trace_put_destroy_sbi);
		afs_put_volume(as->volume, afs_volume_trace_put_destroy_sbi);
		afs_unuse_cell(net, as->cell, afs_cell_trace_unuse_sbi);
		put_net(as->net_ns);
		kfree(as);
@@ -615,7 +614,7 @@ static void afs_free_fc(struct fs_context *fc)
	struct afs_fs_context *ctx = fc->fs_private;

	afs_destroy_sbi(fc->s_fs_info);
	afs_put_volume(ctx->net, ctx->volume, afs_volume_trace_put_free_fc);
	afs_put_volume(ctx->volume, afs_volume_trace_put_free_fc);
	afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_fc);
	key_put(ctx->key);
	kfree(ctx);
+3 −3
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
	/* And see if it's in the new cell. */
	volume = afs_sample_volume(cell, key, pvol->name, pvol->name_len);
	if (IS_ERR(volume)) {
		afs_put_volume(cell->net, pvol, afs_volume_trace_put_query_alias);
		afs_put_volume(pvol, afs_volume_trace_put_query_alias);
		if (PTR_ERR(volume) != -ENOMEDIUM)
			return PTR_ERR(volume);
		/* That volume is not in the new cell, so not an alias */
@@ -174,8 +174,8 @@ static int afs_query_for_alias_one(struct afs_cell *cell, struct key *key,
		rcu_read_unlock();
	}

	afs_put_volume(cell->net, volume, afs_volume_trace_put_query_alias);
	afs_put_volume(cell->net, pvol, afs_volume_trace_put_query_alias);
	afs_put_volume(volume, afs_volume_trace_put_query_alias);
	afs_put_volume(pvol, afs_volume_trace_put_query_alias);
	return ret;
}

Loading