diff options
Diffstat (limited to 'fs/afs/rotate.c')
-rw-r--r-- | fs/afs/rotate.c | 128 |
1 files changed, 20 insertions, 108 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index d67b8c7eb3b9..8d5473cd8ea4 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -21,7 +21,8 @@ static bool afs_start_fs_iteration(struct afs_operation *op, struct afs_vnode *vnode) { - struct afs_cb_interest *cbi; + struct afs_server *server; + void *cb_server; int i; read_lock(&op->volume->servers_lock); @@ -33,12 +34,12 @@ static bool afs_start_fs_iteration(struct afs_operation *op, op->untried = (1UL << op->server_list->nr_servers) - 1; op->index = READ_ONCE(op->server_list->preferred); - cbi = rcu_dereference_protected(vnode->cb_interest, - lockdep_is_held(&vnode->io_lock)); - if (cbi) { + cb_server = vnode->cb_server; + if (cb_server) { /* See if the vnode's preferred record is still available */ for (i = 0; i < op->server_list->nr_servers; i++) { - if (op->server_list->servers[i].cb_interest == cbi) { + server = op->server_list->servers[i].server; + if (server == cb_server) { op->index = i; goto found_interest; } @@ -55,14 +56,11 @@ static bool afs_start_fs_iteration(struct afs_operation *op, /* Note that the callback promise is effectively broken */ write_seqlock(&vnode->cb_lock); - ASSERTCMP(cbi, ==, rcu_access_pointer(vnode->cb_interest)); - rcu_assign_pointer(vnode->cb_interest, NULL); + ASSERTCMP(cb_server, ==, vnode->cb_server); + vnode->cb_server = NULL; if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) vnode->cb_break++; write_sequnlock(&vnode->cb_lock); - - afs_put_cb_interest(op->net, cbi); - cbi = NULL; } found_interest: @@ -303,8 +301,7 @@ bool afs_select_fileserver(struct afs_operation *op) restart_from_beginning: _debug("restart"); afs_end_cursor(&op->ac); - afs_put_cb_interest(op->net, op->cbi); - op->cbi = NULL; + op->server = NULL; afs_put_serverlist(op->net, op->server_list); op->server_list = NULL; start: @@ -331,13 +328,12 @@ pick_server: /* Pick the untried server with the lowest RTT. If we have outstanding * callbacks, we stick with the server we're already using if we can. */ - if (op->cbi) { - _debug("cbi %u", op->index); + if (op->server) { + _debug("server %u", op->index); if (test_bit(op->index, &op->untried)) goto selected_server; - afs_put_cb_interest(op->net, op->cbi); - op->cbi = NULL; - _debug("nocbi"); + op->server = NULL; + _debug("no server"); } op->index = -1; @@ -372,19 +368,13 @@ selected_server: _debug("USING SERVER: %pU", &server->uuid); - /* Make sure we've got a callback interest record for this server. We - * have to link it in before we send the request as we can be sent a - * break request before we've finished decoding the reply and - * installing the vnode. - */ - error = afs_register_server_cb_interest(vnode, op->server_list, - op->index); - if (error < 0) - goto failed_set_error; - - op->cbi = afs_get_cb_interest( - rcu_dereference_protected(vnode->cb_interest, - lockdep_is_held(&vnode->io_lock))); + op->server = server; + if (vnode->cb_server != server) { + vnode->cb_server = server; + vnode->cb_s_break = server->cb_s_break; + vnode->cb_v_break = vnode->volume->cb_v_break; + clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); + } read_lock(&server->fs_lock); alist = rcu_dereference_protected(server->addresses, @@ -447,84 +437,6 @@ failed: } /* - * Select the same fileserver we used for a vnode before and only that - * fileserver. We use this when we have a lock on that file, which is backed - * only by the fileserver we obtained it from. - */ -bool afs_select_current_fileserver(struct afs_operation *op) -{ - struct afs_cb_interest *cbi; - struct afs_addr_list *alist; - int error = op->ac.error; - - _enter(""); - - switch (error) { - case SHRT_MAX: - cbi = op->cbi; - if (!cbi) { - op->error = -ESTALE; - op->flags |= AFS_OPERATION_STOP; - return false; - } - - read_lock(&cbi->server->fs_lock); - alist = rcu_dereference_protected(cbi->server->addresses, - lockdep_is_held(&cbi->server->fs_lock)); - afs_get_addrlist(alist); - read_unlock(&cbi->server->fs_lock); - if (!alist) { - op->error = -ESTALE; - op->flags |= AFS_OPERATION_STOP; - return false; - } - - memset(&op->ac, 0, sizeof(op->ac)); - op->ac.alist = alist; - op->ac.index = -1; - goto iterate_address; - - case 0: - default: - /* Success or local failure. Stop. */ - op->error = error; - op->flags |= AFS_OPERATION_STOP; - _leave(" = f [okay/local %d]", error); - return false; - - case -ECONNABORTED: - op->error = afs_abort_to_error(op->ac.abort_code); - op->flags |= AFS_OPERATION_STOP; - _leave(" = f [abort]"); - return false; - - case -ERFKILL: - case -EADDRNOTAVAIL: - case -ENETUNREACH: - case -EHOSTUNREACH: - case -EHOSTDOWN: - case -ECONNREFUSED: - case -ETIMEDOUT: - case -ETIME: - _debug("no conn"); - op->error = error; - goto iterate_address; - } - -iterate_address: - /* Iterate over the current server's address list to try and find an - * address on which it will respond to us. - */ - if (afs_iterate_addresses(&op->ac)) { - _leave(" = t"); - return true; - } - - afs_end_cursor(&op->ac); - return false; -} - -/* * Dump cursor state in the case of the error being EDESTADDRREQ. */ void afs_dump_edestaddrreq(const struct afs_operation *op) |