[v7,13/19] NFSD return nfs4_stid in nfs4_preprocess_stateid_op
diff mbox series

Message ID 20190916211353.18802-14-olga.kornievskaia@gmail.com
State New
Headers show
Series
  • client and server support for "inter" SSC copy
Related show

Commit Message

Olga Kornievskaia Sept. 16, 2019, 9:13 p.m. UTC
Needed for copy to add nfs4_cp_state to the nfs4_stid.

Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Olga Kornievskaia <kolga@netapp.com>
---
 fs/nfsd/nfs4proc.c  | 21 +++++++++++----------
 fs/nfsd/nfs4state.c | 11 ++++++++---
 fs/nfsd/state.h     |  3 ++-
 3 files changed, 21 insertions(+), 14 deletions(-)

Comments

J . Bruce Fields Oct. 2, 2019, 3:52 p.m. UTC | #1
On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
>  static __be32
>  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
>  		  stateid_t *src_stateid, struct nfsd_file **src,
> -		  stateid_t *dst_stateid, struct nfsd_file **dst)
> +		  stateid_t *dst_stateid, struct nfsd_file **dst,
> +		  struct nfs4_stid **stid)
>  {
>  	__be32 status;
>  
...
> @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
>  	__be32 status;
>  
>  	status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> -				   &clone->cl_dst_stateid, &dst);
> +				   &clone->cl_dst_stateid, &dst, NULL);
>  	if (status)
>  		goto out;
>  
> @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
>  
>  	status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
>  				   &copy->nf_src, &copy->cp_dst_stateid,
> -				   &copy->nf_dst);
> +				   &copy->nf_dst, NULL);
>  	if (status)
>  		goto out;
>  

So both callers pass NULL for the new stid parameter.  Looks like that's
still true after the full series of patches, too.

--b.
Olga Kornievskaia Oct. 2, 2019, 4:12 p.m. UTC | #2
On Wed, Oct 2, 2019 at 11:52 AM J. Bruce Fields <bfields@fieldses.org> wrote:
>
> On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> > @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> >  static __be32
> >  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> >                 stateid_t *src_stateid, struct nfsd_file **src,
> > -               stateid_t *dst_stateid, struct nfsd_file **dst)
> > +               stateid_t *dst_stateid, struct nfsd_file **dst,
> > +               struct nfs4_stid **stid)
> >  {
> >       __be32 status;
> >
> ...
> > @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> >       __be32 status;
> >
> >       status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> > -                                &clone->cl_dst_stateid, &dst);
> > +                                &clone->cl_dst_stateid, &dst, NULL);
> >       if (status)
> >               goto out;
> >
> > @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
> >
> >       status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
> >                                  &copy->nf_src, &copy->cp_dst_stateid,
> > -                                &copy->nf_dst);
> > +                                &copy->nf_dst, NULL);
> >       if (status)
> >               goto out;
> >
>
> So both callers pass NULL for the new stid parameter.  Looks like that's
> still true after the full series of patches, too.
>

If you look at an earlier chunk it uses it (there is only a single
user of it: copy notify state)
@@ -1034,14 +1035,14 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst
*rqstp, struct svc_fh *fh)
                return nfserr_nofilehandle;

        status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
-                                           src_stateid, RD_STATE, src);
+                                           src_stateid, RD_STATE, src, NULL);
        if (status) {
                dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
                goto out;
        }

        status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
-                                           dst_stateid, WR_STATE, dst);
+                                           dst_stateid, WR_STATE, dst, stid);
        if (status) {
                dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
                goto out_put_src;

> --b.
Olga Kornievskaia Oct. 2, 2019, 4:15 p.m. UTC | #3
On Wed, Oct 2, 2019 at 12:12 PM Olga Kornievskaia
<olga.kornievskaia@gmail.com> wrote:
>
> On Wed, Oct 2, 2019 at 11:52 AM J. Bruce Fields <bfields@fieldses.org> wrote:
> >
> > On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> > > @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > >  static __be32
> > >  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > >                 stateid_t *src_stateid, struct nfsd_file **src,
> > > -               stateid_t *dst_stateid, struct nfsd_file **dst)
> > > +               stateid_t *dst_stateid, struct nfsd_file **dst,
> > > +               struct nfs4_stid **stid)
> > >  {
> > >       __be32 status;
> > >
> > ...
> > > @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > >       __be32 status;
> > >
> > >       status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> > > -                                &clone->cl_dst_stateid, &dst);
> > > +                                &clone->cl_dst_stateid, &dst, NULL);
> > >       if (status)
> > >               goto out;
> > >
> > > @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
> > >
> > >       status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
> > >                                  &copy->nf_src, &copy->cp_dst_stateid,
> > > -                                &copy->nf_dst);
> > > +                                &copy->nf_dst, NULL);
> > >       if (status)
> > >               goto out;
> > >
> >
> > So both callers pass NULL for the new stid parameter.  Looks like that's
> > still true after the full series of patches, too.
> >
>
> If you look at an earlier chunk it uses it (there is only a single
> user of it: copy notify state)

