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:
Etienne Dechamps
2011-09-02 09:42:07 +02:00
committed by Brian Behlendorf
parent aec69371a6
commit cb2d19010d
61 changed files with 447 additions and 0 deletions
+47
View File
@@ -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 = {
+12
View File
@@ -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 = {