summaryrefslogtreecommitdiffstats
path: root/fs/cifs/inode.c
diff options
context:
space:
mode:
authorRonnie Sahlberg2019-04-25 08:45:29 +0200
committerSteve French2019-05-08 06:24:55 +0200
commit2f3ebaba13cebd8badfb9aed31c0cf3cc82eb4f4 (patch)
treecd2e5193de15784d7e50ce1a42d2a55ae8727f5f /fs/cifs/inode.c
parentSMB3: Add defines for new negotiate contexts (diff)
downloadkernel-qcow2-linux-2f3ebaba13cebd8badfb9aed31c0cf3cc82eb4f4.tar.gz
kernel-qcow2-linux-2f3ebaba13cebd8badfb9aed31c0cf3cc82eb4f4.tar.xz
kernel-qcow2-linux-2f3ebaba13cebd8badfb9aed31c0cf3cc82eb4f4.zip
cifs: add fiemap support
Useful for improved copy performance as well as for applications which query allocated ranges of sparse files. Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs/inode.c')
-rw-r--r--fs/cifs/inode.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c
index 538fd7d807e4..d7cc62252634 100644
--- a/fs/cifs/inode.c
+++ b/fs/cifs/inode.c
@@ -2116,6 +2116,43 @@ int cifs_getattr(const struct path *path, struct kstat *stat,
return rc;
}
+int cifs_fiemap(struct inode *inode, struct fiemap_extent_info *fei, u64 start,
+ u64 len)
+{
+ struct cifsInodeInfo *cifs_i = CIFS_I(inode);
+ struct cifs_sb_info *cifs_sb = CIFS_SB(cifs_i->vfs_inode.i_sb);
+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
+ struct TCP_Server_Info *server = tcon->ses->server;
+ struct cifsFileInfo *cfile;
+ int rc;
+
+ /*
+ * We need to be sure that all dirty pages are written as they
+ * might fill holes on the server.
+ */
+ if (!CIFS_CACHE_READ(CIFS_I(inode)) && inode->i_mapping &&
+ inode->i_mapping->nrpages != 0) {
+ rc = filemap_fdatawait(inode->i_mapping);
+ if (rc) {
+ mapping_set_error(inode->i_mapping, rc);
+ return rc;
+ }
+ }
+
+ cfile = find_readable_file(cifs_i, false);
+ if (cfile == NULL)
+ return -EINVAL;
+
+ if (server->ops->fiemap) {
+ rc = server->ops->fiemap(tcon, cfile, fei, start, len);
+ cifsFileInfo_put(cfile);
+ return rc;
+ }
+
+ cifsFileInfo_put(cfile);
+ return -ENOTSUPP;
+}
+
static int cifs_truncate_page(struct address_space *mapping, loff_t from)
{
pgoff_t index = from >> PAGE_SHIFT;