mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-23 02:44:41 +03:00
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 <behlendorf1@llnl.gov> Issue #334
This commit is contained in:
committed by
Brian Behlendorf
parent
aec69371a6
commit
cb2d19010d
@@ -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 = {
|
||||
|
||||
@@ -342,6 +342,15 @@ zpl_truncate_range(struct inode* ip, loff_t start, loff_t end)
|
||||
crfree(cr);
|
||||
}
|
||||
|
||||
#ifdef HAVE_INODE_FALLOCATE
|
||||
static long
|
||||
zpl_fallocate(struct inode *ip, int mode, loff_t offset, loff_t len)
|
||||
{
|
||||
return zpl_fallocate_common(ip, mode, offset, len);
|
||||
}
|
||||
#endif /* HAVE_INODE_FALLOCATE */
|
||||
|
||||
|
||||
const struct inode_operations zpl_inode_operations = {
|
||||
.create = zpl_create,
|
||||
.link = zpl_link,
|
||||
@@ -358,6 +367,9 @@ const struct inode_operations zpl_inode_operations = {
|
||||
.removexattr = generic_removexattr,
|
||||
.listxattr = zpl_xattr_list,
|
||||
.truncate_range = zpl_truncate_range,
|
||||
#ifdef HAVE_INODE_FALLOCATE
|
||||
.fallocate = zpl_fallocate,
|
||||
#endif /* HAVE_INODE_FALLOCATE */
|
||||
};
|
||||
|
||||
const struct inode_operations zpl_dir_inode_operations = {
|
||||
|
||||
Reference in New Issue
Block a user