aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb2misc.c')
-rw-r--r--fs/cifs/smb2misc.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/fs/cifs/smb2misc.c b/fs/cifs/smb2misc.c
index e5bc85e49be7..76ccf20fbfb7 100644
--- a/fs/cifs/smb2misc.c
+++ b/fs/cifs/smb2misc.c
@@ -630,3 +630,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
630 cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n"); 630 cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
631 return false; 631 return false;
632} 632}
633
634void
635smb2_cancelled_close_fid(struct work_struct *work)
636{
637 struct close_cancelled_open *cancelled = container_of(work,
638 struct close_cancelled_open, work);
639
640 cifs_dbg(VFS, "Close unmatched open\n");
641
642 SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
643 cancelled->fid.volatile_fid);
644 cifs_put_tcon(cancelled->tcon);
645 kfree(cancelled);
646}
647
648int
649smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
650{
651 struct smb2_hdr *hdr = (struct smb2_hdr *)buffer;
652 struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
653 struct cifs_tcon *tcon;
654 struct close_cancelled_open *cancelled;
655
656 if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS)
657 return 0;
658
659 cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
660 if (!cancelled)
661 return -ENOMEM;
662
663 tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId);
664 if (!tcon) {
665 kfree(cancelled);
666 return -ENOENT;
667 }
668
669 cancelled->fid.persistent_fid = rsp->PersistentFileId;
670 cancelled->fid.volatile_fid = rsp->VolatileFileId;
671 cancelled->tcon = tcon;
672 INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
673 queue_work(cifsiod_wq, &cancelled->work);
674
675 return 0;
676}