mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-31 16:38:12 +00:00
NFS Client Fixes for Linux 5.19-rc
- Bugfixes: - 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 -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmKs2ZwACgkQ18tUv7Cl QOsnGxAA6g0M7IU6g375rfqxq9a/XqSlvwIeuSOb14WNybh7D6qXOa+iInsHFIl7 d7coORg846SOdUl218hVcp8Ba1OTsj/XAruJllsrHQnB50raBJ/nUbIbQlrxGYKn WzMtVnyLQ8Ml+rvERINPqVcgUBJ0PGWMiRi/h8OcUlWylV5ZI/irpkaZiuXamzhe O0Wa04N/82bUU03dEmQ0ZuPuhMn5JbOMaSzciRvHEV8nLvqvRAhGIVBtvrrYF0VB UfZx/4DTRXDD5/RA65hX2vgixZh7/cLTv4pr26wmfDBofo1zDiFsQpPS8QaZo5bt Sw+UQK1c15kW/EJS+au90mazBmFnk5UX2BOyfN+Cg5/GlHjE0YHV1f2ejbHycsyh Rcsu8nxNa5T82mg2EjOCqK2YWy8mGHYr5MJTYftL/uE8NdqP/DSgNpqNSQhQD2Bm vzsG0wP5RP+i3pRWWQnXOlZE+GdaKxtXKtg2ZjHx1Wkb2QIUbgbxST59q/U5QnIN MJKS1nhbxQA0dGo3ClzYNe76S9It7DDE0A3mdvIzPwRSheQhgmF4UlzyTWgSdyfw lnT5EK3pQat6cvdaszjMn1f6vx4BvTuhXUE9eH35opVMYykvAU6hz4ypllxKoR/h BES6KMJPKXn77ICJJVC3RR5w2v756DRNMeOfkjCi18TiuTVFXek= =nTJk -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
4b35035bcf
6 changed files with 20 additions and 6 deletions
|
@ -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,
|
||||||
}
|
}
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
|
|
||||||
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,
|
||||||
* 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,
|
||||||
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)
|
||||||
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 {
|
||||||
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,
|
||||||
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:
|
||||||
|
|
Loading…
Reference in a new issue