diff options
author | Ronnie Sahlberg <lsahlber@redhat.com> | 2019-09-09 01:30:00 -0400 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2019-09-16 12:43:38 -0400 |
commit | 496902dc173dead0e5eeba1f2fd4abd9ba6f2da0 (patch) | |
tree | 196a00f93a641cb5e1cc4c9981c1e24dcfae66bb | |
parent | 563317ec3083f7e126d7e30821ff8505ac338ee5 (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.h | 2 | ||||
-rw-r--r-- | fs/cifs/file.c | 36 | ||||
-rw-r--r-- | fs/cifs/smb2inode.c | 28 |
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, | |||
140 | extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, | 140 | extern int cifs_get_writable_path(struct cifs_tcon *tcon, const char *name, |
141 | struct cifsFileInfo **ret_file); | 141 | struct cifsFileInfo **ret_file); |
142 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); | 142 | extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *, bool); |
143 | extern int cifs_get_readable_path(struct cifs_tcon *tcon, const char *name, | ||
144 | struct cifsFileInfo **ret_file); | ||
143 | extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); | 145 | extern unsigned int smbCalcSize(void *buf, struct TCP_Server_Info *server); |
144 | extern int decode_negTokenInit(unsigned char *security_blob, int length, | 146 | extern 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 | ||
2011 | int | ||
2012 | cifs_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 | |||
2011 | static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) | 2047 | static 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; |