diff mbox series

cifs: update the same create_guid on replay

Message ID 20240209112542.55690-1-sprasad@microsoft.com (mailing list archive)
State New, archived
Headers show
Series cifs: update the same create_guid on replay | expand

Commit Message

Shyam Prasad N Feb. 9, 2024, 11:25 a.m. UTC
From: Shyam Prasad N <sprasad@microsoft.com>

File open requests made to the server contain a
CreateGuid, which is used by the server to identify
the open request. If the same request needs to be
replayed, it needs to be sent with the same CreateGuid
in the durable handle v2 context.

Without doing so, we could end up leaking handles on
the server when:
1. multichannel is used AND
2. connection goes down, but not for all channels

This is because the replayed open request would have a
new CreateGuid and the server will treat this as a new
request and open a new handle.

This change fixes this by reusing the existing create_guid
stored in the cached fid struct.

REF: MS-SMB2 4.9 Replay Create Request on an Alternate Channel

Fixes: 4f1fffa23769 ("cifs: commands that are retried should have replay flag set")
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
---
 fs/smb/client/cached_dir.c |  1 +
 fs/smb/client/cifsglob.h   |  1 +
 fs/smb/client/smb2inode.c  |  1 +
 fs/smb/client/smb2ops.c    |  4 ++++
 fs/smb/client/smb2pdu.c    | 10 ++++++++--
 5 files changed, 15 insertions(+), 2 deletions(-)

Comments

Steve French Feb. 10, 2024, 6:22 a.m. UTC | #1
It needed a small rebase to work around one of Paulo's patches which
it depended on (which is for 6.9-rc) but was wondering if you want
this patch in before 6.9 because its change to smb2_compound_op below
has a dependency on another patch - can that change be safely removed?

replay_again:
        /* reinitialize for possible replay */
        flags = 0;
        oplock = SMB2_OPLOCK_LEVEL_NONE;
        num_rqst = 0;
        server = cifs_pick_channel(ses);
        oparms->replay = !!(retries);

