Commit f2686b09 authored by David Howells's avatar David Howells

afs: Fix giving up callbacks on server destruction

When a server record is destroyed, we want to send a message to the server
telling it that we're giving up all the callbacks it has promised us.

Apply two fixes to this:

 (1) Only send the FS.GiveUpAllCallBacks message if we actually got a
     callback from that server.  We assume this to be the case if we
     performed at least one successful FS operation on that server.

 (2) Send it to the address last used for that server rather than always
     picking the first address in the list (which might be unreachable).

Fixes: d2ddc776 ("afs: Overhaul volume and server record caching and fileserver rotation")
Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 01fd79e6
...@@ -396,6 +396,7 @@ struct afs_server { ...@@ -396,6 +396,7 @@ struct afs_server {
#define AFS_SERVER_FL_PROBED 5 /* The fileserver has been probed */ #define AFS_SERVER_FL_PROBED 5 /* The fileserver has been probed */
#define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */ #define AFS_SERVER_FL_PROBING 6 /* Fileserver is being probed */
#define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */ #define AFS_SERVER_FL_NO_IBULK 7 /* Fileserver doesn't support FS.InlineBulkStatus */
#define AFS_SERVER_FL_MAY_HAVE_CB 8 /* May have callbacks on this fileserver */
atomic_t usage; atomic_t usage;
u32 addr_version; /* Address list version */ u32 addr_version; /* Address list version */
......
...@@ -482,8 +482,12 @@ static void afs_deliver_to_call(struct afs_call *call) ...@@ -482,8 +482,12 @@ static void afs_deliver_to_call(struct afs_call *call)
state = READ_ONCE(call->state); state = READ_ONCE(call->state);
switch (ret) { switch (ret) {
case 0: case 0:
if (state == AFS_CALL_CL_PROC_REPLY) if (state == AFS_CALL_CL_PROC_REPLY) {
if (call->cbi)
set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
&call->cbi->server->flags);
goto call_complete; goto call_complete;
}
ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY); ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
goto done; goto done;
case -EINPROGRESS: case -EINPROGRESS:
......
...@@ -395,14 +395,16 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server) ...@@ -395,14 +395,16 @@ static void afs_destroy_server(struct afs_net *net, struct afs_server *server)
struct afs_addr_list *alist = rcu_access_pointer(server->addresses); struct afs_addr_list *alist = rcu_access_pointer(server->addresses);
struct afs_addr_cursor ac = { struct afs_addr_cursor ac = {
.alist = alist, .alist = alist,
.addr = &alist->addrs[0],
.start = alist->index, .start = alist->index,
.index = alist->index, .index = 0,
.addr = &alist->addrs[alist->index],
.error = 0, .error = 0,
}; };
_enter("%p", server); _enter("%p", server);
if (test_bit(AFS_SERVER_FL_MAY_HAVE_CB, &server->flags))
afs_fs_give_up_all_callbacks(net, server, &ac, NULL); afs_fs_give_up_all_callbacks(net, server, &ac, NULL);
call_rcu(&server->rcu, afs_server_rcu); call_rcu(&server->rcu, afs_server_rcu);
afs_dec_servers_outstanding(net); afs_dec_servers_outstanding(net);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment