On Mon, 2023-01-23 at 21:32 -0800, Dai Ngo wrote: > When nfsd4_copy fails to allocate memory for async_copy->cp_src, or > nfs4_init_copy_state fails, it calls cleanup_async_copy to do the > cleanup for the async_copy which causes page fault since async_copy > is not yet initialized. > > This patche sets async_copy to NULL to skip cleanup_async_copy > if async_copy is not yet initialized. > > Fixes: ce0887ac96d3 ("NFSD add nfs4 inter ssc to nfsd4_copy") > Fixes: 87689df69491 ("NFSD: Shrink size of struct nfsd4_copy") > Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> > --- > fs/nfsd/nfs4proc.c | 13 ++++++++++--- > 1 file changed, 10 insertions(+), 3 deletions(-) > > diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c > index 3b73e4d342bf..b4e7e18e1761 100644 > --- a/fs/nfsd/nfs4proc.c > +++ b/fs/nfsd/nfs4proc.c > @@ -1688,7 +1688,8 @@ static void cleanup_async_copy(struct nfsd4_copy *copy) > if (!nfsd4_ssc_is_inter(copy)) > nfsd_file_put(copy->nf_src); > spin_lock(©->cp_clp->async_lock); > - list_del(©->copies); > + if (!list_empty(©->copies)) > + list_del(©->copies); > spin_unlock(©->cp_clp->async_lock); > nfs4_put_copy(copy); > } > @@ -1789,9 +1790,15 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, > goto out_err; > async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL); > if (!async_copy->cp_src) > + goto no_mem; > + if (!nfs4_init_copy_state(nn, copy)) { > + kfree(async_copy->cp_src); > +no_mem: > + kfree(async_copy); > + async_copy = NULL; This seems pretty fragile and the result begins to resemble spaghetti. I think it'd be cleaner to initialize the list_head and refcount before you do the allocation of cp_src. Then you can just call cleanup_async_copy no matter where it fails. Bear in mind that these are failure codepaths, so we don't need to optimize for performance here. > goto out_err; > - if (!nfs4_init_copy_state(nn, copy)) > - goto out_err; > + } > + INIT_LIST_HEAD(&async_copy->copies); > refcount_set(&async_copy->refcount, 1); > memcpy(©->cp_res.cb_stateid, ©->cp_stateid.cs_stid, > sizeof(copy->cp_res.cb_stateid)); -- Jeff Layton <jlayton@xxxxxxxxxx>