From 8de9e86c67baa71c661b9ba59a4e23210d98bc79 Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Fri, 30 Aug 2019 08:25:46 +1000 Subject: cifs: create a helper to find a writeable handle by path name rename() takes a path for old_file and in SMB2 we used to just create a compound for create(old_path)/rename/close(). If we already have a writable handle we can avoid the create() and close() altogether and just use the existing handle. For this situation, as we avoid doing the create() we also avoid triggering an oplock break for the existing handle. Signed-off-by: Ronnie Sahlberg Signed-off-by: Steve French --- fs/cifs/file.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'fs/cifs/file.c') diff --git a/fs/cifs/file.c b/fs/cifs/file.c index f16f6d2b5217..6124b1d1ab05 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1973,6 +1973,41 @@ find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) return cfile; } +int +cifs_get_writable_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); + return cifs_get_writable_file(cinode, 0, ret_file); + } + + 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; -- cgit v1.2.3-59-g8ed1b