aboutsummaryrefslogtreecommitdiffstats
path: root/fs/cifs/smb2pdu.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/cifs/smb2pdu.c')
-rw-r--r--fs/cifs/smb2pdu.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index f58e4dc3987b..c8cd7b6cdda2 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -1873,10 +1873,21 @@ create_reconnect_durable_buf(struct cifs_fid *fid)
1873 return buf; 1873 return buf;
1874} 1874}
1875 1875
1876__u8 1876static void
1877smb2_parse_lease_state(struct TCP_Server_Info *server, 1877parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf)
1878{
1879 struct create_on_disk_id *pdisk_id = (struct create_on_disk_id *)cc;
1880
1881 cifs_dbg(FYI, "parse query id context 0x%llx 0x%llx\n",
1882 pdisk_id->DiskFileId, pdisk_id->VolumeId);
1883 buf->IndexNumber = pdisk_id->DiskFileId;
1884}
1885
1886void
1887smb2_parse_contexts(struct TCP_Server_Info *server,
1878 struct smb2_create_rsp *rsp, 1888 struct smb2_create_rsp *rsp,
1879 unsigned int *epoch, char *lease_key) 1889 unsigned int *epoch, char *lease_key, __u8 *oplock,
1890 struct smb2_file_all_info *buf)
1880{ 1891{
1881 char *data_offset; 1892 char *data_offset;
1882 struct create_context *cc; 1893 struct create_context *cc;
@@ -1884,15 +1895,24 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
1884 unsigned int remaining; 1895 unsigned int remaining;
1885 char *name; 1896 char *name;
1886 1897
1898 *oplock = 0;
1887 data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); 1899 data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
1888 remaining = le32_to_cpu(rsp->CreateContextsLength); 1900 remaining = le32_to_cpu(rsp->CreateContextsLength);
1889 cc = (struct create_context *)data_offset; 1901 cc = (struct create_context *)data_offset;
1902
1903 /* Initialize inode number to 0 in case no valid data in qfid context */
1904 if (buf)
1905 buf->IndexNumber = 0;
1906
1890 while (remaining >= sizeof(struct create_context)) { 1907 while (remaining >= sizeof(struct create_context)) {
1891 name = le16_to_cpu(cc->NameOffset) + (char *)cc; 1908 name = le16_to_cpu(cc->NameOffset) + (char *)cc;
1892 if (le16_to_cpu(cc->NameLength) == 4 && 1909 if (le16_to_cpu(cc->NameLength) == 4 &&
1893 strncmp(name, "RqLs", 4) == 0) 1910 strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
1894 return server->ops->parse_lease_buf(cc, epoch, 1911 *oplock = server->ops->parse_lease_buf(cc, epoch,
1895 lease_key); 1912 lease_key);
1913 else if (buf && (le16_to_cpu(cc->NameLength) == 4) &&
1914 strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0)
1915 parse_query_id_ctxt(cc, buf);
1896 1916
1897 next = le32_to_cpu(cc->Next); 1917 next = le32_to_cpu(cc->Next);
1898 if (!next) 1918 if (!next)
@@ -1901,7 +1921,10 @@ smb2_parse_lease_state(struct TCP_Server_Info *server,
1901 cc = (struct create_context *)((char *)cc + next); 1921 cc = (struct create_context *)((char *)cc + next);
1902 } 1922 }
1903 1923
1904 return 0; 1924 if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
1925 *oplock = rsp->OplockLevel;
1926
1927 return;
1905} 1928}
1906 1929
1907static int 1930static int
@@ -2588,12 +2611,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path,
2588 buf->DeletePending = 0; 2611 buf->DeletePending = 0;
2589 } 2612 }
2590 2613
2591 if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) 2614
2592 *oplock = smb2_parse_lease_state(server, rsp, 2615 smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
2593 &oparms->fid->epoch, 2616 oparms->fid->lease_key, oplock, buf);
2594 oparms->fid->lease_key);
2595 else
2596 *oplock = rsp->OplockLevel;
2597creat_exit: 2617creat_exit:
2598 SMB2_open_free(&rqst); 2618 SMB2_open_free(&rqst);
2599 free_rsp_buf(resp_buftype, rsp); 2619 free_rsp_buf(resp_buftype, rsp);