Commit 0b08b075 authored by Trond Myklebust's avatar Trond Myklebust

Merge branch 'bugfixes' into nfs-for-next

parents 22763c5c 1185a552
...@@ -92,7 +92,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ ...@@ -92,7 +92,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
return status; return status;
} }
static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid) static int nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *stateid)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
...@@ -116,10 +116,11 @@ static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid * ...@@ -116,10 +116,11 @@ static void nfs_delegation_claim_opens(struct inode *inode, const nfs4_stateid *
err = nfs_delegation_claim_locks(ctx, state); err = nfs_delegation_claim_locks(ctx, state);
put_nfs_open_context(ctx); put_nfs_open_context(ctx);
if (err != 0) if (err != 0)
return; return err;
goto again; goto again;
} }
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
return 0;
} }
/* /*
...@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode) ...@@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
/* /*
* Basic procedure for returning a delegation to the server * Basic procedure for returning a delegation to the server
*/ */
static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation) static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation, int issync)
{ {
struct nfs_inode *nfsi = NFS_I(inode); struct nfs_inode *nfsi = NFS_I(inode);
int err;
nfs_msync_inode(inode);
/* /*
* Guard against new delegated open/lock/unlock calls and against * Guard against new delegated open/lock/unlock calls and against
* state recovery * state recovery
*/ */
down_write(&nfsi->rwsem); down_write(&nfsi->rwsem);
nfs_delegation_claim_opens(inode, &delegation->stateid); err = nfs_delegation_claim_opens(inode, &delegation->stateid);
up_write(&nfsi->rwsem); up_write(&nfsi->rwsem);
nfs_msync_inode(inode); if (err)
goto out;
return nfs_do_return_delegation(inode, delegation, 1); err = nfs_do_return_delegation(inode, delegation, issync);
out:
return err;
} }
/* /*
* Return all delegations that have been marked for return * Return all delegations that have been marked for return
*/ */
void nfs_client_return_marked_delegations(struct nfs_client *clp) int nfs_client_return_marked_delegations(struct nfs_client *clp)
{ {
struct nfs_delegation *delegation; struct nfs_delegation *delegation;
struct inode *inode; struct inode *inode;
int err = 0;
restart: restart:
rcu_read_lock(); rcu_read_lock();
...@@ -298,12 +303,18 @@ void nfs_client_return_marked_delegations(struct nfs_client *clp) ...@@ -298,12 +303,18 @@ void nfs_client_return_marked_delegations(struct nfs_client *clp)
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL); delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
rcu_read_unlock(); rcu_read_unlock();
if (delegation != NULL) if (delegation != NULL) {
__nfs_inode_return_delegation(inode, delegation); filemap_flush(inode->i_mapping);
err = __nfs_inode_return_delegation(inode, delegation, 0);
}
iput(inode); iput(inode);
goto restart; if (!err)
goto restart;
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
return err;
} }
rcu_read_unlock(); rcu_read_unlock();
return 0;
} }
/* /*
...@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode) ...@@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
spin_lock(&clp->cl_lock); spin_lock(&clp->cl_lock);
delegation = nfs_detach_delegation_locked(nfsi, NULL); delegation = nfs_detach_delegation_locked(nfsi, NULL);
spin_unlock(&clp->cl_lock); spin_unlock(&clp->cl_lock);
if (delegation != NULL) if (delegation != NULL) {
err = __nfs_inode_return_delegation(inode, delegation); nfs_msync_inode(inode);
err = __nfs_inode_return_delegation(inode, delegation, 1);
}
} }
return err; return err;
} }
...@@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb) ...@@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb)
spin_unlock(&delegation->lock); spin_unlock(&delegation->lock);
} }
rcu_read_unlock(); rcu_read_unlock();
nfs_client_return_marked_delegations(clp); if (nfs_client_return_marked_delegations(clp) != 0)
nfs4_schedule_state_manager(clp);
} }
static void nfs_client_mark_return_all_delegations(struct nfs_client *clp) static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
......
...@@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb); ...@@ -42,7 +42,7 @@ void nfs_super_return_all_delegations(struct super_block *sb);
void nfs_expire_all_delegations(struct nfs_client *clp); void nfs_expire_all_delegations(struct nfs_client *clp);
void nfs_expire_unreferenced_delegations(struct nfs_client *clp); void nfs_expire_unreferenced_delegations(struct nfs_client *clp);
void nfs_handle_cb_pathdown(struct nfs_client *clp); void nfs_handle_cb_pathdown(struct nfs_client *clp);
void nfs_client_return_marked_delegations(struct nfs_client *clp); int nfs_client_return_marked_delegations(struct nfs_client *clp);
void nfs_delegation_mark_reclaim(struct nfs_client *clp); void nfs_delegation_mark_reclaim(struct nfs_client *clp);
void nfs_delegation_reap_unclaimed(struct nfs_client *clp); void nfs_delegation_reap_unclaimed(struct nfs_client *clp);
......
...@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd, ...@@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
return 0; return 0;
} }
struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, static struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
struct nfs_dns_ent *key) struct nfs_dns_ent *key)
{ {
struct cache_head *ch; struct cache_head *ch;
...@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd, ...@@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
return container_of(ch, struct nfs_dns_ent, h); return container_of(ch, struct nfs_dns_ent, h);
} }
struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd, static struct nfs_dns_ent *nfs_dns_update(struct cache_detail *cd,
struct nfs_dns_ent *new, struct nfs_dns_ent *new,
struct nfs_dns_ent *key) struct nfs_dns_ent *key)
{ {
......
...@@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s ...@@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
return ret; return ret;
} }
static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) static int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state)
{ {
struct nfs_server *server = NFS_SERVER(state->inode); struct nfs_server *server = NFS_SERVER(state->inode);
struct nfs4_exception exception = { }; struct nfs4_exception exception = { };
...@@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4 ...@@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4
do { do {
err = _nfs4_open_expired(ctx, state); err = _nfs4_open_expired(ctx, state);
if (err != -NFS4ERR_DELAY) switch (err) {
break; default:
nfs4_handle_exception(server, err, &exception); goto out;
case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
nfs4_handle_exception(server, err, &exception);
err = 0;
}
} while (exception.retry); } while (exception.retry);
out:
return err; return err;
} }
...@@ -1981,7 +1987,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st ...@@ -1981,7 +1987,7 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
return 0; return 0;
} }
void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync)
{ {
if (ctx->state == NULL) if (ctx->state == NULL)
return; return;
...@@ -4049,10 +4055,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request ...@@ -4049,10 +4055,16 @@ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request
if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0) if (test_bit(NFS_DELEGATED_STATE, &state->flags) != 0)
return 0; return 0;
err = _nfs4_do_setlk(state, F_SETLK, request, 0); err = _nfs4_do_setlk(state, F_SETLK, request, 0);
if (err != -NFS4ERR_DELAY) switch (err) {
break; default:
nfs4_handle_exception(server, err, &exception); goto out;
case -NFS4ERR_GRACE:
case -NFS4ERR_DELAY:
nfs4_handle_exception(server, err, &exception);
err = 0;
}
} while (exception.retry); } while (exception.retry);
out:
return err; return err;
} }
......
...@@ -1046,20 +1046,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp) ...@@ -1046,20 +1046,19 @@ static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce); nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_nograce);
} }
static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp) static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
{
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
}
static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
{ {
switch (error) { switch (error) {
case -NFS4ERR_CB_PATH_DOWN: case -NFS4ERR_CB_PATH_DOWN:
nfs_handle_cb_pathdown(clp); nfs_handle_cb_pathdown(clp);
break; return 0;
case -NFS4ERR_NO_GRACE:
nfs4_state_end_reclaim_reboot(clp);
return 0;
case -NFS4ERR_STALE_CLIENTID: case -NFS4ERR_STALE_CLIENTID:
case -NFS4ERR_LEASE_MOVED: case -NFS4ERR_LEASE_MOVED:
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state); set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
nfs4_state_end_reclaim_reboot(clp);
nfs4_state_start_reclaim_reboot(clp); nfs4_state_start_reclaim_reboot(clp);
break; break;
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
...@@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error) ...@@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
case -NFS4ERR_SEQ_MISORDERED: case -NFS4ERR_SEQ_MISORDERED:
set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state); set_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state);
} }
return error;
} }
static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops) static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recovery_ops *ops)
...@@ -1093,8 +1093,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov ...@@ -1093,8 +1093,7 @@ static int nfs4_do_reclaim(struct nfs_client *clp, const struct nfs4_state_recov
if (status < 0) { if (status < 0) {
set_bit(ops->owner_flag_bit, &sp->so_flags); set_bit(ops->owner_flag_bit, &sp->so_flags);
nfs4_put_state_owner(sp); nfs4_put_state_owner(sp);
nfs4_recovery_handle_error(clp, status); return nfs4_recovery_handle_error(clp, status);
return status;
} }
nfs4_put_state_owner(sp); nfs4_put_state_owner(sp);
goto restart; goto restart;
...@@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp) ...@@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
status = ops->renew_lease(clp, cred); status = ops->renew_lease(clp, cred);
put_rpccred(cred); put_rpccred(cred);
out: out:
nfs4_recovery_handle_error(clp, status); return nfs4_recovery_handle_error(clp, status);
return status;
} }
static int nfs4_reclaim_lease(struct nfs_client *clp) static int nfs4_reclaim_lease(struct nfs_client *clp)
...@@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
status = nfs4_reclaim_lease(clp); status = nfs4_reclaim_lease(clp);
if (status) { if (status) {
nfs4_set_lease_expired(clp, status); nfs4_set_lease_expired(clp, status);
if (status == -EAGAIN) if (test_bit(NFS4CLNT_LEASE_EXPIRED,
&clp->cl_state))
continue; continue;
if (clp->cl_cons_state == if (clp->cl_cons_state ==
NFS_CS_SESSION_INITING) NFS_CS_SESSION_INITING)
...@@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) { if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
status = nfs4_check_lease(clp); status = nfs4_check_lease(clp);
if (status != 0) if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
continue; continue;
if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
goto out_error;
} }
/* Initialize or reset the session */ /* Initialize or reset the session */
if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
&& nfs4_has_session(clp)) { && nfs4_has_session(clp)) {
...@@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp)
status = nfs4_initialize_session(clp); status = nfs4_initialize_session(clp);
else else
status = nfs4_reset_session(clp); status = nfs4_reset_session(clp);
if (status) { if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
if (status == -NFS4ERR_STALE_CLIENTID) continue;
continue; if (status < 0)
goto out_error; goto out_error;
}
} }
/* First recover reboot state... */ /* First recover reboot state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) { if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state)) {
status = nfs4_do_reclaim(clp, status = nfs4_do_reclaim(clp,
nfs4_reboot_recovery_ops[clp->cl_minorversion]); nfs4_reboot_recovery_ops[clp->cl_minorversion]);
if (status == -NFS4ERR_STALE_CLIENTID) if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
continue; test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
continue; continue;
nfs4_state_end_reclaim_reboot(clp); nfs4_state_end_reclaim_reboot(clp);
continue; if (test_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state))
continue;
if (status < 0)
goto out_error;
} }
/* Now recover expired state... */ /* Now recover expired state... */
if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) { if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
status = nfs4_do_reclaim(clp, status = nfs4_do_reclaim(clp,
nfs4_nograce_recovery_ops[clp->cl_minorversion]); nfs4_nograce_recovery_ops[clp->cl_minorversion]);
if (status < 0) { if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state); test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) ||
if (status == -NFS4ERR_STALE_CLIENTID) test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
continue; continue;
if (status == -NFS4ERR_EXPIRED) if (status < 0)
continue;
if (test_bit(NFS4CLNT_SESSION_SETUP,
&clp->cl_state))
continue;
goto out_error; goto out_error;
} else
nfs4_state_end_reclaim_nograce(clp);
continue;
} }
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
...@@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp) ...@@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
out_error: out_error:
printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s" printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
" with error %d\n", clp->cl_hostname, -status); " with error %d\n", clp->cl_hostname, -status);
if (test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
nfs4_state_end_reclaim_reboot(clp);
nfs4_clear_state_manager_bit(clp); nfs4_clear_state_manager_bit(clp);
} }
......
...@@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p, ...@@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
encode_compound_hdr(&xdr, req, &hdr); encode_compound_hdr(&xdr, req, &hdr);
encode_sequence(&xdr, &args->seq_args, &hdr); encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, args->fh, &hdr); encode_putfh(&xdr, args->fh, &hdr);
replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1; replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr); encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
xdr_inline_pages(&req->rq_rcv_buf, replen << 2, xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
......
...@@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred) ...@@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags); clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
} }
static void static int
rpcauth_unhash_cred(struct rpc_cred *cred) rpcauth_unhash_cred(struct rpc_cred *cred)
{ {
spinlock_t *cache_lock; spinlock_t *cache_lock;
int ret;
cache_lock = &cred->cr_auth->au_credcache->lock; cache_lock = &cred->cr_auth->au_credcache->lock;
spin_lock(cache_lock); spin_lock(cache_lock);
if (atomic_read(&cred->cr_count) == 0) ret = atomic_read(&cred->cr_count) == 0;
if (ret)
rpcauth_unhash_cred_locked(cred); rpcauth_unhash_cred_locked(cred);
spin_unlock(cache_lock); spin_unlock(cache_lock);
return ret;
} }
/* /*
...@@ -446,31 +449,35 @@ void ...@@ -446,31 +449,35 @@ void
put_rpccred(struct rpc_cred *cred) put_rpccred(struct rpc_cred *cred)
{ {
/* Fast path for unhashed credentials */ /* Fast path for unhashed credentials */
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
goto need_lock; if (atomic_dec_and_test(&cred->cr_count))
cred->cr_ops->crdestroy(cred);
if (!atomic_dec_and_test(&cred->cr_count))
return; return;
goto out_destroy; }
need_lock:
if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock)) if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
return; return;
if (!list_empty(&cred->cr_lru)) { if (!list_empty(&cred->cr_lru)) {
number_cred_unused--; number_cred_unused--;
list_del_init(&cred->cr_lru); list_del_init(&cred->cr_lru);
} }
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0)
rpcauth_unhash_cred(cred);
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) { if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0) {
cred->cr_expire = jiffies; if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
list_add_tail(&cred->cr_lru, &cred_unused); cred->cr_expire = jiffies;
number_cred_unused++; list_add_tail(&cred->cr_lru, &cred_unused);
spin_unlock(&rpc_credcache_lock); number_cred_unused++;
return; goto out_nodestroy;
}
if (!rpcauth_unhash_cred(cred)) {
/* We were hashed and someone looked us up... */
goto out_nodestroy;
}
} }
spin_unlock(&rpc_credcache_lock); spin_unlock(&rpc_credcache_lock);
out_destroy:
cred->cr_ops->crdestroy(cred); cred->cr_ops->crdestroy(cred);
return;
out_nodestroy:
spin_unlock(&rpc_credcache_lock);
} }
EXPORT_SYMBOL_GPL(put_rpccred); EXPORT_SYMBOL_GPL(put_rpccred);
......
...@@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task) ...@@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task)
} }
if (!xprt_lock_write(xprt, task)) if (!xprt_lock_write(xprt, task))
return; return;
if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state))
xprt->ops->close(xprt);
if (xprt_connected(xprt)) if (xprt_connected(xprt))
xprt_release_write(xprt, task); xprt_release_write(xprt, task);
else { else {
......
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