diff options
Diffstat (limited to 'fs/afs/rotate.c')
| -rw-r--r-- | fs/afs/rotate.c | 53 | 
1 files changed, 33 insertions, 20 deletions
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index c3ae324781f8..172ba569cd60 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later  /* Handle fileserver selection and rotation.   *   * Copyright (C) 2017 Red Hat, Inc. All Rights Reserved.   * Written by David Howells ([email protected]) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version.   */  #include <linux/kernel.h> @@ -25,7 +21,7 @@   * them here also using the io_lock.   */  bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode, -			       struct key *key) +			       struct key *key, bool intr)  {  	memset(fc, 0, sizeof(*fc));  	fc->vnode = vnode; @@ -33,10 +29,15 @@ bool afs_begin_vnode_operation(struct afs_fs_cursor *fc, struct afs_vnode *vnode  	fc->ac.error = SHRT_MAX;  	fc->error = -EDESTADDRREQ; -	if (mutex_lock_interruptible(&vnode->io_lock) < 0) { -		fc->error = -EINTR; -		fc->flags |= AFS_FS_CURSOR_STOP; -		return false; +	if (intr) { +		fc->flags |= AFS_FS_CURSOR_INTR; +		if (mutex_lock_interruptible(&vnode->io_lock) < 0) { +			fc->error = -EINTR; +			fc->flags |= AFS_FS_CURSOR_STOP; +			return false; +		} +	} else { +		mutex_lock(&vnode->io_lock);  	}  	if (vnode->lock_state != AFS_VNODE_LOCK_NONE) @@ -61,7 +62,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,  	fc->untried = (1UL << fc->server_list->nr_servers) - 1;  	fc->index = READ_ONCE(fc->server_list->preferred); -	cbi = vnode->cb_interest; +	cbi = rcu_dereference_protected(vnode->cb_interest, +					lockdep_is_held(&vnode->io_lock));  	if (cbi) {  		/* See if the vnode's preferred record is still available */  		for (i = 0; i < fc->server_list->nr_servers; i++) { @@ -82,8 +84,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc,  		/* Note that the callback promise is effectively broken */  		write_seqlock(&vnode->cb_lock); -		ASSERTCMP(cbi, ==, vnode->cb_interest); -		vnode->cb_interest = NULL; +		ASSERTCMP(cbi, ==, rcu_access_pointer(vnode->cb_interest)); +		rcu_assign_pointer(vnode->cb_interest, NULL);  		if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags))  			vnode->cb_break++;  		write_sequnlock(&vnode->cb_lock); @@ -118,10 +120,14 @@ static void afs_busy(struct afs_volume *volume, u32 abort_code)   */  static bool afs_sleep_and_retry(struct afs_fs_cursor *fc)  { -	msleep_interruptible(1000); -	if (signal_pending(current)) { -		fc->error = -ERESTARTSYS; -		return false; +	if (fc->flags & AFS_FS_CURSOR_INTR) { +		msleep_interruptible(1000); +		if (signal_pending(current)) { +			fc->error = -ERESTARTSYS; +			return false; +		} +	} else { +		msleep(1000);  	}  	return true; @@ -408,7 +414,9 @@ selected_server:  	if (error < 0)  		goto failed_set_error; -	fc->cbi = afs_get_cb_interest(vnode->cb_interest); +	fc->cbi = afs_get_cb_interest( +		rcu_dereference_protected(vnode->cb_interest, +					  lockdep_is_held(&vnode->io_lock)));  	read_lock(&server->fs_lock);  	alist = rcu_dereference_protected(server->addresses, @@ -459,6 +467,8 @@ no_more_servers:  				     s->probe.abort_code);  	} +	error = e.error; +  failed_set_error:  	fc->error = error;  failed: @@ -476,12 +486,15 @@ failed:  bool afs_select_current_fileserver(struct afs_fs_cursor *fc)  {  	struct afs_vnode *vnode = fc->vnode; -	struct afs_cb_interest *cbi = vnode->cb_interest; +	struct afs_cb_interest *cbi;  	struct afs_addr_list *alist;  	int error = fc->ac.error;  	_enter(""); +	cbi = rcu_dereference_protected(vnode->cb_interest, +					lockdep_is_held(&vnode->io_lock)); +  	switch (error) {  	case SHRT_MAX:  		if (!cbi) { @@ -490,7 +503,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc)  			return false;  		} -		fc->cbi = afs_get_cb_interest(vnode->cb_interest); +		fc->cbi = afs_get_cb_interest(cbi);  		read_lock(&cbi->server->fs_lock);  		alist = rcu_dereference_protected(cbi->server->addresses,  |