NFS Client Bugfixes for Linux 6.18-rc

Bugfixes:
  * Fix for FlexFiles mirror->dss allocation
  * Apply delay_retrans to async operations
  * Check if suid/sgid is cleared after a write when needed
  * Fix setting the state renewal timer for early mounts after a reboot
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEnZ5MQTpR7cLU7KEp18tUv7ClQOsFAmjyqWYACgkQ18tUv7Cl
 QOuuhBAAtW3JjqOvuJdUKqLnvEB7p9MJCbJuLvxu3IncS7LR4ApMthogQNws/kYH
 sU44KZh1lIe0G6juYTR4SmpwuJ1VbPJ7tZ+ZAssfp29mLQu3txybK9o21jZMu+jH
 qjPRH4VIbfJot77lhBykSk+JzpxQMC89JaZbC5sgATHfTstQPiHtBSQ7zwC5EY8f
 dBmh2mlhRbBsblHw6KZq5QhNR6E1XsXMWGE8GoyzQR4QAWTNOtM+QIBkUapREODG
 4HCnW/7JEUNuaAAYMovqqxv+qGC/axEEjZdVEGyiOvliSIs9RM2CCSQnDZQ619DI
 xCV3Qxvbsr22dDX5O127If/vXNisWJM7JzB65yX2y0ZlAAIoDX6XwADDtnvMlHPX
 KI+CqwGyk41Wwc9F6WPOL+NUwaqCcVumeDGBSZ5LFN4uqR1SeSfztAVqgtDU++u4
 cePZlNXwob5BlzfqF8DG5uGagxirXIiwOo6N63xSCWuU0NMwfdi7wrMLi/cfFqeg
 xCyB6mSm+BE6qSwppzSupHxwuQH0RzOSsSAQArKarEICnQfmgKAd98r6fDkRffJQ
 mrfUGMF/bvf7kDyv9kywjFw+KPWr0DNWRjFaLF9gcIxyI6Ml5HDFVzkK7WpI0dou
 N/rO/XGjNt8mVYgAG1BgFRXwSE2NRufNbQTygVUfe7coBSjth+Y=
 =p2V5
 -----END PGP SIGNATURE-----

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

Pull NFS client fixes from Anna Schumaker:

 - Fix for FlexFiles mirror->dss allocation

 - Apply delay_retrans to async operations

 - Check if suid/sgid is cleared after a write when needed

 - Fix setting the state renewal timer for early mounts after a reboot

* tag 'nfs-for-6.18-2' of git://git.linux-nfs.org/projects/anna/linux-nfs:
  NFS4: Fix state renewals missing after boot
  NFS: check if suid/sgid was cleared after a write as needed
  NFS4: Apply delay_retrans to async operations
  NFSv4/flexfiles: fix to allocate mirror->dss before use
This commit is contained in:
Linus Torvalds 2025-10-18 07:18:48 -10:00
commit 2d07c6c209
5 changed files with 38 additions and 15 deletions

View File

