Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux semantics for fallocate() #2499

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions config/kernel-truncate-pagecache-range.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
dnl #
dnl # 3.4 API Change
dnl # Added truncate_pagecache_range() function.
dnl #
AC_DEFUN([ZFS_AC_KERNEL_TRUNCATE_PAGECACHE_RANGE],
[AC_MSG_CHECKING([whether truncate_pagecache_range() is available])
ZFS_LINUX_TRY_COMPILE_SYMBOL([
#include <linux/mm.h>
], [
truncate_pagecache_range(NULL, 0, 0);
], [truncate_pagecache_range], [mm/truncate.c], [
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_TRUNCATE_PAGECACHE_RANGE, 1,
[truncate_pagecache_range() is available])
], [
AC_MSG_RESULT(no)
])
])
1 change: 1 addition & 0 deletions config/kernel.m4
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
ZFS_AC_KERNEL_MKDIR_UMODE_T
ZFS_AC_KERNEL_LOOKUP_NAMEIDATA
ZFS_AC_KERNEL_CREATE_NAMEIDATA
ZFS_AC_KERNEL_TRUNCATE_PAGECACHE_RANGE
ZFS_AC_KERNEL_TRUNCATE_RANGE
ZFS_AC_KERNEL_AUTOMOUNT
ZFS_AC_KERNEL_ENCODE_FH_WITH_INODE
Expand Down
31 changes: 31 additions & 0 deletions include/linux/vfs_compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,37 @@ truncate_setsize(struct inode *ip, loff_t new)
}
#endif /* HAVE_TRUNCATE_SETSIZE */

/*
* 3.4 API change,
* Add truncate_pagecache_range if it is not exported by the Linux kernel.
*
* Comment from the Linux kernel sources:
*
* This function should typically be called before the filesystem
* releases resources associated with the freed range (eg. deallocates
* blocks). This way, pagecache will always stay logically coherent
* with on-disk format, and the filesystem would not have to deal with
* situations such as writepage being called for a page that has already
* had its underlying blocks deallocated.
*/
#ifndef HAVE_TRUNCATE_PAGECACHE_RANGE
static inline void
truncate_pagecache_range(struct inode *ip, loff_t off, loff_t endoff)
{
struct address_space *mapping = ip->i_mapping;
loff_t unmap_start, unmap_end;

ASSERT(ISP2(PAGE_SIZE));
unmap_start = roundup(off, PAGE_SIZE);
unmap_end = ((1 + endoff) & (PAGE_SIZE - 1)) - 1;

if ((uint64_t)unmap_end > (uint64_t)unmap_start)
unmap_mapping_range(mapping, unmap_start,
1 + unmap_end - unmap_start, 0);
truncate_inode_pages_range(mapping, off, endoff);
}
#endif /* HAVE_TRUNCATE_PAGECACHE_RANGE */

#if defined(HAVE_BDI) && !defined(HAVE_BDI_SETUP_AND_REGISTER)
/*
* 2.6.34 API change,
Expand Down
21 changes: 21 additions & 0 deletions module/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -486,22 +486,43 @@ zpl_fallocate_common(struct inode *ip, int mode, loff_t offset, loff_t len)
cred_t *cr = CRED();
int error = -EOPNOTSUPP;

#ifdef FALLOC_FL_PUNCH_HOLE
if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
#else
if (mode & FALLOC_FL_KEEP_SIZE)
#endif
return (-EOPNOTSUPP);

crhold(cr);

#ifdef FALLOC_FL_PUNCH_HOLE
if (mode & FALLOC_FL_PUNCH_HOLE) {
flock64_t bf;
loff_t olen;

if (len <= 0)
return (-EINVAL);

spl_inode_lock(ip);
olen = i_size_read(ip);

if (offset > olen) {
spl_inode_unlock(ip);
return (0);
}
if (offset + len > olen)
len = olen - offset;
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);
if (!error)
truncate_pagecache_range(ip, offset,
offset + len - 1);
spl_inode_unlock(ip);
}
#endif /* FALLOC_FL_PUNCH_HOLE */

Expand Down