summaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorEtienne Dechamps <[email protected]>2011-09-01 13:59:41 +0200
committerBrian Behlendorf <[email protected]>2012-02-09 15:20:32 -0800
commit5cb63a57f8d2d1a94e65b4710bfbb221b1a71700 (patch)
tree29217086ca4df5c495526cffa0b661563a5c1577 /module/zfs
parent93648f314c258897a0fa72b0d0b164e1937a5b63 (diff)
Implement the truncate_range() inode operation.
This operation allows "hole punching" in ZFS files. On Solaris this is done via the vop_space() system call, which maps to the zfs_space() function. So we just need to write zpl_truncate_range() as a wrapper around zfs_space(). Note that this only works for regular files, not ZVOLs. This is currently an insecure implementation without permission checking, although this isn't that big of a deal since truncate_range() isn't even callable from userspace. Signed-off-by: Brian Behlendorf <[email protected]> Issue #334
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/zpl_inode.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/module/zfs/zpl_inode.c b/module/zfs/zpl_inode.c
index 46b77c9f1..2d197a488 100644
--- a/module/zfs/zpl_inode.c
+++ b/module/zfs/zpl_inode.c
@@ -315,6 +315,33 @@ out:
return (error);
}
+static void
+zpl_truncate_range(struct inode* ip, loff_t start, loff_t end)
+{
+ cred_t *cr = CRED();
+ flock64_t bf;
+
+ ASSERT3S(start, <=, end);
+
+ /*
+ * zfs_freesp() will interpret (len == 0) as meaning "truncate until
+ * the end of the file". We don't want that.
+ */
+ if (start == end)
+ return;
+
+ crhold(cr);
+
+ bf.l_type = F_WRLCK;
+ bf.l_whence = 0;
+ bf.l_start = start;
+ bf.l_len = end - start;
+ bf.l_pid = 0;
+ zfs_space(ip, F_FREESP, &bf, FWRITE, start, cr);
+
+ crfree(cr);
+}
+
const struct inode_operations zpl_inode_operations = {
.create = zpl_create,
.link = zpl_link,
@@ -330,6 +357,7 @@ const struct inode_operations zpl_inode_operations = {
.getxattr = generic_getxattr,
.removexattr = generic_removexattr,
.listxattr = zpl_xattr_list,
+ .truncate_range = zpl_truncate_range,
};
const struct inode_operations zpl_dir_inode_operations = {