cifs: update the same create_guid on replay
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: 4f1fffa237
("cifs: commands that are retried should have replay flag set")
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
cffe487026
commit
79520587fe
@ -242,6 +242,7 @@ replay_again:
|
||||
.desired_access = FILE_READ_DATA | FILE_READ_ATTRIBUTES,
|
||||
.disposition = FILE_OPEN,
|
||||
.fid = pfid,
|
||||
.replay = !!(retries),
|
||||
};
|
||||
|
||||
rc = SMB2_open_init(tcon, server,
|
||||
|
@ -1378,6 +1378,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 cifs_fid {
|
||||
|
@ -1204,6 +1204,7 @@ replay_again:
|
||||
.disposition = FILE_OPEN,
|
||||
.create_options = cifs_create_options(cifs_sb, 0),
|
||||
.fid = &fid,
|
||||
.replay = !!(retries),
|
||||
};
|
||||
|
||||
rc = SMB2_open_init(tcon, server,
|
||||
@ -1569,6 +1570,7 @@ replay_again:
|
||||
.disposition = FILE_OPEN,
|
||||
.create_options = cifs_create_options(cifs_sb, create_options),
|
||||
.fid = &fid,
|
||||
.replay = !!(retries),
|
||||
};
|
||||
|
||||
if (qi.flags & PASSTHRU_FSCTL) {
|
||||
@ -2295,6 +2297,7 @@ replay_again:
|
||||
.disposition = FILE_OPEN,
|
||||
.create_options = cifs_create_options(cifs_sb, 0),
|
||||
.fid = fid,
|
||||
.replay = !!(retries),
|
||||
};
|
||||
|
||||
rc = SMB2_open_init(tcon, server,
|
||||
@ -2681,6 +2684,7 @@ replay_again:
|
||||
.disposition = FILE_OPEN,
|
||||
.create_options = cifs_create_options(cifs_sb, 0),
|
||||
.fid = &fid,
|
||||
.replay = !!(retries),
|
||||
};
|
||||
|
||||
rc = SMB2_open_init(tcon, server,
|
||||
|
@ -2404,8 +2404,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';
|
||||
@ -3142,6 +3147,7 @@ replay_again:
|
||||
/* reinitialize for possible replay */
|
||||
flags = 0;
|
||||
server = cifs_pick_channel(ses);
|
||||
oparms->replay = !!(retries);
|
||||
|
||||
cifs_dbg(FYI, "create/open\n");
|
||||
if (!ses || !server)
|
||||
|
Loading…
Reference in New Issue
Block a user