summaryrefslogtreecommitdiff
path: root/fs/cifs/file.c
diff options
context:
space:
mode:
authorRonnie Sahlberg <lsahlber@redhat.com>2019-09-09 08:30:00 +0300
committerSteve French <stfrench@microsoft.com>2019-09-16 19:43:38 +0300
commit496902dc173dead0e5eeba1f2fd4abd9ba6f2da0 (patch)
tree196a00f93a641cb5e1cc4c9981c1e24dcfae66bb /fs/cifs/file.c
parent563317ec3083f7e126d7e30821ff8505ac338ee5 (diff)
downloadlinux-496902dc173dead0e5eeba1f2fd4abd9ba6f2da0.tar.xz
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>
Diffstat (limited to 'fs/cifs/file.c')
-rw-r--r--fs/cifs/file.c36
1 files changed, 36 insertions, 0 deletions
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,
return -ENOENT;
}
+int
+cifs_get_readable_path(struct cifs_tcon *tcon, const char *name,
+ struct cifsFileInfo **ret_file)
+{
+ struct list_head *tmp;
+ struct cifsFileInfo *cfile;
+ struct cifsInodeInfo *cinode;
+ char *full_path;
+
+ *ret_file = NULL;
+
+ spin_lock(&tcon->open_file_lock);
+ list_for_each(tmp, &tcon->openFileList) {
+ cfile = list_entry(tmp, struct cifsFileInfo,
+ tlist);
+ full_path = build_path_from_dentry(cfile->dentry);
+ if (full_path == NULL) {
+ spin_unlock(&tcon->open_file_lock);
+ return -ENOMEM;
+ }
+ if (strcmp(full_path, name)) {
+ kfree(full_path);
+ continue;
+ }
+
+ kfree(full_path);
+ cinode = CIFS_I(d_inode(cfile->dentry));
+ spin_unlock(&tcon->open_file_lock);
+ *ret_file = find_readable_file(cinode, 0);
+ return *ret_file ? 0 : -ENOENT;
+ }
+
+ spin_unlock(&tcon->open_file_lock);
+ return -ENOENT;
+}
+
static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to)
{
struct address_space *mapping = page->mapping;