@ -270,19 +270,31 @@ ff_layout_remove_mirror(struct nfs4_ff_layout_mirror *mirror)
mirror->layout = NULL; mirror->layout = NULL;
} }
static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(gfp_t gfp_flags) static struct nfs4_ff_layout_mirror *ff_layout_alloc_mirror(u32 dss_count,
gfp_t gfp_flags)
{ {
struct nfs4_ff_layout_mirror *mirror; struct nfs4_ff_layout_mirror *mirror;
u32 dss_id;
mirror = kzalloc(sizeof(*mirror), gfp_flags); mirror = kzalloc(sizeof(*mirror), gfp_flags);
if (mirror != NULL) { if (mirror == NULL)
spin_lock_init(&mirror->lock); return NULL;
refcount_set(&mirror->ref, 1);
INIT_LIST_HEAD(&mirror->mirrors); spin_lock_init(&mirror->lock);
for (dss_id = 0; dss_id < mirror->dss_count; dss_id++) refcount_set(&mirror->ref, 1);
nfs_localio_file_init(&mirror->dss[dss_id].nfl); INIT_LIST_HEAD(&mirror->mirrors);
mirror->dss_count = dss_count;
mirror->dss =
kcalloc(dss_count, sizeof(struct nfs4_ff_layout_ds_stripe),
gfp_flags);
if (mirror->dss == NULL) {
kfree(mirror);
return NULL;
} }
for (u32 dss_id = 0; dss_id < mirror->dss_count; dss_id++)
nfs_localio_file_init(&mirror->dss[dss_id].nfl);
return mirror; return mirror;
} }
@ -507,17 +519,12 @@ ff_layout_alloc_lseg(struct pnfs_layout_hdr *lh,
if (dss_count > 1 && stripe_unit == 0) if (dss_count > 1 && stripe_unit == 0)
goto out_err_free; goto out_err_free;
fls->mirror_array[i] = ff_layout_alloc_mirror(gfp_flags); fls->mirror_array[i] = ff_layout_alloc_mirror(dss_count, gfp_flags);
if (fls->mirror_array[i] == NULL) { if (fls->mirror_array[i] == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto out_err_free; goto out_err_free;
} }
fls->mirror_array[i]->dss_count = dss_count;
fls->mirror_array[i]->dss =
kcalloc(dss_count, sizeof(struct nfs4_ff_layout_ds_stripe),
gfp_flags);
for (dss_id = 0; dss_id < dss_count; dss_id++) { for (dss_id = 0; dss_id < dss_count; dss_id++) {
dss_info = &fls->mirror_array[i]->dss[dss_id]; dss_info = &fls->mirror_array[i]->dss[dss_id];
dss_info->mirror = fls->mirror_array[i]; dss_info->mirror = fls->mirror_array[i];

View File

@ -222,6 +222,7 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED; clp->cl_state = 1 << NFS4CLNT_LEASE_EXPIRED;
clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion]; clp->cl_mvops = nfs_v4_minor_ops[cl_init->minorversion];
clp->cl_mig_gen = 1; clp->cl_mig_gen = 1;
clp->cl_last_renewal = jiffies;
#if IS_ENABLED(CONFIG_NFS_V4_1) #if IS_ENABLED(CONFIG_NFS_V4_1)
init_waitqueue_head(&clp->cl_lock_waitq); init_waitqueue_head(&clp->cl_lock_waitq);
#endif #endif

View File

@ -3636,6 +3636,7 @@ struct nfs4_closedata {
} lr; } lr;
struct nfs_fattr fattr; struct nfs_fattr fattr;
unsigned long timestamp; unsigned long timestamp;
unsigned short retrans;
}; };
static void nfs4_free_closedata(void *data) static void nfs4_free_closedata(void *data)
@ -3664,6 +3665,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
.state = state, .state = state,
.inode = calldata->inode, .inode = calldata->inode,
.stateid = &calldata->arg.stateid, .stateid = &calldata->arg.stateid,
.retrans = calldata->retrans,
}; };
if (!nfs4_sequence_done(task, &calldata->res.seq_res)) if (!nfs4_sequence_done(task, &calldata->res.seq_res))
@ -3711,6 +3713,7 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
default: default:
task->tk_status = nfs4_async_handle_exception(task, task->tk_status = nfs4_async_handle_exception(task,
server, task->tk_status, &exception); server, task->tk_status, &exception);
calldata->retrans = exception.retrans;
if (exception.retry) if (exception.retry)
goto out_restart; goto out_restart;
} }
@ -5593,9 +5596,11 @@ static int nfs4_read_done_cb(struct rpc_task *task, struct nfs_pgio_header *hdr)
.inode = hdr->inode, .inode = hdr->inode,
.state = hdr->args.context->state, .state = hdr->args.context->state,
.stateid = &hdr->args.stateid, .stateid = &hdr->args.stateid,
.retrans = hdr->retrans,
}; };
task->tk_status = nfs4_async_handle_exception(task, task->tk_status = nfs4_async_handle_exception(task,
server, task->tk_status, &exception); server, task->tk_status, &exception);
hdr->retrans = exception.retrans;
if (exception.retry) { if (exception.retry) {
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
return -EAGAIN; return -EAGAIN;
@ -5709,10 +5714,12 @@ static int nfs4_write_done_cb(struct rpc_task *task,
.inode = hdr->inode, .inode = hdr->inode,
.state = hdr->args.context->state, .state = hdr->args.context->state,
.stateid = &hdr->args.stateid, .stateid = &hdr->args.stateid,
.retrans = hdr->retrans,
}; };
task->tk_status = nfs4_async_handle_exception(task, task->tk_status = nfs4_async_handle_exception(task,
NFS_SERVER(inode), task->tk_status, NFS_SERVER(inode), task->tk_status,
&exception); &exception);
hdr->retrans = exception.retrans;
if (exception.retry) { if (exception.retry) {
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
return -EAGAIN; return -EAGAIN;
@ -6726,6 +6733,7 @@ struct nfs4_delegreturndata {
struct nfs_fh fh; struct nfs_fh fh;
nfs4_stateid stateid; nfs4_stateid stateid;
unsigned long timestamp; unsigned long timestamp;
unsigned short retrans;
struct { struct {
struct nfs4_layoutreturn_args arg; struct nfs4_layoutreturn_args arg;
struct nfs4_layoutreturn_res res; struct nfs4_layoutreturn_res res;
@ -6746,6 +6754,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
.inode = data->inode, .inode = data->inode,
.stateid = &data->stateid, .stateid = &data->stateid,
.task_is_privileged = data->args.seq_args.sa_privileged, .task_is_privileged = data->args.seq_args.sa_privileged,
.retrans = data->retrans,
}; };
if (!nfs4_sequence_done(task, &data->res.seq_res)) if (!nfs4_sequence_done(task, &data->res.seq_res))
@ -6817,6 +6826,7 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
task->tk_status = nfs4_async_handle_exception(task, task->tk_status = nfs4_async_handle_exception(task,
data->res.server, task->tk_status, data->res.server, task->tk_status,
&exception); &exception);
data->retrans = exception.retrans;
if (exception.retry) if (exception.retry)
goto out_restart; goto out_restart;
} }
@ -7093,6 +7103,7 @@ struct nfs4_unlockdata {
struct file_lock fl; struct file_lock fl;
struct nfs_server *server; struct nfs_server *server;
unsigned long timestamp; unsigned long timestamp;
unsigned short retrans;
}; };
static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl, static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
@ -7147,6 +7158,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
struct nfs4_exception exception = { struct nfs4_exception exception = {
.inode = calldata->lsp->ls_state->inode, .inode = calldata->lsp->ls_state->inode,
.stateid = &calldata->arg.stateid, .stateid = &calldata->arg.stateid,
.retrans = calldata->retrans,
}; };
if (!nfs4_sequence_done(task, &calldata->res.seq_res)) if (!nfs4_sequence_done(task, &calldata->res.seq_res))
@ -7180,6 +7192,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
task->tk_status = nfs4_async_handle_exception(task, task->tk_status = nfs4_async_handle_exception(task,
calldata->server, task->tk_status, calldata->server, task->tk_status,
&exception); &exception);
calldata->retrans = exception.retrans;
if (exception.retry) if (exception.retry)
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
} }

View File

@ -1535,7 +1535,8 @@ static int nfs_writeback_done(struct rpc_task *task,
/* Deal with the suid/sgid bit corner case */ /* Deal with the suid/sgid bit corner case */
if (nfs_should_remove_suid(inode)) { if (nfs_should_remove_suid(inode)) {
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE); nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE
| NFS_INO_REVAL_FORCED);
spin_unlock(&inode->i_lock); spin_unlock(&inode->i_lock);
} }
return 0; return 0;

View File

@ -1659,6 +1659,7 @@ struct nfs_pgio_header {
void *netfs; void *netfs;
#endif #endif
unsigned short retrans;
int pnfs_error; int pnfs_error;
int error; /* merge with pnfs_error */ int error; /* merge with pnfs_error */
unsigned int good_bytes; /* boundary of good data */ unsigned int good_bytes; /* boundary of good data */