summaryrefslogtreecommitdiffstats
path: root/module/zfs/zpl_file.c
diff options
context:
space:
mode:
authorEtienne Dechamps <[email protected]>2011-09-02 09:42:07 +0200
committerBrian Behlendorf <[email protected]>2012-02-09 16:19:32 -0800
commitcb2d19010d8fbcf6c22585cd8763fad3ba7db724 (patch)
treeb4fe64638a19856107953dc1a814c2e3f787c989 /module/zfs/zpl_file.c
parentaec69371a6a2e94534809c5e9ba22e7b0e276937 (diff)
Support the fallocate() file operation.
Currently only the (FALLOC_FL_PUNCH_HOLE) flag combination is supported, since it's the only one that matches the behavior of zfs_space(). This makes it pretty much useless in its current form, but it's a start. To support other flag combinations we would need to modify zfs_space() to make it more flexible, or emulate the desired functionality in zpl_fallocate(). Signed-off-by: Brian Behlendorf <[email protected]> Issue #334
Diffstat (limited to 'module/zfs/zpl_file.c')
-rw-r--r--module/zfs/zpl_file.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/module/zfs/zpl_file.c b/module/zfs/zpl_file.c
index 0ef2c1558..5ac41c9d2 100644
--- a/module/zfs/zpl_file.c
+++ b/module/zfs/zpl_file.c
@@ -394,6 +394,50 @@ zpl_writepage(struct page *pp, struct writeback_control *wbc)
return zpl_putpage(pp, wbc, pp->mapping);
}
+/*
+ * The only flag combination which matches the behavior of zfs_space()
+ * is FALLOC_FL_PUNCH_HOLE. This flag was introduced in the 2.6.38 kernel.
+ */
+long
+zpl_fallocate_common(struct inode *ip, int mode, loff_t offset, loff_t len)
+{
+ cred_t *cr = CRED();
+ int error = -EOPNOTSUPP;
+
+ if (mode & FALLOC_FL_KEEP_SIZE)
+ return (-EOPNOTSUPP);
+
+ crhold(cr);
+
+#ifdef FALLOC_FL_PUNCH_HOLE
+ if (mode & FALLOC_FL_PUNCH_HOLE) {
+ flock64_t bf;
+
+ bf.l_type = F_WRLCK;
+ bf.l_whence = 0;
+ bf.l_start = offset;
+ bf.l_len = len;
+ bf.l_pid = 0;
+
+ error = -zfs_space(ip, F_FREESP, &bf, FWRITE, offset, cr);
+ }
+#endif /* FALLOC_FL_PUNCH_HOLE */
+
+ crfree(cr);
+
+ ASSERT3S(error, <=, 0);
+ return (error);
+}
+
+#ifdef HAVE_FILE_FALLOCATE
+static long
+zpl_fallocate(struct file *filp, int mode, loff_t offset, loff_t len)
+{
+ return zpl_fallocate_common(filp->f_path.dentry->d_inode,
+ mode, offset, len);
+}
+#endif /* HAVE_FILE_FALLOCATE */
+
const struct address_space_operations zpl_address_space_operations = {
.readpages = zpl_readpages,
.readpage = zpl_readpage,
@@ -410,6 +454,9 @@ const struct file_operations zpl_file_operations = {
.readdir = zpl_readdir,
.mmap = zpl_mmap,
.fsync = zpl_fsync,
+#ifdef HAVE_FILE_FALLOCATE
+ .fallocate = zpl_fallocate,
+#endif /* HAVE_FILE_FALLOCATE */
};
const struct file_operations zpl_dir_file_operations = {