Commit 4b35035b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfs-for-5.19-2' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client fixes from Anna Schumaker:

 - Add FMODE_CAN_ODIRECT support to NFSv4 so opens don't fail

 - Fix trunking detection & cl_max_connect setting

 - Avoid pnfs_update_layout() livelocks

 - Don't keep retrying pNFS if the server replies with NFS4ERR_UNAVAILABLE

* tag 'nfs-for-5.19-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFSv4: Add FMODE_CAN_ODIRECT after successful open of a NFS4.x file
  sunrpc: set cl_max_connect when cloning an rpc_clnt
  pNFS: Avoid a live lock condition in pnfs_update_layout()
  pNFS: Don't keep retrying if the server replied NFS4ERR_LAYOUTUNAVAILABLE
parents 32efdbff 5ee3d10f
...@@ -288,6 +288,7 @@ static u32 initiate_file_draining(struct nfs_client *clp, ...@@ -288,6 +288,7 @@ static u32 initiate_file_draining(struct nfs_client *clp,
rv = NFS4_OK; rv = NFS4_OK;
break; break;
case -ENOENT: case -ENOENT:
set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);
/* Embrace your forgetfulness! */ /* Embrace your forgetfulness! */
rv = NFS4ERR_NOMATCHING_LAYOUT; rv = NFS4ERR_NOMATCHING_LAYOUT;
......
...@@ -2124,6 +2124,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry, ...@@ -2124,6 +2124,7 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
} }
goto out; goto out;
} }
file->f_mode |= FMODE_CAN_ODIRECT;
err = nfs_finish_open(ctx, ctx->dentry, file, open_flags); err = nfs_finish_open(ctx, ctx->dentry, file, open_flags);
trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
......
...@@ -93,6 +93,7 @@ nfs4_file_open(struct inode *inode, struct file *filp) ...@@ -93,6 +93,7 @@ nfs4_file_open(struct inode *inode, struct file *filp)
nfs_file_set_open_context(filp, ctx); nfs_file_set_open_context(filp, ctx);
nfs_fscache_open_file(inode, filp); nfs_fscache_open_file(inode, filp);
err = 0; err = 0;
filp->f_mode |= FMODE_CAN_ODIRECT;
out_put_ctx: out_put_ctx:
put_nfs_open_context(ctx); put_nfs_open_context(ctx);
......
...@@ -469,6 +469,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo, ...@@ -469,6 +469,7 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
pnfs_clear_lseg_state(lseg, lseg_list); pnfs_clear_lseg_state(lseg, lseg_list);
pnfs_clear_layoutreturn_info(lo); pnfs_clear_layoutreturn_info(lo);
pnfs_free_returned_lsegs(lo, lseg_list, &range, 0); pnfs_free_returned_lsegs(lo, lseg_list, &range, 0);
set_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags);
if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) && if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) &&
!test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags)) !test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))
pnfs_clear_layoutreturn_waitbit(lo); pnfs_clear_layoutreturn_waitbit(lo);
...@@ -1917,8 +1918,9 @@ static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo) ...@@ -1917,8 +1918,9 @@ static void nfs_layoutget_begin(struct pnfs_layout_hdr *lo)
static void nfs_layoutget_end(struct pnfs_layout_hdr *lo) static void nfs_layoutget_end(struct pnfs_layout_hdr *lo)
{ {
if (atomic_dec_and_test(&lo->plh_outstanding)) if (atomic_dec_and_test(&lo->plh_outstanding) &&
wake_up_var(&lo->plh_outstanding); test_and_clear_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags))
wake_up_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN);
} }
static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo) static bool pnfs_is_first_layoutget(struct pnfs_layout_hdr *lo)
...@@ -2025,11 +2027,11 @@ pnfs_update_layout(struct inode *ino, ...@@ -2025,11 +2027,11 @@ pnfs_update_layout(struct inode *ino,
* If the layout segment list is empty, but there are outstanding * If the layout segment list is empty, but there are outstanding
* layoutget calls, then they might be subject to a layoutrecall. * layoutget calls, then they might be subject to a layoutrecall.
*/ */
if ((list_empty(&lo->plh_segs) || !pnfs_layout_is_valid(lo)) && if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) &&
atomic_read(&lo->plh_outstanding) != 0) { atomic_read(&lo->plh_outstanding) != 0) {
spin_unlock(&ino->i_lock); spin_unlock(&ino->i_lock);
lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding, lseg = ERR_PTR(wait_on_bit(&lo->plh_flags, NFS_LAYOUT_DRAIN,
!atomic_read(&lo->plh_outstanding))); TASK_KILLABLE));
if (IS_ERR(lseg)) if (IS_ERR(lseg))
goto out_put_layout_hdr; goto out_put_layout_hdr;
pnfs_put_layout_hdr(lo); pnfs_put_layout_hdr(lo);
...@@ -2152,6 +2154,12 @@ pnfs_update_layout(struct inode *ino, ...@@ -2152,6 +2154,12 @@ pnfs_update_layout(struct inode *ino,
case -ERECALLCONFLICT: case -ERECALLCONFLICT:
case -EAGAIN: case -EAGAIN:
break; break;
case -ENODATA:
/* The server returned NFS4ERR_LAYOUTUNAVAILABLE */
pnfs_layout_set_fail_bit(
lo, pnfs_iomode_to_fail_bit(iomode));
lseg = NULL;
goto out_put_layout_hdr;
default: default:
if (!nfs_error_is_fatal(PTR_ERR(lseg))) { if (!nfs_error_is_fatal(PTR_ERR(lseg))) {
pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode)); pnfs_layout_clear_fail_bit(lo, pnfs_iomode_to_fail_bit(iomode));
...@@ -2407,7 +2415,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) ...@@ -2407,7 +2415,8 @@ pnfs_layout_process(struct nfs4_layoutget *lgp)
goto out_forget; goto out_forget;
} }
if (!pnfs_layout_is_valid(lo) && !pnfs_is_first_layoutget(lo)) if (test_bit(NFS_LAYOUT_DRAIN, &lo->plh_flags) &&
!pnfs_is_first_layoutget(lo))
goto out_forget; goto out_forget;
if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) {
......
...@@ -105,6 +105,7 @@ enum { ...@@ -105,6 +105,7 @@ enum {
NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */ NFS_LAYOUT_FIRST_LAYOUTGET, /* Serialize first layoutget */
NFS_LAYOUT_INODE_FREEING, /* The inode is being freed */ NFS_LAYOUT_INODE_FREEING, /* The inode is being freed */
NFS_LAYOUT_HASHED, /* The layout visible */ NFS_LAYOUT_HASHED, /* The layout visible */
NFS_LAYOUT_DRAIN,
}; };
enum layoutdriver_policy_flags { enum layoutdriver_policy_flags {
......
...@@ -651,6 +651,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args, ...@@ -651,6 +651,7 @@ static struct rpc_clnt *__rpc_clone_client(struct rpc_create_args *args,
new->cl_discrtry = clnt->cl_discrtry; new->cl_discrtry = clnt->cl_discrtry;
new->cl_chatty = clnt->cl_chatty; new->cl_chatty = clnt->cl_chatty;
new->cl_principal = clnt->cl_principal; new->cl_principal = clnt->cl_principal;
new->cl_max_connect = clnt->cl_max_connect;
return new; return new;
out_err: out_err:
......
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