actually the 2 user nfsd4_verify_copy and nfsd4_copy_notify in a different patch

> @@ -1034,14 +1035,14 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst
> *rqstp, struct svc_fh *fh)
>                 return nfserr_nofilehandle;
>
>         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
> -                                           src_stateid, RD_STATE, src);
> +                                           src_stateid, RD_STATE, src, NULL);
>         if (status) {
>                 dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
>                 goto out;
>         }
>
>         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> -                                           dst_stateid, WR_STATE, dst);
> +                                           dst_stateid, WR_STATE, dst, stid);
>         if (status) {
>                 dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
>                 goto out_put_src;
>
> > --b.
J. Bruce Fields Oct. 2, 2019, 4:34 p.m. UTC | #4
On Wed, Oct 02, 2019 at 12:12:17PM -0400, Olga Kornievskaia wrote:
> On Wed, Oct 2, 2019 at 11:52 AM J. Bruce Fields <bfields@fieldses.org> wrote:
> >
> > On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> > > @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > >  static __be32
> > >  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > >                 stateid_t *src_stateid, struct nfsd_file **src,
> > > -               stateid_t *dst_stateid, struct nfsd_file **dst)
> > > +               stateid_t *dst_stateid, struct nfsd_file **dst,
> > > +               struct nfs4_stid **stid)
> > >  {
> > >       __be32 status;
> > >
> > ...
> > > @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > >       __be32 status;
> > >
> > >       status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> > > -                                &clone->cl_dst_stateid, &dst);
> > > +                                &clone->cl_dst_stateid, &dst, NULL);
> > >       if (status)
> > >               goto out;
> > >
> > > @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
> > >
> > >       status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
> > >                                  &copy->nf_src, &copy->cp_dst_stateid,
> > > -                                &copy->nf_dst);
> > > +                                &copy->nf_dst, NULL);
> > >       if (status)
> > >               goto out;
> > >
> >
> > So both callers pass NULL for the new stid parameter.  Looks like that's
> > still true after the full series of patches, too.
> >
> 
> If you look at an earlier chunk it uses it (there is only a single
> user of it: copy notify state)

You're talking about nfs4_preprocess_stateid_op, the above is
nfsd4_verify_copy.

--b.

> @@ -1034,14 +1035,14 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst
> *rqstp, struct svc_fh *fh)
>                 return nfserr_nofilehandle;
> 
>         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
> -                                           src_stateid, RD_STATE, src);
> +                                           src_stateid, RD_STATE, src, NULL);
>         if (status) {
>                 dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
>                 goto out;
>         }
> 
>         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> -                                           dst_stateid, WR_STATE, dst);
> +                                           dst_stateid, WR_STATE, dst, stid);
>         if (status) {
>                 dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
>                 goto out_put_src;
> 
> > --b.
Olga Kornievskaia Oct. 2, 2019, 4:52 p.m. UTC | #5
On Wed, Oct 2, 2019 at 12:34 PM J. Bruce Fields <bfields@redhat.com> wrote:
>
> On Wed, Oct 02, 2019 at 12:12:17PM -0400, Olga Kornievskaia wrote:
> > On Wed, Oct 2, 2019 at 11:52 AM J. Bruce Fields <bfields@fieldses.org> wrote:
> > >
> > > On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> > > > @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > > >  static __be32
> > > >  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > > >                 stateid_t *src_stateid, struct nfsd_file **src,
> > > > -               stateid_t *dst_stateid, struct nfsd_file **dst)
> > > > +               stateid_t *dst_stateid, struct nfsd_file **dst,
> > > > +               struct nfs4_stid **stid)
> > > >  {
> > > >       __be32 status;
> > > >
> > > ...
> > > > @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > > >       __be32 status;
> > > >
> > > >       status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> > > > -                                &clone->cl_dst_stateid, &dst);
> > > > +                                &clone->cl_dst_stateid, &dst, NULL);
> > > >       if (status)
> > > >               goto out;
> > > >
> > > > @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
> > > >
> > > >       status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
> > > >                                  &copy->nf_src, &copy->cp_dst_stateid,
> > > > -                                &copy->nf_dst);
> > > > +                                &copy->nf_dst, NULL);
> > > >       if (status)
> > > >               goto out;
> > > >
> > >
> > > So both callers pass NULL for the new stid parameter.  Looks like that's
> > > still true after the full series of patches, too.
> > >
> >
> > If you look at an earlier chunk it uses it (there is only a single
> > user of it: copy notify state)
>
> You're talking about nfs4_preprocess_stateid_op, the above is
> nfsd4_verify_copy.

