Skip to content

Commit 81e7229

Browse files
daimngochucklever
authored andcommitted
NFSD: fix problems with cleanup on errors in nfsd4_copy
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 rearranges the order of initializing the fields in async_copy and adds checks in cleanup_async_copy to skip un-initialized fields. Fixes: ce0887a ("NFSD add nfs4 inter ssc to nfsd4_copy") Fixes: 87689df ("NFSD: Shrink size of struct nfsd4_copy") Signed-off-by: Dai Ngo <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Chuck Lever <[email protected]>
1 parent fb610c4 commit 81e7229

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

fs/nfsd/nfs4proc.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,9 +1687,12 @@ static void cleanup_async_copy(struct nfsd4_copy *copy)
16871687
{
16881688
nfs4_free_copy_state(copy);
16891689
release_copy_files(copy);
1690-
spin_lock(&copy->cp_clp->async_lock);
1691-
list_del(&copy->copies);
1692-
spin_unlock(&copy->cp_clp->async_lock);
1690+
if (copy->cp_clp) {
1691+
spin_lock(&copy->cp_clp->async_lock);
1692+
if (!list_empty(&copy->copies))
1693+
list_del_init(&copy->copies);
1694+
spin_unlock(&copy->cp_clp->async_lock);
1695+
}
16931696
nfs4_put_copy(copy);
16941697
}
16951698

@@ -1786,12 +1789,13 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
17861789
async_copy = kzalloc(sizeof(struct nfsd4_copy), GFP_KERNEL);
17871790
if (!async_copy)
17881791
goto out_err;
1792+
INIT_LIST_HEAD(&async_copy->copies);
1793+
refcount_set(&async_copy->refcount, 1);
17891794
async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
17901795
if (!async_copy->cp_src)
17911796
goto out_err;
17921797
if (!nfs4_init_copy_state(nn, copy))
17931798
goto out_err;
1794-
refcount_set(&async_copy->refcount, 1);
17951799
memcpy(&copy->cp_res.cb_stateid, &copy->cp_stateid.cs_stid,
17961800
sizeof(copy->cp_res.cb_stateid));
17971801
dup_copy_fields(copy, async_copy);

fs/nfsd/nfs4state.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -975,7 +975,6 @@ static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid,
975975

976976
stid->cs_stid.si_opaque.so_clid.cl_boot = (u32)nn->boot_time;
977977
stid->cs_stid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id;
978-
stid->cs_type = cs_type;
979978

980979
idr_preload(GFP_KERNEL);
981980
spin_lock(&nn->s2s_cp_lock);
@@ -986,6 +985,7 @@ static int nfs4_init_cp_state(struct nfsd_net *nn, copy_stateid_t *stid,
986985
idr_preload_end();
987986
if (new_id < 0)
988987
return 0;
988+
stid->cs_type = cs_type;
989989
return 1;
990990
}
991991

@@ -1019,7 +1019,8 @@ void nfs4_free_copy_state(struct nfsd4_copy *copy)
10191019
{
10201020
struct nfsd_net *nn;
10211021

1022-
WARN_ON_ONCE(copy->cp_stateid.cs_type != NFS4_COPY_STID);
1022+
if (copy->cp_stateid.cs_type != NFS4_COPY_STID)
1023+
return;
10231024
nn = net_generic(copy->cp_clp->net, nfsd_net_id);
10241025
spin_lock(&nn->s2s_cp_lock);
10251026
idr_remove(&nn->s2s_cp_stateids,

0 commit comments

Comments
 (0)