Skip to content

Commit

Permalink
afs: Split the usage count on struct afs_server
Browse files Browse the repository at this point in the history
Split the usage count on the afs_server struct to have an active count that
registers who's actually using it separately from the reference count on
the object.

This allows a future patch to dispatch polling probes without advancing the
"unuse" time into the future each time we emit a probe, which would
otherwise prevent unused server records from expiring.

Included in this:

 (1) The latter part of afs_destroy_server() in which the RCU destruction
     of afs_server objects is invoked and the outstanding server count is
     decremented is split out into __afs_put_server().

 (2) afs_put_server() now calls __afs_put_server() rather then setting the
     management timer.

 (3) The calls begun by afs_fs_give_up_all_callbacks() and
     afs_fs_get_capabilities() can now take a ref on the server record, so
     afs_destroy_server() can just drop its ref and needn't wait for the
     completion of these calls.  They'll put the ref when they're done.

 (4) Because of (3), afs_fs_probe_done() no longer needs to wake up
     afs_destroy_server() with server->probe_outstanding.

 (5) afs_gc_servers can be simplified.  It only needs to check if
     server->active is 0 rather than playing games with the refcount.

 (6) afs_manage_servers() can propose a server for gc if usage == 0 rather
     than if ref == 1.  The gc is effected by (5).

Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed May 31, 2020
1 parent 8100680 commit 977e5f8
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 71 deletions.
4 changes: 3 additions & 1 deletion fs/afs/cmservice.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,9 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
* to maintain cache coherency.
*/
if (call->server) {
trace_afs_server(call->server, atomic_read(&call->server->usage),
trace_afs_server(call->server,
atomic_read(&call->server->ref),
atomic_read(&call->server->active),
afs_server_trace_callback);
afs_break_callbacks(call->server, call->count, call->request);
}
Expand Down
1 change: 0 additions & 1 deletion fs/afs/fs_probe.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ static bool afs_fs_probe_done(struct afs_server *server)
if (!atomic_dec_and_test(&server->probe_outstanding))
return false;

wake_up_var(&server->probe_outstanding);
clear_bit_unlock(AFS_SERVER_FL_PROBING, &server->flags);
wake_up_bit(&server->flags, AFS_SERVER_FL_PROBING);
return true;
Expand Down
5 changes: 2 additions & 3 deletions fs/afs/fsclient.c
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,7 @@ int afs_fs_give_up_all_callbacks(struct afs_net *net,
bp = call->request;
*bp++ = htonl(FSGIVEUPALLCALLBACKS);

/* Can't take a ref on server */
call->server = afs_use_server(server, afs_server_trace_give_up_cb);
afs_make_call(ac, call, GFP_NOFS);
return afs_wait_for_call_to_complete(call, ac);
}
Expand Down Expand Up @@ -1924,7 +1924,7 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
return ERR_PTR(-ENOMEM);

call->key = key;
call->server = afs_get_server(server, afs_server_trace_get_caps);
call->server = afs_use_server(server, afs_server_trace_get_caps);
call->server_index = server_index;
call->upgrade = true;
call->async = true;
Expand All @@ -1934,7 +1934,6 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net,
bp = call->request;
*bp++ = htonl(FSGETCAPABILITIES);

/* Can't take a ref on server */
trace_afs_make_fs_call(call, NULL);
afs_make_call(ac, call, GFP_NOFS);
return call;
Expand Down
8 changes: 6 additions & 2 deletions fs/afs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ struct afs_server {
struct hlist_node addr6_link; /* Link in net->fs_addresses6 */
struct hlist_node proc_link; /* Link in net->fs_proc */
struct afs_server *gc_next; /* Next server in manager's list */
time64_t put_time; /* Time at which last put */
time64_t unuse_time; /* Time at which last unused */
unsigned long flags;
#define AFS_SERVER_FL_NOT_READY 1 /* The record is not ready for use */
#define AFS_SERVER_FL_NOT_FOUND 2 /* VL server says no such server */
Expand All @@ -512,7 +512,8 @@ struct afs_server {
#define AFS_SERVER_FL_NO_RM2 10 /* Fileserver doesn't support YFS.RemoveFile2 */
#define AFS_SERVER_FL_HAVE_EPOCH 11 /* ->epoch is valid */
#define AFS_SERVER_FL_NEEDS_UPDATE 12 /* Fileserver address list is out of date */
atomic_t usage;
atomic_t ref; /* Object refcount */
atomic_t active; /* Active user count */
u32 addr_version; /* Address list version */
u32 cm_epoch; /* Server RxRPC epoch */
unsigned int debug_id; /* Debugging ID for traces */
Expand Down Expand Up @@ -1244,6 +1245,9 @@ extern struct afs_server *afs_find_server(struct afs_net *,
extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *, u32);
extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
extern struct afs_server *afs_use_server(struct afs_server *, enum afs_server_trace);
extern void afs_unuse_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
extern void afs_unuse_server_notime(struct afs_net *, struct afs_server *, enum afs_server_trace);
extern void afs_put_server(struct afs_net *, struct afs_server *, enum afs_server_trace);
extern void afs_manage_servers(struct work_struct *);
extern void afs_servers_timer(struct timer_list *);
Expand Down
9 changes: 5 additions & 4 deletions fs/afs/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,19 +378,20 @@ static int afs_proc_servers_show(struct seq_file *m, void *v)
int i;

if (v == SEQ_START_TOKEN) {
seq_puts(m, "UUID USE ADDR\n");
seq_puts(m, "UUID REF ACT ADDR\n");
return 0;
}

server = list_entry(v, struct afs_server, proc_link);
alist = rcu_dereference(server->addresses);
seq_printf(m, "%pU %3d %pISpc%s\n",
seq_printf(m, "%pU %3d %3d %pISpc%s\n",
&server->uuid,
atomic_read(&server->usage),
atomic_read(&server->ref),
atomic_read(&server->active),
&alist->addrs[0].transport,
alist->preferred == 0 ? "*" : "");
for (i = 1; i < alist->nr_addrs; i++)
seq_printf(m, " %pISpc%s\n",
seq_printf(m, " %pISpc%s\n",
&alist->addrs[i].transport,
alist->preferred == i ? "*" : "");
return 0;
Expand Down
2 changes: 1 addition & 1 deletion fs/afs/rxrpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ void afs_put_call(struct afs_call *call)
if (call->type->destructor)
call->type->destructor(call);

afs_put_server(call->net, call->server, afs_server_trace_put_call);
afs_unuse_server_notime(call->net, call->server, afs_server_trace_put_call);
afs_put_cb_interest(call->net, call->cbi);
afs_put_addrlist(call->alist);
kfree(call->request);
Expand Down
Loading

0 comments on commit 977e5f8

Please sign in to comment.