summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2019-09-09 01:30:00 -0400
committerSteve French <stfrench@microsoft.com>2019-09-16 12:43:38 -0400
commit496902dc173dead0e5eeba1f2fd4abd9ba6f2da0 (patch)
tree196a00f93a641cb5e1cc4c9981c1e24dcfae66bb
parent563317ec3083f7e126d7e30821ff8505ac338ee5 (diff)
cifs: add a helper to find an existing readable handle to a file
and convert smb2_query_path_info() to use it. This will eliminate the need for a SMB2_Create when we already have an open handle that can be used. This will also prevent a oplock break in case the other handle holds a lease. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
-rw-r--r--fs/cifs/cifsproto.h2
-rw-r--r--fs/cifs/file.c36
-rw-r--r--fs/cifs/smb2inode.c28
3 files changed, 61 insertions, 5 deletions
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h
index 7b69037bed24..99b1b1ef558c 100644
--- a/fs/cifs/cifsproto.h
+++ b/fs/cifs/cifsproto.h
@@ -140,6 +140,8 @@ extern int cifs_get_writable_file(struct cifsInodeInfo *cifs_inode,
140extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, 140extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
141 struct cifsFileInfo **ret_file); 141 struct cifsFileInfo **ret_file);
142extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); 142extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool);
143extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
144 struct cifsFileInfo **ret_file);
143extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); 145extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server);
144extern int decode_negTokenInit(unsigned char *security_blob, int length, 146extern int decode_negTokenInit(unsigned char *security_blob, int length,
145 struct TCP_Server_Info *server); 147 struct TCP_Server_Info *server);
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index 6124b1d1ab05..4b95700c507c 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2008,6 +2008,42 @@ cifs_get_writable_path(struct cifs_tcon *tcon, const char *name,
2008 return -ENOENT; 2008 return -ENOENT;
2009} 2009}
2010 2010
2011int
2012cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
2013 struct cifsFileInfo **ret_file)
2014{
2015 struct list_head *tmp;
2016 struct cifsFileInfo *cfile;
2017 struct cifsInodeInfo *cinode;
2018 char *full_path;
2019
2020 *ret_file = NULL;
2021
2022 spin_lock(&tcon->open_file_lock);
2023 list_for_each(tmp, &tcon->openFileList) {
2024 cfile = list_entry(tmp, struct cifsFileInfo,
2025 tlist);
2026 full_path = build_path_from_dentry(cfile->dentry);
2027 if (full_path == NULL) {
2028 spin_unlock(&tcon->open_file_lock);
2029 return -ENOMEM;
2030 }
2031 if (strcmp(full_path, name)) {
2032 kfree(full_path);
2033 continue;
2034 }
2035
2036 kfree(full_path);
2037 cinode = CIFS_I(d_inode(cfile->dentry));
2038 spin_unlock(&tcon->open_file_lock);
2039 *ret_file = find_readable_file(cinode, 0);
2040 return *ret_file ? 0 : -ENOENT;
2041 }
2042
2043 spin_unlock(&tcon->open_file_lock);
2044 return -ENOENT;
2045}
2046
2011static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) 2047static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
2012{ 2048{
2013 struct address_space *mapping = page->mapping; 2049 struct address_space *mapping = page->mapping;
diff --git a/fs/cifs/smb2inode.c b/fs/cifs/smb2inode.c
index 9bb0a5bc38c9..c866555b6278 100644
--- a/fs/cifs/smb2inode.c
+++ b/fs/cifs/smb2inode.c
@@ -125,15 +125,31 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
125 rqst[num_rqst].rq_iov = qi_iov; 125 rqst[num_rqst].rq_iov = qi_iov;
126 rqst[num_rqst].rq_nvec = 1; 126 rqst[num_rqst].rq_nvec = 1;
127 127
128 rc = SMB2_query_info_init(tcon, &rqst[num_rqst], COMPOUND_FID, 128 if (cfile)
129 COMPOUND_FID, FILE_ALL_INFORMATION, 129 rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
130 cfile->fid.persistent_fid,
131 cfile->fid.volatile_fid,
132 FILE_ALL_INFORMATION,
130 SMB2_O_INFO_FILE, 0, 133 SMB2_O_INFO_FILE, 0,
131 sizeof(struct smb2_file_all_info) + 134 sizeof(struct smb2_file_all_info) +
132 PATH_MAX * 2, 0, NULL); 135 PATH_MAX * 2, 0, NULL);
136 else {
137 rc = SMB2_query_info_init(tcon, &rqst[num_rqst],
138 COMPOUND_FID,
139 COMPOUND_FID,
140 FILE_ALL_INFORMATION,
141 SMB2_O_INFO_FILE, 0,
142 sizeof(struct smb2_file_all_info) +
143 PATH_MAX * 2, 0, NULL);
144 if (!rc) {
145 smb2_set_next_command(tcon, &rqst[num_rqst]);
146 smb2_set_related(&rqst[num_rqst]);
147 }
148 }
149
133 if (rc) 150 if (rc)
134 goto finished; 151 goto finished;
135 smb2_set_next_command(tcon, &rqst[num_rqst]); 152 num_rqst++;
136 smb2_set_related(&rqst[num_rqst++]);
137 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid, 153 trace_smb3_query_info_compound_enter(xid, ses->Suid, tcon->tid,
138 full_path); 154 full_path);
139 break; 155 break;
@@ -421,6 +437,7 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
421 __u32 create_options = 0; 437 __u32 create_options = 0;
422 struct cifs_fid fid; 438 struct cifs_fid fid;
423 bool no_cached_open = tcon->nohandlecache; 439 bool no_cached_open = tcon->nohandlecache;
440 struct cifsFileInfo *cfile;
424 441
425 *adjust_tz = false; 442 *adjust_tz = false;
426 *symlink = false; 443 *symlink = false;
@@ -452,9 +469,10 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
452 if (backup_cred(cifs_sb)) 469 if (backup_cred(cifs_sb))
453 create_options |= CREATE_OPEN_BACKUP_INTENT; 470 create_options |= CREATE_OPEN_BACKUP_INTENT;
454 471
472 cifs_get_readable_path(tcon, full_path, &cfile);
455 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path, 473 rc = smb2_compound_op(xid, tcon, cifs_sb, full_path,
456 FILE_READ_ATTRIBUTES, FILE_OPEN, create_options, 474 FILE_READ_ATTRIBUTES, FILE_OPEN, create_options,
457 smb2_data, SMB2_OP_QUERY_INFO, NULL); 475 smb2_data, SMB2_OP_QUERY_INFO, cfile);
458 if (rc == -EOPNOTSUPP) { 476 if (rc == -EOPNOTSUPP) {
459 *symlink = true; 477 *symlink = true;
460 create_options |= OPEN_REPARSE_POINT; 478 create_options |= OPEN_REPARSE_POINT;