I see. You are right, looks like after reworks the nfsd4_verify_copy
doesn't need a stid. Previously both copy stateid and copy_notify
stateids were tied to its parents but I've removed the link for the
copy stateid a while back. Should I now combine this patch with "NFSD
add COPY_NOTIFY operation" because that's the only caller of
nfsd4_preprocess_stateid_op that needs the stid.

>
> --b.
>
> > @@ -1034,14 +1035,14 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst
> > *rqstp, struct svc_fh *fh)
> >                 return nfserr_nofilehandle;
> >
> >         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
> > -                                           src_stateid, RD_STATE, src);
> > +                                           src_stateid, RD_STATE, src, NULL);
> >         if (status) {
> >                 dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
> >                 goto out;
> >         }
> >
> >         status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
> > -                                           dst_stateid, WR_STATE, dst);
> > +                                           dst_stateid, WR_STATE, dst, stid);
> >         if (status) {
> >                 dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
> >                 goto out_put_src;
> >
> > > --b.
J. Bruce Fields Oct. 2, 2019, 4:57 p.m. UTC | #6
On Wed, Oct 02, 2019 at 12:52:37PM -0400, Olga Kornievskaia wrote:
> On Wed, Oct 2, 2019 at 12:34 PM J. Bruce Fields <bfields@redhat.com> wrote:
> >
> > On Wed, Oct 02, 2019 at 12:12:17PM -0400, Olga Kornievskaia wrote:
> > > On Wed, Oct 2, 2019 at 11:52 AM J. Bruce Fields <bfields@fieldses.org> wrote:
> > > >
> > > > On Mon, Sep 16, 2019 at 05:13:47PM -0400, Olga Kornievskaia wrote:
> > > > > @@ -1026,7 +1026,8 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > > > >  static __be32
> > > > >  nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
> > > > >                 stateid_t *src_stateid, struct nfsd_file **src,
> > > > > -               stateid_t *dst_stateid, struct nfsd_file **dst)
> > > > > +               stateid_t *dst_stateid, struct nfsd_file **dst,
> > > > > +               struct nfs4_stid **stid)
> > > > >  {
> > > > >       __be32 status;
> > > > >
> > > > ...
> > > > > @@ -1072,7 +1073,7 @@ static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
> > > > >       __be32 status;
> > > > >
> > > > >       status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
> > > > > -                                &clone->cl_dst_stateid, &dst);
> > > > > +                                &clone->cl_dst_stateid, &dst, NULL);
> > > > >       if (status)
> > > > >               goto out;
> > > > >
> > > > > @@ -1260,7 +1261,7 @@ static int nfsd4_do_async_copy(void *data)
> > > > >
> > > > >       status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
> > > > >                                  &copy->nf_src, &copy->cp_dst_stateid,
> > > > > -                                &copy->nf_dst);
> > > > > +                                &copy->nf_dst, NULL);
> > > > >       if (status)
> > > > >               goto out;
> > > > >
> > > >
> > > > So both callers pass NULL for the new stid parameter.  Looks like that's
> > > > still true after the full series of patches, too.
> > > >
> > >
> > > If you look at an earlier chunk it uses it (there is only a single
> > > user of it: copy notify state)
> >
> > You're talking about nfs4_preprocess_stateid_op, the above is
> > nfsd4_verify_copy.
> 
> I see. You are right, looks like after reworks the nfsd4_verify_copy
> doesn't need a stid. Previously both copy stateid and copy_notify
> stateids were tied to its parents but I've removed the link for the
> copy stateid a while back. Should I now combine this patch with "NFSD
> add COPY_NOTIFY operation" because that's the only caller of
> nfsd4_preprocess_stateid_op that needs the stid.

Yeah, maybe so.

--b.

Patch
diff mbox series

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index 4e3e77b..6c0d216 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -776,7 +776,7 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 	/* check stateid */
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
 					&read->rd_stateid, RD_STATE,
