diff options
author | Ronnie Sahlberg <lsahlber@redhat.com> | 2019-11-14 19:32:12 +0100 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-11-25 08:14:53 +0100 |
commit | 87bc2376fffae6821869c988edbb45a14527b258 (patch) | |
tree | 3fd6d6474e8e280d39adfe08af937b02c0adbf14 /fs/cifs | |
parent | CIFS: Do not miss cancelled OPEN responses (diff) | |
download | linux-87bc2376fffae6821869c988edbb45a14527b258.tar.xz linux-87bc2376fffae6821869c988edbb45a14527b258.zip |
smb3: add debug messages for closing unmatched open
Helps distinguish between an interrupted close and a truly
unmatched open.
Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/cifsglob.h | 2 | ||||
-rw-r--r-- | fs/cifs/smb2misc.c | 42 |
2 files changed, 34 insertions, 10 deletions
diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 5d2dd04b55a6..57453226469d 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1552,6 +1552,8 @@ struct close_cancelled_open { struct cifs_fid fid; struct cifs_tcon *tcon; struct work_struct work; + __u64 mid; + __u16 cmd; }; /* Make code in transport.c a little cleaner by moving diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c index 5668fb7d94e5..289915f0915d 100644 --- a/fs/cifs/smb2misc.c +++ b/fs/cifs/smb2misc.c @@ -729,19 +729,35 @@ smb2_cancelled_close_fid(struct work_struct *work) { struct close_cancelled_open *cancelled = container_of(work, struct close_cancelled_open, work); + struct cifs_tcon *tcon = cancelled->tcon; + int rc; + + if (cancelled->mid) + cifs_tcon_dbg(VFS, "Close unmatched open for MID:%llx\n", + cancelled->mid); + else + cifs_tcon_dbg(VFS, "Close interrupted close\n"); - cifs_dbg(VFS, "Close unmatched open\n"); + rc = SMB2_close(0, tcon, cancelled->fid.persistent_fid, + cancelled->fid.volatile_fid); + if (rc) + cifs_tcon_dbg(VFS, "Close cancelled mid failed rc:%d\n", rc); - SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid, - cancelled->fid.volatile_fid); - cifs_put_tcon(cancelled->tcon); + cifs_put_tcon(tcon); kfree(cancelled); } -/* Caller should already has an extra reference to @tcon */ +/* + * Caller should already has an extra reference to @tcon + * This function is used to queue work to close a handle to prevent leaks + * on the server. + * We handle two cases. If an open was interrupted after we sent the + * SMB2_CREATE to the server but before we processed the reply, and second + * if a close was interrupted before we sent the SMB2_CLOSE to the server. + */ static int -__smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, - __u64 volatile_fid) +__smb2_handle_cancelled_cmd(struct cifs_tcon *tcon, __u16 cmd, __u64 mid, + __u64 persistent_fid, __u64 volatile_fid) { struct close_cancelled_open *cancelled; @@ -752,6 +768,8 @@ __smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, cancelled->fid.persistent_fid = persistent_fid; cancelled->fid.volatile_fid = volatile_fid; cancelled->tcon = tcon; + cancelled->cmd = cmd; + cancelled->mid = mid; INIT_WORK(&cancelled->work, smb2_cancelled_close_fid); WARN_ON(queue_work(cifsiod_wq, &cancelled->work) == false); @@ -769,7 +787,8 @@ smb2_handle_cancelled_close(struct cifs_tcon *tcon, __u64 persistent_fid, tcon->tc_count++; spin_unlock(&cifs_tcp_ses_lock); - rc = __smb2_handle_cancelled_close(tcon, persistent_fid, volatile_fid); + rc = __smb2_handle_cancelled_cmd(tcon, SMB2_CLOSE_HE, 0, + persistent_fid, volatile_fid); if (rc) cifs_put_tcon(tcon); @@ -793,8 +812,11 @@ smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server) if (!tcon) return -ENOENT; - rc = __smb2_handle_cancelled_close(tcon, rsp->PersistentFileId, - rsp->VolatileFileId); + rc = __smb2_handle_cancelled_cmd(tcon, + le16_to_cpu(sync_hdr->Command), + le64_to_cpu(sync_hdr->MessageId), + rsp->PersistentFileId, + rsp->VolatileFileId); if (rc) cifs_put_tcon(tcon); |