summaryrefslogtreecommitdiff
path: root/fs/afs/rotate.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-02-08 12:12:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2018-02-08 12:12:04 -0800
commit81153336eb76b253ba7852f3f1de525bb98f8c4d (patch)
tree635fe0495b762841eb72e5ee40d9d88563674691 /fs/afs/rotate.c
parentef9417e8a903d3a68a83ea2da32f1db030341c37 (diff)
parent4d673da14533b32fe8d3125b5b7be4fea14e39a8 (diff)
Merge tag 'afs-next-20180208' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull afs updates from David Howells: "Four fixes: - add a missing put - two fixes to reset the address iteration cursor correctly - fix setting up the fileserver iteration cursor. Two cleanups: - remove some dead code - rearrange a function to be more logically laid out And one new feature: - Support AFS dynamic root. With this one should be able to do, say: mkdir /afs mount -t afs none /afs -o dyn to create a dynamic root and then, provided you have keyutils installed, do: ls /afs/grand.central.org and: ls /afs/umich.edu to list the root volumes of both those organisations' AFS cells without requiring any other setup (the kernel upcall to a program in the keyutils package to do DNS access as does NFS)" * tag 'afs-next-20180208' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Support the AFS dynamic root afs: Rearrange afs_select_fileserver() a little afs: Remove unused code afs: Fix server list handling afs: Need to clear responded flag in addr cursor afs: Fix missing cursor clearance afs: Add missing afs_put_cell()
Diffstat (limited to 'fs/afs/rotate.c')
-rw-r--r--fs/afs/rotate.c293
1 files changed, 26 insertions, 267 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c
index d04511fb3879..ad1328d85526 100644
--- a/fs/afs/rotate.c
+++ b/fs/afs/rotate.c
@@ -330,26 +330,6 @@ start:
if (!afs_start_fs_iteration(fc, vnode))
goto failed;
- goto use_server;
-
-next_server:
- _debug("next");
- afs_put_cb_interest(afs_v2net(vnode), fc->cbi);
- fc->cbi = NULL;
- fc->index++;
- if (fc->index >= fc->server_list->nr_servers)
- fc->index = 0;
- if (fc->index != fc->start)
- goto use_server;
-
- /* That's all the servers poked to no good effect. Try again if some
- * of them were busy.
- */
- if (fc->flags & AFS_FS_CURSOR_VBUSY)
- goto restart_from_beginning;
-
- fc->ac.error = -EDESTADDRREQ;
- goto failed;
use_server:
_debug("use");
@@ -383,6 +363,7 @@ use_server:
afs_get_addrlist(alist);
read_unlock(&server->fs_lock);
+ memset(&fc->ac, 0, sizeof(fc->ac));
/* Probe the current fileserver if we haven't done so yet. */
if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) {
@@ -397,12 +378,8 @@ use_server:
else
afs_put_addrlist(alist);
- fc->ac.addr = NULL;
fc->ac.start = READ_ONCE(alist->index);
fc->ac.index = fc->ac.start;
- fc->ac.error = 0;
- fc->ac.begun = false;
- goto iterate_address;
iterate_address:
ASSERT(fc->ac.alist);
@@ -410,16 +387,35 @@ 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(&fc->ac)) {
- _leave(" = t");
- return true;
- }
+ if (!afs_iterate_addresses(&fc->ac))
+ goto next_server;
+
+ _leave(" = t");
+ return true;
+next_server:
+ _debug("next");
afs_end_cursor(&fc->ac);
- goto next_server;
+ afs_put_cb_interest(afs_v2net(vnode), fc->cbi);
+ fc->cbi = NULL;
+ fc->index++;
+ if (fc->index >= fc->server_list->nr_servers)
+ fc->index = 0;
+ if (fc->index != fc->start)
+ goto use_server;
+
+ /* That's all the servers poked to no good effect. Try again if some
+ * of them were busy.
+ */
+ if (fc->flags & AFS_FS_CURSOR_VBUSY)
+ goto restart_from_beginning;
+
+ fc->ac.error = -EDESTADDRREQ;
+ goto failed;
failed:
fc->flags |= AFS_FS_CURSOR_STOP;
+ afs_end_cursor(&fc->ac);
_leave(" = f [failed %d]", fc->ac.error);
return false;
}
@@ -458,12 +454,10 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)
return false;
}
+ memset(&fc->ac, 0, sizeof(fc->ac));
fc->ac.alist = alist;
- fc->ac.addr = NULL;
fc->ac.start = READ_ONCE(alist->index);
fc->ac.index = fc->ac.start;
- fc->ac.error = 0;
- fc->ac.begun = false;
goto iterate_address;
case 0:
@@ -520,238 +514,3 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc)
return fc->ac.error;
}
-
-#if 0
-/*
- * Set a filesystem server cursor for using a specific FS server.
- */
-int afs_set_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode)
-{
- afs_init_fs_cursor(fc, vnode);
-
- read_seqlock_excl(&vnode->cb_lock);
- if (vnode->cb_interest) {
- if (vnode->cb_interest->server->fs_state == 0)
- fc->server = afs_get_server(vnode->cb_interest->server);
- else
- fc->ac.error = vnode->cb_interest->server->fs_state;
- } else {
- fc->ac.error = -ESTALE;
- }
- read_sequnlock_excl(&vnode->cb_lock);
-
- return fc->ac.error;
-}
-
-/*
- * pick a server to use to try accessing this volume
- * - returns with an elevated usage count on the server chosen
- */
-bool afs_volume_pick_fileserver(struct afs_fs_cursor *fc, struct afs_vnode *vnode)
-{
- struct afs_volume *volume = vnode->volume;
- struct afs_server *server;
- int ret, state, loop;
-
- _enter("%s", volume->vlocation->vldb.name);
-
- /* stick with the server we're already using if we can */
- if (vnode->cb_interest && vnode->cb_interest->server->fs_state == 0) {
- fc->server = afs_get_server(vnode->cb_interest->server);
- goto set_server;
- }
-
- down_read(&volume->server_sem);
-
- /* handle the no-server case */
- if (volume->nservers == 0) {
- fc->ac.error = volume->rjservers ? -ENOMEDIUM : -ESTALE;
- up_read(&volume->server_sem);
- _leave(" = f [no servers %d]", fc->ac.error);
- return false;
- }
-
- /* basically, just search the list for the first live server and use
- * that */
- ret = 0;
- for (loop = 0; loop < volume->nservers; loop++) {
- server = volume->servers[loop];
- state = server->fs_state;
-
- _debug("consider %d [%d]", loop, state);
-
- switch (state) {
- case 0:
- goto picked_server;
-
- case -ENETUNREACH:
- if (ret == 0)
- ret = state;
- break;
-
- case -EHOSTUNREACH:
- if (ret == 0 ||
- ret == -ENETUNREACH)
- ret = state;
- break;
-
- case -ECONNREFUSED:
- if (ret == 0 ||
- ret == -ENETUNREACH ||
- ret == -EHOSTUNREACH)
- ret = state;
- break;
-
- default:
- case -EREMOTEIO:
- if (ret == 0 ||
- ret == -ENETUNREACH ||
- ret == -EHOSTUNREACH ||
- ret == -ECONNREFUSED)
- ret = state;
- break;
- }
- }
-
-error:
- fc->ac.error = ret;
-
- /* no available servers
- * - TODO: handle the no active servers case better
- */
- up_read(&volume->server_sem);
- _leave(" = f [%d]", fc->ac.error);
- return false;
-
-picked_server:
- /* Found an apparently healthy server. We need to register an interest
- * in receiving callbacks before we talk to it.
- */
- ret = afs_register_server_cb_interest(vnode,
- &volume->cb_interests[loop], server);
- if (ret < 0)
- goto error;
-
- fc->server = afs_get_server(server);
- up_read(&volume->server_sem);
-set_server:
- fc->ac.alist = afs_get_addrlist(fc->server->addrs);
- fc->ac.addr = &fc->ac.alist->addrs[0];
- _debug("USING SERVER: %pIS\n", &fc->ac.addr->transport);
- _leave(" = t (picked %pIS)", &fc->ac.addr->transport);
- return true;
-}
-
-/*
- * release a server after use
- * - releases the ref on the server struct that was acquired by picking
- * - records result of using a particular server to access a volume
- * - return true to try again, false if okay or to issue error
- * - the caller must release the server struct if result was false
- */
-bool afs_iterate_fs_cursor(struct afs_fs_cursor *fc,
- struct afs_vnode *vnode)
-{
- struct afs_volume *volume = vnode->volume;
- struct afs_server *server = fc->server;
- unsigned loop;
-
- _enter("%s,%pIS,%d",
- volume->vlocation->vldb.name, &fc->ac.addr->transport,
- fc->ac.error);
-
- switch (fc->ac.error) {
- /* success */
- case 0:
- server->fs_state = 0;
- _leave(" = f");
- return false;
-
- /* the fileserver denied all knowledge of the volume */
- case -ENOMEDIUM:
- down_write(&volume->server_sem);
-
- /* firstly, find where the server is in the active list (if it
- * is) */
- for (loop = 0; loop < volume->nservers; loop++)
- if (volume->servers[loop] == server)
- goto present;
-
- /* no longer there - may have been discarded by another op */
- goto try_next_server_upw;
-
- present:
- volume->nservers--;
- memmove(&volume->servers[loop],
- &volume->servers[loop + 1],
- sizeof(volume->servers[loop]) *
- (volume->nservers - loop));
- volume->servers[volume->nservers] = NULL;
- afs_put_server(afs_v2net(vnode), server);
- volume->rjservers++;
-
- if (volume->nservers > 0)
- /* another server might acknowledge its existence */
- goto try_next_server_upw;
-
- /* handle the case where all the fileservers have rejected the
- * volume
- * - TODO: try asking the fileservers for volume information
- * - TODO: contact the VL server again to see if the volume is
- * no longer registered
- */
- up_write(&volume->server_sem);
- afs_put_server(afs_v2net(vnode), server);
- fc->server = NULL;
- _leave(" = f [completely rejected]");
- return false;
-
- /* problem reaching the server */
- case -ENETUNREACH:
- case -EHOSTUNREACH:
- case -ECONNREFUSED:
- case -ETIME:
- case -ETIMEDOUT:
- case -EREMOTEIO:
- /* mark the server as dead
- * TODO: vary dead timeout depending on error
- */
- spin_lock(&server->fs_lock);
- if (!server->fs_state) {
- server->fs_state = fc->ac.error;
- printk("kAFS: SERVER DEAD state=%d\n", fc->ac.error);
- }
- spin_unlock(&server->fs_lock);
- goto try_next_server;
-
- /* miscellaneous error */
- default:
- case -ENOMEM:
- case -ENONET:
- /* tell the caller to accept the result */
- afs_put_server(afs_v2net(vnode), server);
- fc->server = NULL;
- _leave(" = f [local failure]");
- return false;
- }
-
- /* tell the caller to loop around and try the next server */
-try_next_server_upw:
- up_write(&volume->server_sem);
-try_next_server:
- afs_put_server(afs_v2net(vnode), server);
- _leave(" = t [try next server]");
- return true;
-}
-
-/*
- * Clean up a fileserver cursor.
- */
-int afs_end_fs_cursor(struct afs_fs_cursor *fc, struct afs_net *net)
-{
- afs_end_cursor(&fc->ac);
- afs_put_server(net, fc->server);
- return fc->ac.error;
-}
-
-#endif