On Fri, Feb 9, 2024 at 5:25 AM <nspmangalore@gmail.com> wrote:
>
> From: Shyam Prasad N <sprasad@microsoft.com>
>
> File open requests made to the server contain a
> CreateGuid, which is used by the server to identify
> the open request. If the same request needs to be
> replayed, it needs to be sent with the same CreateGuid
> in the durable handle v2 context.
>
> Without doing so, we could end up leaking handles on
> the server when:
> 1. multichannel is used AND
> 2. connection goes down, but not for all channels
>
> This is because the replayed open request would have a
> new CreateGuid and the server will treat this as a new
> request and open a new handle.
>
> This change fixes this by reusing the existing create_guid
> stored in the cached fid struct.
>
> REF: MS-SMB2 4.9 Replay Create Request on an Alternate Channel
>
> Fixes: 4f1fffa23769 ("cifs: commands that are retried should have replay flag set")
> Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
> ---
>  fs/smb/client/cached_dir.c |  1 +
>  fs/smb/client/cifsglob.h   |  1 +
>  fs/smb/client/smb2inode.c  |  1 +
>  fs/smb/client/smb2ops.c    |  4 ++++
>  fs/smb/client/smb2pdu.c    | 10 ++++++++--
>  5 files changed, 15 insertions(+), 2 deletions(-)
>
> diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
> index 1daeb5714faa..3de5047a7ff9 100644
> --- a/fs/smb/client/cached_dir.c
> +++ b/fs/smb/client/cached_dir.c
> @@ -242,6 +242,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
>                 .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
>                 .disposition = FILE_OPEN,
>                 .fid = pfid,
> +               .replay = !!(retries),
>         };
>
>         rc = SMB2_open_init(tcon, server,
> diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> index cac10f8e17e4..efab4769de4e 100644
> --- a/fs/smb/client/cifsglob.h
> +++ b/fs/smb/client/cifsglob.h
> @@ -1373,6 +1373,7 @@ struct cifs_open_parms {
>         struct cifs_fid *fid;
>         umode_t mode;
>         bool reconnect:1;
> +       bool replay:1; /* indicates that this open is for a replay */
>         struct kvec *ea_cctx;
>  };
>
> diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> index 63485078a6df..22bd01e7bf6e 100644
> --- a/fs/smb/client/smb2inode.c
> +++ b/fs/smb/client/smb2inode.c
> @@ -203,6 +203,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
>         oplock = SMB2_OPLOCK_LEVEL_NONE;
>         num_rqst = 0;
>         server = cifs_pick_channel(ses);
> +       oparms->replay = !!(retries);
>
>         vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
>         if (vars == NULL)
> diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> index 8d674aef8dd9..c0da1935b0bd 100644
> --- a/fs/smb/client/smb2ops.c
> +++ b/fs/smb/client/smb2ops.c
> @@ -1205,6 +1205,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
>                 .disposition = FILE_OPEN,
>                 .create_options = cifs_create_options(cifs_sb, 0),
>                 .fid = &fid,
> +               .replay = !!(retries),
>         };
>
>         rc = SMB2_open_init(tcon, server,
> @@ -1570,6 +1571,7 @@ smb2_ioctl_query_info(const unsigned int xid,
>                 .disposition = FILE_OPEN,
>                 .create_options = cifs_create_options(cifs_sb, create_options),
>                 .fid = &fid,
> +               .replay = !!(retries),
>         };
>
>         if (qi.flags & PASSTHRU_FSCTL) {
> @@ -2296,6 +2298,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
>                 .disposition = FILE_OPEN,
>                 .create_options = cifs_create_options(cifs_sb, 0),
>                 .fid = fid,
> +               .replay = !!(retries),
>         };
>
>         rc = SMB2_open_init(tcon, server,
> @@ -2682,6 +2685,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
>                 .disposition = FILE_OPEN,
>                 .create_options = cifs_create_options(cifs_sb, 0),
>                 .fid = &fid,
> +               .replay = !!(retries),
>         };
>
>         rc = SMB2_open_init(tcon, server,
> diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> index 2ecc5f210329..1ce9be3a7ca7 100644
> --- a/fs/smb/client/smb2pdu.c
> +++ b/fs/smb/client/smb2pdu.c
> @@ -2406,8 +2406,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
>          */
>         buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
>         buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
> -       generate_random_uuid(buf->dcontext.CreateGuid);
> -       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> +
> +       /* for replay, we should not overwrite the existing create guid */
> +       if (!oparms->replay) {
> +               generate_random_uuid(buf->dcontext.CreateGuid);
> +               memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> +       } else
> +               memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
>
>         /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
>         buf->Name[0] = 'D';
> @@ -3156,6 +3161,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
>         /* reinitialize for possible replay */
>         flags = 0;
>         server = cifs_pick_channel(ses);
> +       oparms->replay = !!(retries);
>
>         cifs_dbg(FYI, "create/open\n");
>         if (!ses || !server)
> --
> 2.34.1
>
Shyam Prasad N Feb. 10, 2024, 4:42 p.m. UTC | #2
On Sat, Feb 10, 2024 at 11:52 AM Steve French <smfrench@gmail.com> wrote:
>
> It needed a small rebase to work around one of Paulo's patches which
> it depended on (which is for 6.9-rc) but was wondering if you want
> this patch in before 6.9 because its change to smb2_compound_op below
> has a dependency on another patch - can that change be safely removed?
>
It will be good to have this in 6.8-rc4, if it will be accepted. It's
the same small change made in several places.
It avoids a possible handle leak on the server.

> replay_again:
>         /* reinitialize for possible replay */
>         flags = 0;
>         oplock = SMB2_OPLOCK_LEVEL_NONE;
>         num_rqst = 0;
>         server = cifs_pick_channel(ses);
>         oparms->replay = !!(retries);
>
> On Fri, Feb 9, 2024 at 5:25 AM <nspmangalore@gmail.com> wrote:
> >
> > From: Shyam Prasad N <sprasad@microsoft.com>
> >
> > File open requests made to the server contain a
> > CreateGuid, which is used by the server to identify
> > the open request. If the same request needs to be
> > replayed, it needs to be sent with the same CreateGuid
> > in the durable handle v2 context.
> >
> > Without doing so, we could end up leaking handles on
> > the server when:
> > 1. multichannel is used AND
> > 2. connection goes down, but not for all channels
> >
> > This is because the replayed open request would have a
> > new CreateGuid and the server will treat this as a new
> > request and open a new handle.
> >
> > This change fixes this by reusing the existing create_guid
> > stored in the cached fid struct.
> >
> > REF: MS-SMB2 4.9 Replay Create Request on an Alternate Channel
> >
> > Fixes: 4f1fffa23769 ("cifs: commands that are retried should have replay flag set")
> > Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
> > ---
> >  fs/smb/client/cached_dir.c |  1 +
> >  fs/smb/client/cifsglob.h   |  1 +
> >  fs/smb/client/smb2inode.c  |  1 +
> >  fs/smb/client/smb2ops.c    |  4 ++++
> >  fs/smb/client/smb2pdu.c    | 10 ++++++++--
> >  5 files changed, 15 insertions(+), 2 deletions(-)
> >
> > diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
> > index 1daeb5714faa..3de5047a7ff9 100644
> > --- a/fs/smb/client/cached_dir.c
> > +++ b/fs/smb/client/cached_dir.c
> > @@ -242,6 +242,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
> >                 .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
> >                 .disposition = FILE_OPEN,
> >                 .fid = pfid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> > index cac10f8e17e4..efab4769de4e 100644
> > --- a/fs/smb/client/cifsglob.h
> > +++ b/fs/smb/client/cifsglob.h
> > @@ -1373,6 +1373,7 @@ struct cifs_open_parms {
> >         struct cifs_fid *fid;
> >         umode_t mode;
> >         bool reconnect:1;
> > +       bool replay:1; /* indicates that this open is for a replay */
> >         struct kvec *ea_cctx;
> >  };
> >
> > diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> > index 63485078a6df..22bd01e7bf6e 100644
> > --- a/fs/smb/client/smb2inode.c
> > +++ b/fs/smb/client/smb2inode.c
> > @@ -203,6 +203,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
> >         oplock = SMB2_OPLOCK_LEVEL_NONE;
> >         num_rqst = 0;
> >         server = cifs_pick_channel(ses);
> > +       oparms->replay = !!(retries);
> >
> >         vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
> >         if (vars == NULL)
> > diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> > index 8d674aef8dd9..c0da1935b0bd 100644
> > --- a/fs/smb/client/smb2ops.c
> > +++ b/fs/smb/client/smb2ops.c
> > @@ -1205,6 +1205,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > @@ -1570,6 +1571,7 @@ smb2_ioctl_query_info(const unsigned int xid,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, create_options),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         if (qi.flags & PASSTHRU_FSCTL) {
> > @@ -2296,6 +2298,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > @@ -2682,6 +2685,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
> >                 .disposition = FILE_OPEN,
> >                 .create_options = cifs_create_options(cifs_sb, 0),
> >                 .fid = &fid,
> > +               .replay = !!(retries),
> >         };
> >
> >         rc = SMB2_open_init(tcon, server,
> > diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> > index 2ecc5f210329..1ce9be3a7ca7 100644
> > --- a/fs/smb/client/smb2pdu.c
> > +++ b/fs/smb/client/smb2pdu.c
> > @@ -2406,8 +2406,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
> >          */
> >         buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
> >         buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
> > -       generate_random_uuid(buf->dcontext.CreateGuid);
> > -       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > +
> > +       /* for replay, we should not overwrite the existing create guid */
> > +       if (!oparms->replay) {
> > +               generate_random_uuid(buf->dcontext.CreateGuid);
> > +               memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > +       } else
> > +               memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
> >
> >         /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
> >         buf->Name[0] = 'D';
> > @@ -3156,6 +3161,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> >         /* reinitialize for possible replay */
> >         flags = 0;
> >         server = cifs_pick_channel(ses);
> > +       oparms->replay = !!(retries);
> >
> >         cifs_dbg(FYI, "create/open\n");
> >         if (!ses || !server)
> > --
> > 2.34.1
> >
>
>
> --
> Thanks,
>
> Steve
Steve French Feb. 10, 2024, 7:08 p.m. UTC | #3
updated patch attached - rebased to work around Paulo's change and
removed the update to smb2inode.c compounding due to dependency on a
later patch, and tentatively merged to cifs-2.6.git for-next pending
testing

On Sat, Feb 10, 2024 at 10:42 AM Shyam Prasad N <nspmangalore@gmail.com> wrote:
>
> On Sat, Feb 10, 2024 at 11:52 AM Steve French <smfrench@gmail.com> wrote:
> >
> > It needed a small rebase to work around one of Paulo's patches which
> > it depended on (which is for 6.9-rc) but was wondering if you want
> > this patch in before 6.9 because its change to smb2_compound_op below
> > has a dependency on another patch - can that change be safely removed?
> >
> It will be good to have this in 6.8-rc4, if it will be accepted. It's
> the same small change made in several places.
> It avoids a possible handle leak on the server.
>
> > replay_again:
> >         /* reinitialize for possible replay */
> >         flags = 0;
> >         oplock = SMB2_OPLOCK_LEVEL_NONE;
> >         num_rqst = 0;
> >         server = cifs_pick_channel(ses);
> >         oparms->replay = !!(retries);
> >
> > On Fri, Feb 9, 2024 at 5:25 AM <nspmangalore@gmail.com> wrote:
> > >
> > > From: Shyam Prasad N <sprasad@microsoft.com>
> > >
> > > File open requests made to the server contain a
> > > CreateGuid, which is used by the server to identify
> > > the open request. If the same request needs to be
> > > replayed, it needs to be sent with the same CreateGuid
> > > in the durable handle v2 context.
> > >
> > > Without doing so, we could end up leaking handles on
> > > the server when:
> > > 1. multichannel is used AND
> > > 2. connection goes down, but not for all channels
> > >
> > > This is because the replayed open request would have a
> > > new CreateGuid and the server will treat this as a new
> > > request and open a new handle.
> > >
> > > This change fixes this by reusing the existing create_guid
> > > stored in the cached fid struct.
> > >
> > > REF: MS-SMB2 4.9 Replay Create Request on an Alternate Channel
> > >
> > > Fixes: 4f1fffa23769 ("cifs: commands that are retried should have replay flag set")
> > > Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
> > > ---
> > >  fs/smb/client/cached_dir.c |  1 +
> > >  fs/smb/client/cifsglob.h   |  1 +
> > >  fs/smb/client/smb2inode.c  |  1 +
> > >  fs/smb/client/smb2ops.c    |  4 ++++
> > >  fs/smb/client/smb2pdu.c    | 10 ++++++++--
> > >  5 files changed, 15 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
> > > index 1daeb5714faa..3de5047a7ff9 100644
> > > --- a/fs/smb/client/cached_dir.c
> > > +++ b/fs/smb/client/cached_dir.c
> > > @@ -242,6 +242,7 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
> > >                 .desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
> > >                 .disposition = FILE_OPEN,
> > >                 .fid = pfid,
> > > +               .replay = !!(retries),
> > >         };
> > >
> > >         rc = SMB2_open_init(tcon, server,
> > > diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
> > > index cac10f8e17e4..efab4769de4e 100644
> > > --- a/fs/smb/client/cifsglob.h
> > > +++ b/fs/smb/client/cifsglob.h
> > > @@ -1373,6 +1373,7 @@ struct cifs_open_parms {
> > >         struct cifs_fid *fid;
> > >         umode_t mode;
> > >         bool reconnect:1;
> > > +       bool replay:1; /* indicates that this open is for a replay */
> > >         struct kvec *ea_cctx;
> > >  };
> > >
> > > diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
> > > index 63485078a6df..22bd01e7bf6e 100644
> > > --- a/fs/smb/client/smb2inode.c
> > > +++ b/fs/smb/client/smb2inode.c
> > > @@ -203,6 +203,7 @@ static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
> > >         oplock = SMB2_OPLOCK_LEVEL_NONE;
> > >         num_rqst = 0;
> > >         server = cifs_pick_channel(ses);
> > > +       oparms->replay = !!(retries);
> > >
> > >         vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
> > >         if (vars == NULL)
> > > diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
> > > index 8d674aef8dd9..c0da1935b0bd 100644
> > > --- a/fs/smb/client/smb2ops.c
> > > +++ b/fs/smb/client/smb2ops.c
> > > @@ -1205,6 +1205,7 @@ smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
> > >                 .disposition = FILE_OPEN,
> > >                 .create_options = cifs_create_options(cifs_sb, 0),
> > >                 .fid = &fid,
> > > +               .replay = !!(retries),
> > >         };
> > >
> > >         rc = SMB2_open_init(tcon, server,
> > > @@ -1570,6 +1571,7 @@ smb2_ioctl_query_info(const unsigned int xid,
> > >                 .disposition = FILE_OPEN,
> > >                 .create_options = cifs_create_options(cifs_sb, create_options),
> > >                 .fid = &fid,
> > > +               .replay = !!(retries),
> > >         };
> > >
> > >         if (qi.flags & PASSTHRU_FSCTL) {
> > > @@ -2296,6 +2298,7 @@ smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
> > >                 .disposition = FILE_OPEN,
> > >                 .create_options = cifs_create_options(cifs_sb, 0),
> > >                 .fid = fid,
> > > +               .replay = !!(retries),
> > >         };
> > >
> > >         rc = SMB2_open_init(tcon, server,
> > > @@ -2682,6 +2685,7 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
> > >                 .disposition = FILE_OPEN,
> > >                 .create_options = cifs_create_options(cifs_sb, 0),
> > >                 .fid = &fid,
> > > +               .replay = !!(retries),
> > >         };
> > >
> > >         rc = SMB2_open_init(tcon, server,
> > > diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
> > > index 2ecc5f210329..1ce9be3a7ca7 100644
> > > --- a/fs/smb/client/smb2pdu.c
> > > +++ b/fs/smb/client/smb2pdu.c
> > > @@ -2406,8 +2406,13 @@ create_durable_v2_buf(struct cifs_open_parms *oparms)
> > >          */
> > >         buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
> > >         buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
> > > -       generate_random_uuid(buf->dcontext.CreateGuid);
> > > -       memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > > +
> > > +       /* for replay, we should not overwrite the existing create guid */
> > > +       if (!oparms->replay) {
> > > +               generate_random_uuid(buf->dcontext.CreateGuid);
> > > +               memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
> > > +       } else
> > > +               memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
> > >
> > >         /* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
> > >         buf->Name[0] = 'D';
> > > @@ -3156,6 +3161,7 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
> > >         /* reinitialize for possible replay */
> > >         flags = 0;
> > >         server = cifs_pick_channel(ses);
> > > +       oparms->replay = !!(retries);
> > >
> > >         cifs_dbg(FYI, "create/open\n");
> > >         if (!ses || !server)
> > > --
> > > 2.34.1
> > >
> >
> >
> > --
> > Thanks,
> >
> > Steve
>
>
>
> --
> Regards,
> Shyam
diff mbox series

Patch

diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index 1daeb5714faa..3de5047a7ff9 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -242,6 +242,7 @@  int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
 		.desired_access =  FILE_READ_DATA | FILE_READ_ATTRIBUTES,
 		.disposition = FILE_OPEN,
 		.fid = pfid,
+		.replay = !!(retries),
 	};
 
 	rc = SMB2_open_init(tcon, server,
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index cac10f8e17e4..efab4769de4e 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -1373,6 +1373,7 @@  struct cifs_open_parms {
 	struct cifs_fid *fid;
 	umode_t mode;
 	bool reconnect:1;
+	bool replay:1; /* indicates that this open is for a replay */
 	struct kvec *ea_cctx;
 };
 
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index 63485078a6df..22bd01e7bf6e 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -203,6 +203,7 @@  static int smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
 	oplock = SMB2_OPLOCK_LEVEL_NONE;
 	num_rqst = 0;
 	server = cifs_pick_channel(ses);
+	oparms->replay = !!(retries);
 
 	vars = kzalloc(sizeof(*vars), GFP_ATOMIC);
 	if (vars == NULL)
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index 8d674aef8dd9..c0da1935b0bd 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -1205,6 +1205,7 @@  smb2_set_ea(const unsigned int xid, struct cifs_tcon *tcon,
 		.disposition = FILE_OPEN,
 		.create_options = cifs_create_options(cifs_sb, 0),
 		.fid = &fid,
+		.replay = !!(retries),
 	};
 
 	rc = SMB2_open_init(tcon, server,
@@ -1570,6 +1571,7 @@  smb2_ioctl_query_info(const unsigned int xid,
 		.disposition = FILE_OPEN,
 		.create_options = cifs_create_options(cifs_sb, create_options),
 		.fid = &fid,
+		.replay = !!(retries),
 	};
 
 	if (qi.flags & PASSTHRU_FSCTL) {
@@ -2296,6 +2298,7 @@  smb2_query_dir_first(const unsigned int xid, struct cifs_tcon *tcon,
 		.disposition = FILE_OPEN,
 		.create_options = cifs_create_options(cifs_sb, 0),
 		.fid = fid,
+		.replay = !!(retries),
 	};
 
 	rc = SMB2_open_init(tcon, server,
@@ -2682,6 +2685,7 @@  smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon,
 		.disposition = FILE_OPEN,
 		.create_options = cifs_create_options(cifs_sb, 0),
 		.fid = &fid,
+		.replay = !!(retries),
 	};
 
 	rc = SMB2_open_init(tcon, server,
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 2ecc5f210329..1ce9be3a7ca7 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -2406,8 +2406,13 @@  create_durable_v2_buf(struct cifs_open_parms *oparms)
 	 */
 	buf->dcontext.Timeout = cpu_to_le32(oparms->tcon->handle_timeout);
 	buf->dcontext.Flags = cpu_to_le32(SMB2_DHANDLE_FLAG_PERSISTENT);
-	generate_random_uuid(buf->dcontext.CreateGuid);
-	memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+
+	/* for replay, we should not overwrite the existing create guid */
+	if (!oparms->replay) {
+		generate_random_uuid(buf->dcontext.CreateGuid);
+		memcpy(pfid->create_guid, buf->dcontext.CreateGuid, 16);
+	} else
+		memcpy(buf->dcontext.CreateGuid, pfid->create_guid, 16);
 
 	/* SMB2_CREATE_DURABLE_HANDLE_REQUEST is "DH2Q" */
 	buf->Name[0] = 'D';
@@ -3156,6 +3161,7 @@  SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
 	/* reinitialize for possible replay */
 	flags = 0;
 	server = cifs_pick_channel(ses);
+	oparms->replay = !!(retries);
 
 	cifs_dbg(FYI, "create/open\n");
 	if (!ses || !server)