History

Merge tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French: "Two fixes for stable, one that had dependency on earlier patch in this merge window and can now go in, and a perf improvement in SMB3 open" * tag '5.3-smb3-fixes' of git://git.samba.org/sfrench/cifs-2.6: cifs: update internal module number cifs: flush before set-info if we have writeable handles smb3: optimize open to not send query file internal info cifs: copy_file_range needs to strip setuid bits and update timestamps CIFS: fix deadlock in cached root handling

Linus Torvalds committed 7 years ago

Commit 91962d02 parents 8cf6650 2a957ac8 files · +126 −31Browse files

Unified · Split

8 files
  1. fs/cifs/cifsfs.c +8 −3
  2. fs/cifs/cifsfs.h +1 −1
  3. fs/cifs/inode.c +16 −0
  4. fs/cifs/smb2file.c +12 −6
  5. fs/cifs/smb2ops.c +49 −4
  6. fs/cifs/smb2pdu.c +33 −13
  7. fs/cifs/smb2pdu.h +3 −1
  8. fs/cifs/smb2proto.h +4 −3
fs/cifs/cifsfs.c+8−3
@@ -1104,6 +1104,10 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, · 1103 unmodified lines
11041104 goto out;
11051105 }
11061106
1107+ rc = -EOPNOTSUPP;
1108+ if (!target_tcon->ses->server->ops->copychunk_range)
1109+ goto out;
1110+
11071111 /*
11081112 * Note: cifs case is easier than btrfs since server responsible for
11091113 * checks for proper open modes and file type and if it wants
@@ -1115,11 +1119,12 @@ ssize_t cifs_file_copychunk_range(unsigned int xid, · 5 unmodified lines
11151119 /* should we flush first and last page first */
11161120 truncate_inode_pages(&target_inode->i_data, 0);
11171121
1118− if (target_tcon->ses->server->ops->copychunk_range)
1122+ rc = file_modified(dst_file);
1123+ if (!rc)
11191124 rc = target_tcon->ses->server->ops->copychunk_range(xid,
11201125 smb_file_src, smb_file_target, off, len, destoff);
1121− else
1122− rc = -EOPNOTSUPP;
1126+
1127+ file_accessed(src_file);
11231128
11241129 /* force revalidate of size and timestamps of target file now
11251130 * that target is updated on the server
fs/cifs/cifsfs.h+1−1
@@ -152,5 +152,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); · 151 unmodified lines
152152 extern const struct export_operations cifs_export_ops;
153153 #endif /* CONFIG_CIFS_NFSD_EXPORT */
154154
155−#define CIFS_VERSION "2.20"
155+#define CIFS_VERSION "2.21"
156156 #endif /* _CIFSFS_H */
fs/cifs/inode.c+16−0
@@ -2406,6 +2406,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) · 2405 unmodified lines
24062406 struct inode *inode = d_inode(direntry);
24072407 struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
24082408 struct cifsInodeInfo *cifsInode = CIFS_I(inode);
2409+ struct cifsFileInfo *wfile;
2410+ struct cifs_tcon *tcon;
24092411 char *full_path = NULL;
24102412 int rc = -EACCES;
24112413 __u32 dosattr = 0;
@@ -2452,6 +2454,20 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) · 40 unmodified lines
24522454 mapping_set_error(inode->i_mapping, rc);
24532455 rc = 0;
24542456
2457+ if (attrs->ia_valid & ATTR_MTIME) {
2458+ rc = cifs_get_writable_file(cifsInode, false, &wfile);
2459+ if (!rc) {
2460+ tcon = tlink_tcon(wfile->tlink);
2461+ rc = tcon->ses->server->ops->flush(xid, tcon, &wfile->fid);
2462+ cifsFileInfo_put(wfile);
2463+ if (rc)
2464+ return rc;
2465+ } else if (rc != -EBADF)
2466+ return rc;
2467+ else
2468+ rc = 0;
2469+ }
2470+
24552471 if (attrs->ia_valid & ATTR_SIZE) {
24562472 rc = cifs_set_file_size(inode, attrs, xid, full_path);
24572473 if (rc != 0)
fs/cifs/smb2file.c+12−6
@@ -88,14 +88,20 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, · 87 unmodified lines
8888 }
8989
9090 if (buf) {
91− /* open response does not have IndexNumber field - get it */
92− rc = SMB2_get_srv_num(xid, oparms->tcon, fid->persistent_fid,
91+ /* if open response does not have IndexNumber field - get it */
92+ if (smb2_data->IndexNumber == 0) {
93+ rc = SMB2_get_srv_num(xid, oparms->tcon,
94+ fid->persistent_fid,
9395 fid->volatile_fid,
9496 &smb2_data->IndexNumber);
95− if (rc) {
96− /* let get_inode_info disable server inode numbers */
97− smb2_data->IndexNumber = 0;
98− rc = 0;
97+ if (rc) {
98+ /*
99+ * let get_inode_info disable server inode
100+ * numbers
101+ */
102+ smb2_data->IndexNumber = 0;
103+ rc = 0;
104+ }
99105 }
100106 move_smb2_info_to_cifs(buf, smb2_data);
101107 }
fs/cifs/smb2ops.c+49−4
@@ -694,8 +694,51 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) · 693 unmodified lines
694694
695695 smb2_set_related(&rqst[1]);
696696
697+ /*
698+ * We do not hold the lock for the open because in case
699+ * SMB2_open needs to reconnect, it will end up calling
700+ * cifs_mark_open_files_invalid() which takes the lock again
701+ * thus causing a deadlock
702+ */
703+
704+ mutex_unlock(&tcon->crfid.fid_mutex);
697705 rc = compound_send_recv(xid, ses, flags, 2, rqst,
698706 resp_buftype, rsp_iov);
707+ mutex_lock(&tcon->crfid.fid_mutex);
708+
709+ /*
710+ * Now we need to check again as the cached root might have
711+ * been successfully re-opened from a concurrent process
712+ */
713+
714+ if (tcon->crfid.is_valid) {
715+ /* work was already done */
716+
717+ /* stash fids for close() later */
718+ struct cifs_fid fid = {
719+ .persistent_fid = pfid->persistent_fid,
720+ .volatile_fid = pfid->volatile_fid,
721+ };
722+
723+ /*
724+ * caller expects this func to set pfid to a valid
725+ * cached root, so we copy the existing one and get a
726+ * reference.
727+ */
728+ memcpy(pfid, tcon->crfid.fid, sizeof(*pfid));
729+ kref_get(&tcon->crfid.refcount);
730+
731+ mutex_unlock(&tcon->crfid.fid_mutex);
732+
733+ if (rc == 0) {
734+ /* close extra handle outside of crit sec */
735+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
736+ }
737+ goto oshr_free;
738+ }
739+
740+ /* Cached root is still invalid, continue normaly */
741+
699742 if (rc)
700743 goto oshr_exit;
701744
@@ -711,11 +754,12 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) · 9 unmodified lines
711754 tcon->crfid.is_valid = true;
712755 kref_init(&tcon->crfid.refcount);
713756
757+ /* BB TBD check to see if oplock level check can be removed below */
714758 if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
715759 kref_get(&tcon->crfid.refcount);
716− oplock = smb2_parse_lease_state(server, o_rsp,
717− &oparms.fid->epoch,
718− oparms.fid->lease_key);
760+ smb2_parse_contexts(server, o_rsp,
761+ &oparms.fid->epoch,
762+ oparms.fid->lease_key, &oplock, NULL);
719763 } else
720764 goto oshr_exit;
721765
@@ -729,8 +773,9 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid) · 7 unmodified lines
729773 (char *)&tcon->crfid.file_all_info))
730774 tcon->crfid.file_all_info_is_valid = 1;
731775
732− oshr_exit:
776+oshr_exit:
733777 mutex_unlock(&tcon->crfid.fid_mutex);
778+oshr_free:
734779 SMB2_open_free(&rqst[0]);
735780 SMB2_query_info_free(&rqst[1]);
736781 free_rsp_buf(resp_buftype[0], rsp_iov[0].iov_base);
fs/cifs/smb2pdu.c+33−13
@@ -1873,10 +1873,21 @@ create_reconnect_durable_buf(struct cifs_fid *fid) · 1872 unmodified lines
18731873 return buf;
18741874 }
18751875
1876−__u8
1877−smb2_parse_lease_state(struct TCP_Server_Info *server,
1876+static void
1877+parse_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+
1886+void
1887+smb2_parse_contexts(struct TCP_Server_Info *server,
18781888 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)
18801891 {
18811892 char *data_offset;
18821893 struct create_context *cc;
@@ -1884,15 +1895,24 @@ smb2_parse_lease_state(struct TCP_Server_Info *server, · 1 unmodified line
18841895 unsigned int remaining;
18851896 char *name;
18861897
1898+ *oplock = 0;
18871899 data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset);
18881900 remaining = le32_to_cpu(rsp->CreateContextsLength);
18891901 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+
18901907 while (remaining >= sizeof(struct create_context)) {
18911908 name = le16_to_cpu(cc->NameOffset) + (char *)cc;
18921909 if (le16_to_cpu(cc->NameLength) == 4 &&
1893− strncmp(name, "RqLs", 4) == 0)
1894− return server->ops->parse_lease_buf(cc, epoch,
1895− lease_key);
1910+ strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0)
1911+ *oplock = server->ops->parse_lease_buf(cc, epoch,
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);
18961916
18971917 next = le32_to_cpu(cc->Next);
18981918 if (!next)
@@ -1901,7 +1921,10 @@ smb2_parse_lease_state(struct TCP_Server_Info *server, · 2 unmodified lines
19011921 cc = (struct create_context *)((char *)cc + next);
19021922 }
19031923
1904− return 0;
1924+ if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE)
1925+ *oplock = rsp->OplockLevel;
1926+
1927+ return;
19051928 }
19061929
19071930 static int
@@ -2588,12 +2611,9 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, · 680 unmodified lines
25882611 buf->DeletePending = 0;
25892612 }
25902613
2591− if (rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE)
2592− *oplock = smb2_parse_lease_state(server, rsp,
2593− &oparms->fid->epoch,
2594− oparms->fid->lease_key);
2595− else
2596− *oplock = rsp->OplockLevel;
2614+
2615+ smb2_parse_contexts(server, rsp, &oparms->fid->epoch,
2616+ oparms->fid->lease_key, oplock, buf);
25972617 creat_exit:
25982618 SMB2_open_free(&rqst);
25992619 free_rsp_buf(resp_buftype, rsp);
fs/cifs/smb2pdu.h+3−1
@@ -818,7 +818,9 @@ struct durable_reconnect_context_v2 { · 817 unmodified lines
818818 } __packed;
819819
820820 /* See MS-SMB2 2.2.14.2.9 */
821−struct on_disk_id {
821+struct create_on_disk_id {
822+ struct create_context ccontext;
823+ __u8 Name[8];
822824 __le64 DiskFileId;
823825 __le64 VolumeId;
824826 __u32 Reserved[4];
fs/cifs/smb2proto.h+4−3
@@ -228,9 +228,10 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); · 227 unmodified lines
228228
229229 extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *,
230230 enum securityEnum);
231−extern __u8 smb2_parse_lease_state(struct TCP_Server_Info *server,
232− struct smb2_create_rsp *rsp,
233− unsigned int *epoch, char *lease_key);
231+extern void smb2_parse_contexts(struct TCP_Server_Info *server,
232+ struct smb2_create_rsp *rsp,
233+ unsigned int *epoch, char *lease_key,
234+ __u8 *oplock, struct smb2_file_all_info *buf);
234235 extern int smb3_encryption_required(const struct cifs_tcon *tcon);
235236 extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length,
236237 struct kvec *iov, unsigned int min_buf_size);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t