diff options
author | Etienne Dechamps <[email protected]> | 2011-09-01 13:59:41 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2012-02-09 15:20:32 -0800 |
commit | 5cb63a57f8d2d1a94e65b4710bfbb221b1a71700 (patch) | |
tree | 29217086ca4df5c495526cffa0b661563a5c1577 /module/zfs/zpl_inode.c | |
parent | 93648f314c258897a0fa72b0d0b164e1937a5b63 (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/zpl_inode.c')
-rw-r--r-- | module/zfs/zpl_inode.c | 28 |
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 = { |