-					&read->rd_nf);
+					&read->rd_nf, NULL);
 	if (status) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
@@ -948,7 +948,7 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 		status = nfs4_preprocess_stateid_op(rqstp, cstate,
 				&cstate->current_fh, &setattr->sa_stateid,
-				WR_STATE, NULL);
+				WR_STATE, NULL, NULL);
 		if (status) {
 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
 			return status;
@@ -999,7 +999,7 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 	trace_nfsd_write_start(rqstp, &cstate->current_fh,
 			       write->wr_offset, cnt);
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
-						stateid, WR_STATE, &nf);
+						stateid, WR_STATE, &nf, NULL);
 	if (status) {
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		return status;
@@ -1026,7 +1026,8 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 static __be32
 nfsd4_verify_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		  stateid_t *src_stateid, struct nfsd_file **src,
-		  stateid_t *dst_stateid, struct nfsd_file **dst)
+		  stateid_t *dst_stateid, struct nfsd_file **dst,
+		  struct nfs4_stid **stid)
 {
 	__be32 status;
 
@@ -1034,14 +1035,14 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 		return nfserr_nofilehandle;
 
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->save_fh,
-					    src_stateid, RD_STATE, src);
+					    src_stateid, RD_STATE, src, NULL);
 	if (status) {
 		dprintk("NFSD: %s: couldn't process src stateid!\n", __func__);
 		goto out;
 	}
 
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
-					    dst_stateid, WR_STATE, dst);
+					    dst_stateid, WR_STATE, dst, stid);
 	if (status) {
 		dprintk("NFSD: %s: couldn't process dst stateid!\n", __func__);
 		goto out_put_src;
@@ -1072,7 +1073,7 @@  static __be32 nfsd4_do_lookupp(struct svc_rqst *rqstp, struct svc_fh *fh)
 	__be32 status;
 
 	status = nfsd4_verify_copy(rqstp, cstate, &clone->cl_src_stateid, &src,
-				   &clone->cl_dst_stateid, &dst);
+				   &clone->cl_dst_stateid, &dst, NULL);
 	if (status)
 		goto out;
 
@@ -1260,7 +1261,7 @@  static int nfsd4_do_async_copy(void *data)
 
 	status = nfsd4_verify_copy(rqstp, cstate, &copy->cp_src_stateid,
 				   &copy->nf_src, &copy->cp_dst_stateid,
-				   &copy->nf_dst);
+				   &copy->nf_dst, NULL);
 	if (status)
 		goto out;
 
@@ -1346,7 +1347,7 @@  struct nfsd4_copy *
 
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
 					    &fallocate->falloc_stateid,
-					    WR_STATE, &nf);
+					    WR_STATE, &nf, NULL);
 	if (status != nfs_ok) {
 		dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n");
 		return status;
@@ -1405,7 +1406,7 @@  struct nfsd4_copy *
 
 	status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh,
 					    &seek->seek_stateid,
-					    RD_STATE, &nf);
+					    RD_STATE, &nf, NULL);
 	if (status) {
 		dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n");
 		return status;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index da1093d..78e03af 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -5584,7 +5584,8 @@  static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 __be32
 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
-		stateid_t *stateid, int flags, struct nfsd_file **nfp)
+		stateid_t *stateid, int flags, struct nfsd_file **nfp,
+		struct nfs4_stid **cstid)
 {
 	struct inode *ino = d_inode(fhp->fh_dentry);
 	struct net *net = SVC_NET(rqstp);
@@ -5633,8 +5634,12 @@  static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
 	if (status == nfs_ok && nfp)
 		status = nfs4_check_file(rqstp, fhp, s, nfp, flags);
 out:
-	if (s)
-		nfs4_put_stid(s);
+	if (s) {
+		if (!status && cstid)
+			*cstid = s;
+		else
+			nfs4_put_stid(s);
+	}
 	return status;
 }
 
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 46f56af..d9e7cbd 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -617,7 +617,8 @@  struct nfsd4_blocked_lock {
 
 extern __be32 nfs4_preprocess_stateid_op(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *cstate, struct svc_fh *fhp,
-		stateid_t *stateid, int flags, struct nfsd_file **filp);
+		stateid_t *stateid, int flags, struct nfsd_file **filp,
+		struct nfs4_stid **cstid);
 __be32 nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
 		     stateid_t *stateid, unsigned char typemask,
 		     struct nfs4_stid **s, struct nfsd_net *nn);