diff options
Diffstat (limited to 'fs/cifs/smb2misc.c')
-rw-r--r-- | fs/cifs/smb2misc.c | 44 |
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 | |||
634 | void | ||
635 | smb2_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 | |||
648 | int | ||
649 | smb2_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 | } | ||