Merge branch 'bugfixes' into nfs-for-next
This commit is contained in:
Коммит
0b08b07507
|
@ -92,7 +92,7 @@ out:
|
|||
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_open_context *ctx;
|
||||
|
@ -116,10 +116,11 @@ again:
|
|||
err = nfs_delegation_claim_locks(ctx, state);
|
||||
put_nfs_open_context(ctx);
|
||||
if (err != 0)
|
||||
return;
|
||||
return err;
|
||||
goto again;
|
||||
}
|
||||
spin_unlock(&inode->i_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -261,30 +262,34 @@ static void nfs_msync_inode(struct inode *inode)
|
|||
/*
|
||||
* 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);
|
||||
int err;
|
||||
|
||||
nfs_msync_inode(inode);
|
||||
/*
|
||||
* Guard against new delegated open/lock/unlock calls and against
|
||||
* state recovery
|
||||
*/
|
||||
down_write(&nfsi->rwsem);
|
||||
nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||
err = nfs_delegation_claim_opens(inode, &delegation->stateid);
|
||||
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
|
||||
*/
|
||||
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 inode *inode;
|
||||
int err = 0;
|
||||
|
||||
restart:
|
||||
rcu_read_lock();
|
||||
|
@ -298,12 +303,18 @@ restart:
|
|||
delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
rcu_read_unlock();
|
||||
if (delegation != NULL)
|
||||
__nfs_inode_return_delegation(inode, delegation);
|
||||
if (delegation != NULL) {
|
||||
filemap_flush(inode->i_mapping);
|
||||
err = __nfs_inode_return_delegation(inode, delegation, 0);
|
||||
}
|
||||
iput(inode);
|
||||
goto restart;
|
||||
if (!err)
|
||||
goto restart;
|
||||
set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state);
|
||||
return err;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -338,8 +349,10 @@ int nfs_inode_return_delegation(struct inode *inode)
|
|||
spin_lock(&clp->cl_lock);
|
||||
delegation = nfs_detach_delegation_locked(nfsi, NULL);
|
||||
spin_unlock(&clp->cl_lock);
|
||||
if (delegation != NULL)
|
||||
err = __nfs_inode_return_delegation(inode, delegation);
|
||||
if (delegation != NULL) {
|
||||
nfs_msync_inode(inode);
|
||||
err = __nfs_inode_return_delegation(inode, delegation, 1);
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
@ -368,7 +381,8 @@ void nfs_super_return_all_delegations(struct super_block *sb)
|
|||
spin_unlock(&delegation->lock);
|
||||
}
|
||||
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)
|
||||
|
|
|
@ -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_unreferenced_delegations(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_reap_unclaimed(struct nfs_client *clp);
|
||||
|
|
|
@ -146,7 +146,7 @@ static int nfs_dns_show(struct seq_file *m, struct cache_detail *cd,
|
|||
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 cache_head *ch;
|
||||
|
@ -159,7 +159,7 @@ struct nfs_dns_ent *nfs_dns_lookup(struct cache_detail *cd,
|
|||
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 *key)
|
||||
{
|
||||
|
|
|
@ -1488,7 +1488,7 @@ static int _nfs4_open_expired(struct nfs_open_context *ctx, struct nfs4_state *s
|
|||
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 nfs4_exception exception = { };
|
||||
|
@ -1496,10 +1496,16 @@ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4
|
|||
|
||||
do {
|
||||
err = _nfs4_open_expired(ctx, state);
|
||||
if (err != -NFS4ERR_DELAY)
|
||||
break;
|
||||
nfs4_handle_exception(server, err, &exception);
|
||||
switch (err) {
|
||||
default:
|
||||
goto out;
|
||||
case -NFS4ERR_GRACE:
|
||||
case -NFS4ERR_DELAY:
|
||||
nfs4_handle_exception(server, err, &exception);
|
||||
err = 0;
|
||||
}
|
||||
} while (exception.retry);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -1981,7 +1987,7 @@ out_drop:
|
|||
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)
|
||||
return;
|
||||
|
@ -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)
|
||||
return 0;
|
||||
err = _nfs4_do_setlk(state, F_SETLK, request, 0);
|
||||
if (err != -NFS4ERR_DELAY)
|
||||
break;
|
||||
nfs4_handle_exception(server, err, &exception);
|
||||
switch (err) {
|
||||
default:
|
||||
goto out;
|
||||
case -NFS4ERR_GRACE:
|
||||
case -NFS4ERR_DELAY:
|
||||
nfs4_handle_exception(server, err, &exception);
|
||||
err = 0;
|
||||
}
|
||||
} while (exception.retry);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
static void nfs4_state_end_reclaim_nograce(struct nfs_client *clp)
|
||||
{
|
||||
clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
||||
}
|
||||
|
||||
static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
|
||||
static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
|
||||
{
|
||||
switch (error) {
|
||||
case -NFS4ERR_CB_PATH_DOWN:
|
||||
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_LEASE_MOVED:
|
||||
set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
|
||||
nfs4_state_end_reclaim_reboot(clp);
|
||||
nfs4_state_start_reclaim_reboot(clp);
|
||||
break;
|
||||
case -NFS4ERR_EXPIRED:
|
||||
|
@ -1074,6 +1073,7 @@ static void nfs4_recovery_handle_error(struct nfs_client *clp, int error)
|
|||
case -NFS4ERR_SEQ_MISORDERED:
|
||||
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)
|
||||
|
@ -1093,8 +1093,7 @@ restart:
|
|||
if (status < 0) {
|
||||
set_bit(ops->owner_flag_bit, &sp->so_flags);
|
||||
nfs4_put_state_owner(sp);
|
||||
nfs4_recovery_handle_error(clp, status);
|
||||
return status;
|
||||
return nfs4_recovery_handle_error(clp, status);
|
||||
}
|
||||
nfs4_put_state_owner(sp);
|
||||
goto restart;
|
||||
|
@ -1124,8 +1123,7 @@ static int nfs4_check_lease(struct nfs_client *clp)
|
|||
status = ops->renew_lease(clp, cred);
|
||||
put_rpccred(cred);
|
||||
out:
|
||||
nfs4_recovery_handle_error(clp, status);
|
||||
return status;
|
||||
return nfs4_recovery_handle_error(clp, status);
|
||||
}
|
||||
|
||||
static int nfs4_reclaim_lease(struct nfs_client *clp)
|
||||
|
@ -1234,7 +1232,8 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
|||
status = nfs4_reclaim_lease(clp);
|
||||
if (status) {
|
||||
nfs4_set_lease_expired(clp, status);
|
||||
if (status == -EAGAIN)
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED,
|
||||
&clp->cl_state))
|
||||
continue;
|
||||
if (clp->cl_cons_state ==
|
||||
NFS_CS_SESSION_INITING)
|
||||
|
@ -1246,9 +1245,12 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
|||
|
||||
if (test_and_clear_bit(NFS4CLNT_CHECK_LEASE, &clp->cl_state)) {
|
||||
status = nfs4_check_lease(clp);
|
||||
if (status != 0)
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
|
||||
continue;
|
||||
if (status < 0 && status != -NFS4ERR_CB_PATH_DOWN)
|
||||
goto out_error;
|
||||
}
|
||||
|
||||
/* Initialize or reset the session */
|
||||
if (test_and_clear_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state)
|
||||
&& nfs4_has_session(clp)) {
|
||||
|
@ -1256,41 +1258,36 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
|||
status = nfs4_initialize_session(clp);
|
||||
else
|
||||
status = nfs4_reset_session(clp);
|
||||
if (status) {
|
||||
if (status == -NFS4ERR_STALE_CLIENTID)
|
||||
continue;
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state))
|
||||
continue;
|
||||
if (status < 0)
|
||||
goto out_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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,
|
||||
nfs4_reboot_recovery_ops[clp->cl_minorversion]);
|
||||
if (status == -NFS4ERR_STALE_CLIENTID)
|
||||
continue;
|
||||
if (test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
|
||||
test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state))
|
||||
continue;
|
||||
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... */
|
||||
if (test_and_clear_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state)) {
|
||||
status = nfs4_do_reclaim(clp,
|
||||
nfs4_nograce_recovery_ops[clp->cl_minorversion]);
|
||||
if (status < 0) {
|
||||
set_bit(NFS4CLNT_RECLAIM_NOGRACE, &clp->cl_state);
|
||||
if (status == -NFS4ERR_STALE_CLIENTID)
|
||||
continue;
|
||||
if (status == -NFS4ERR_EXPIRED)
|
||||
continue;
|
||||
if (test_bit(NFS4CLNT_SESSION_SETUP,
|
||||
&clp->cl_state))
|
||||
continue;
|
||||
if (test_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state) ||
|
||||
test_bit(NFS4CLNT_SESSION_SETUP, &clp->cl_state) ||
|
||||
test_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state))
|
||||
continue;
|
||||
if (status < 0)
|
||||
goto out_error;
|
||||
} else
|
||||
nfs4_state_end_reclaim_nograce(clp);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) {
|
||||
|
@ -1309,8 +1306,6 @@ static void nfs4_state_manager(struct nfs_client *clp)
|
|||
out_error:
|
||||
printk(KERN_WARNING "Error: state manager failed on NFSv4 server %s"
|
||||
" 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -2096,7 +2096,7 @@ nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
|
|||
encode_compound_hdr(&xdr, req, &hdr);
|
||||
encode_sequence(&xdr, &args->seq_args, &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);
|
||||
|
||||
xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
|
||||
|
|
|
@ -123,16 +123,19 @@ rpcauth_unhash_cred_locked(struct rpc_cred *cred)
|
|||
clear_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
static int
|
||||
rpcauth_unhash_cred(struct rpc_cred *cred)
|
||||
{
|
||||
spinlock_t *cache_lock;
|
||||
int ret;
|
||||
|
||||
cache_lock = &cred->cr_auth->au_credcache->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);
|
||||
spin_unlock(cache_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -446,31 +449,35 @@ void
|
|||
put_rpccred(struct rpc_cred *cred)
|
||||
{
|
||||
/* Fast path for unhashed credentials */
|
||||
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) != 0)
|
||||
goto need_lock;
|
||||
|
||||
if (!atomic_dec_and_test(&cred->cr_count))
|
||||
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
|
||||
if (atomic_dec_and_test(&cred->cr_count))
|
||||
cred->cr_ops->crdestroy(cred);
|
||||
return;
|
||||
goto out_destroy;
|
||||
need_lock:
|
||||
}
|
||||
|
||||
if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
|
||||
return;
|
||||
if (!list_empty(&cred->cr_lru)) {
|
||||
number_cred_unused--;
|
||||
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) {
|
||||
cred->cr_expire = jiffies;
|
||||
list_add_tail(&cred->cr_lru, &cred_unused);
|
||||
number_cred_unused++;
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
return;
|
||||
if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) != 0) {
|
||||
cred->cr_expire = jiffies;
|
||||
list_add_tail(&cred->cr_lru, &cred_unused);
|
||||
number_cred_unused++;
|
||||
goto out_nodestroy;
|
||||
}
|
||||
if (!rpcauth_unhash_cred(cred)) {
|
||||
/* We were hashed and someone looked us up... */
|
||||
goto out_nodestroy;
|
||||
}
|
||||
}
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
out_destroy:
|
||||
cred->cr_ops->crdestroy(cred);
|
||||
return;
|
||||
out_nodestroy:
|
||||
spin_unlock(&rpc_credcache_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(put_rpccred);
|
||||
|
||||
|
|
|
@ -700,6 +700,10 @@ void xprt_connect(struct rpc_task *task)
|
|||
}
|
||||
if (!xprt_lock_write(xprt, task))
|
||||
return;
|
||||
|
||||
if (test_and_clear_bit(XPRT_CLOSE_WAIT, &xprt->state))
|
||||
xprt->ops->close(xprt);
|
||||
|
||||
if (xprt_connected(xprt))
|
||||
xprt_release_write(xprt, task);
|
||||
else {
|
||||
|
|
Загрузка…
Ссылка в новой задаче