diff options
Diffstat (limited to 'fs/nfs/nfs4client.c')
| -rw-r--r-- | fs/nfs/nfs4client.c | 75 | 
1 files changed, 32 insertions, 43 deletions
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index e5f2fad14ff..ac4fc9a8fdb 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -30,15 +30,14 @@ static int nfs_get_cb_ident_idr(struct nfs_client *clp, int minorversion)  	if (clp->rpc_ops->version != 4 || minorversion != 0)  		return ret; -retry: -	if (!idr_pre_get(&nn->cb_ident_idr, GFP_KERNEL)) -		return -ENOMEM; +	idr_preload(GFP_KERNEL);  	spin_lock(&nn->nfs_client_lock); -	ret = idr_get_new(&nn->cb_ident_idr, clp, &clp->cl_cb_ident); +	ret = idr_alloc(&nn->cb_ident_idr, clp, 0, 0, GFP_NOWAIT); +	if (ret >= 0) +		clp->cl_cb_ident = ret;  	spin_unlock(&nn->nfs_client_lock); -	if (ret == -EAGAIN) -		goto retry; -	return ret; +	idr_preload_end(); +	return ret < 0 ? ret : 0;  }  #ifdef CONFIG_NFS_V4_1 @@ -237,11 +236,10 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,  	error = nfs4_discover_server_trunking(clp, &old);  	if (error < 0)  		goto error; +	nfs_put_client(clp);  	if (clp != old) {  		clp->cl_preserve_clid = true; -		nfs_put_client(clp);  		clp = old; -		atomic_inc(&clp->cl_count);  	}  	return clp; @@ -307,7 +305,7 @@ int nfs40_walk_client_list(struct nfs_client *new,  		.clientid	= new->cl_clientid,  		.confirm	= new->cl_confirm,  	}; -	int status; +	int status = -NFS4ERR_STALE_CLIENTID;  	spin_lock(&nn->nfs_client_lock);  	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { @@ -333,40 +331,33 @@ int nfs40_walk_client_list(struct nfs_client *new,  		if (prev)  			nfs_put_client(prev); +		prev = pos;  		status = nfs4_proc_setclientid_confirm(pos, &clid, cred); -		if (status == 0) { +		switch (status) { +		case -NFS4ERR_STALE_CLIENTID: +			break; +		case 0:  			nfs4_swap_callback_idents(pos, new); -			nfs_put_client(pos); +			prev = NULL;  			*result = pos;  			dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",  				__func__, pos, atomic_read(&pos->cl_count)); -			return 0; -		} -		if (status != -NFS4ERR_STALE_CLIENTID) { -			nfs_put_client(pos); -			dprintk("NFS: <-- %s status = %d, no result\n", -				__func__, status); -			return status; +		default: +			goto out;  		}  		spin_lock(&nn->nfs_client_lock); -		prev = pos;  	} +	spin_unlock(&nn->nfs_client_lock); -	/* -	 * No matching nfs_client found.  This should be impossible, -	 * because the new nfs_client has already been added to -	 * nfs_client_list by nfs_get_client(). -	 * -	 * Don't BUG(), since the caller is holding a mutex. -	 */ +	/* No match found. The server lost our clientid */ +out:  	if (prev)  		nfs_put_client(prev); -	spin_unlock(&nn->nfs_client_lock); -	pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); -	return -NFS4ERR_STALE_CLIENTID; +	dprintk("NFS: <-- %s status = %d\n", __func__, status); +	return status;  }  #ifdef CONFIG_NFS_V4_1 @@ -433,7 +424,7 @@ int nfs41_walk_client_list(struct nfs_client *new,  {  	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);  	struct nfs_client *pos, *n, *prev = NULL; -	int error; +	int status = -NFS4ERR_STALE_CLIENTID;  	spin_lock(&nn->nfs_client_lock);  	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) { @@ -449,14 +440,17 @@ int nfs41_walk_client_list(struct nfs_client *new,  				nfs_put_client(prev);  			prev = pos; -			error = nfs_wait_client_init_complete(pos); -			if (error < 0) { +			nfs4_schedule_lease_recovery(pos); +			status = nfs_wait_client_init_complete(pos); +			if (status < 0) {  				nfs_put_client(pos);  				spin_lock(&nn->nfs_client_lock);  				continue;  			} - +			status = pos->cl_cons_state;  			spin_lock(&nn->nfs_client_lock); +			if (status < 0) +				continue;  		}  		if (pos->rpc_ops != new->rpc_ops) @@ -474,6 +468,7 @@ int nfs41_walk_client_list(struct nfs_client *new,  		if (!nfs4_match_serverowners(pos, new))  			continue; +		atomic_inc(&pos->cl_count);  		spin_unlock(&nn->nfs_client_lock);  		dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",  			__func__, pos, atomic_read(&pos->cl_count)); @@ -482,16 +477,10 @@ int nfs41_walk_client_list(struct nfs_client *new,  		return 0;  	} -	/* -	 * No matching nfs_client found.  This should be impossible, -	 * because the new nfs_client has already been added to -	 * nfs_client_list by nfs_get_client(). -	 * -	 * Don't BUG(), since the caller is holding a mutex. -	 */ +	/* No matching nfs_client found. */  	spin_unlock(&nn->nfs_client_lock); -	pr_err("NFS: %s Error: no matching nfs_client found\n", __func__); -	return -NFS4ERR_STALE_CLIENTID; +	dprintk("NFS: <-- %s status = %d\n", __func__, status); +	return status;  }  #endif	/* CONFIG_NFS_V4_1 */  |