mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-26 03:09:34 +03:00
Linux: use filemap_range_has_page()
As of the 4.13 kernel filemap_range_has_page() can be used to check if there is a page mapped in a given file range. When available this interface should be used which eliminates the need for the zp->z_is_mapped boolean. Reviewed-by: Brian Atkinson <batkinson@lanl.gov> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #14493
This commit is contained in:
parent
ab672133a9
commit
3fc92adc40
26
config/kernel-filemap.m4
Normal file
26
config/kernel-filemap.m4
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
dnl #
|
||||||
|
dnl # filemap_range_has_page was not available till 4.13
|
||||||
|
dnl #
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_SRC_FILEMAP], [
|
||||||
|
ZFS_LINUX_TEST_SRC([filemap_range_has_page], [
|
||||||
|
#include <linux/fs.h>
|
||||||
|
],[
|
||||||
|
struct address_space *mapping = NULL;
|
||||||
|
loff_t lstart = 0;
|
||||||
|
loff_t lend = 0;
|
||||||
|
bool ret __attribute__ ((unused));
|
||||||
|
|
||||||
|
ret = filemap_range_has_page(mapping, lstart, lend);
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN([ZFS_AC_KERNEL_FILEMAP], [
|
||||||
|
AC_MSG_CHECKING([whether filemap_range_has_page() is available])
|
||||||
|
ZFS_LINUX_TEST_RESULT([filemap_range_has_page], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
AC_DEFINE(HAVE_FILEMAP_RANGE_HAS_PAGE, 1,
|
||||||
|
[filemap_range_has_page() is available])
|
||||||
|
],[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
])
|
||||||
|
])
|
@ -150,6 +150,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [
|
|||||||
ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM
|
ZFS_AC_KERNEL_SRC_USER_NS_COMMON_INUM
|
||||||
ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
|
ZFS_AC_KERNEL_SRC_IDMAP_MNT_API
|
||||||
ZFS_AC_KERNEL_SRC_IATTR_VFSID
|
ZFS_AC_KERNEL_SRC_IATTR_VFSID
|
||||||
|
ZFS_AC_KERNEL_SRC_FILEMAP
|
||||||
|
|
||||||
AC_MSG_CHECKING([for available kernel interfaces])
|
AC_MSG_CHECKING([for available kernel interfaces])
|
||||||
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
|
ZFS_LINUX_TEST_COMPILE_ALL([kabi])
|
||||||
@ -273,6 +274,7 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [
|
|||||||
ZFS_AC_KERNEL_USER_NS_COMMON_INUM
|
ZFS_AC_KERNEL_USER_NS_COMMON_INUM
|
||||||
ZFS_AC_KERNEL_IDMAP_MNT_API
|
ZFS_AC_KERNEL_IDMAP_MNT_API
|
||||||
ZFS_AC_KERNEL_IATTR_VFSID
|
ZFS_AC_KERNEL_IATTR_VFSID
|
||||||
|
ZFS_AC_KERNEL_FILEMAP
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl #
|
dnl #
|
||||||
|
@ -116,7 +116,8 @@ typedef struct zfs_soft_state {
|
|||||||
#define Z_ISLNK(type) ((type) == VLNK)
|
#define Z_ISLNK(type) ((type) == VLNK)
|
||||||
#define Z_ISDIR(type) ((type) == VDIR)
|
#define Z_ISDIR(type) ((type) == VDIR)
|
||||||
|
|
||||||
#define zn_has_cached_data(zp) vn_has_cached_data(ZTOV(zp))
|
#define zn_has_cached_data(zp, start, end) \
|
||||||
|
vn_has_cached_data(ZTOV(zp))
|
||||||
#define zn_flush_cached_data(zp, sync) vn_flush_cached_data(ZTOV(zp), sync)
|
#define zn_flush_cached_data(zp, sync) vn_flush_cached_data(ZTOV(zp), sync)
|
||||||
#define zn_rlimit_fsize(zp, uio) \
|
#define zn_rlimit_fsize(zp, uio) \
|
||||||
vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio))
|
vn_rlimit_fsize(ZTOV(zp), GET_UIO_STRUCT(uio), zfs_uio_td(uio))
|
||||||
|
@ -62,7 +62,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
|
|||||||
__field(uint32_t, z_async_writes_cnt)
|
__field(uint32_t, z_async_writes_cnt)
|
||||||
__field(mode_t, z_mode)
|
__field(mode_t, z_mode)
|
||||||
__field(boolean_t, z_is_sa)
|
__field(boolean_t, z_is_sa)
|
||||||
__field(boolean_t, z_is_mapped)
|
|
||||||
__field(boolean_t, z_is_ctldir)
|
__field(boolean_t, z_is_ctldir)
|
||||||
|
|
||||||
__field(uint32_t, i_uid)
|
__field(uint32_t, i_uid)
|
||||||
@ -96,7 +95,6 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
|
|||||||
__entry->z_async_writes_cnt = zn->z_async_writes_cnt;
|
__entry->z_async_writes_cnt = zn->z_async_writes_cnt;
|
||||||
__entry->z_mode = zn->z_mode;
|
__entry->z_mode = zn->z_mode;
|
||||||
__entry->z_is_sa = zn->z_is_sa;
|
__entry->z_is_sa = zn->z_is_sa;
|
||||||
__entry->z_is_mapped = zn->z_is_mapped;
|
|
||||||
__entry->z_is_ctldir = zn->z_is_ctldir;
|
__entry->z_is_ctldir = zn->z_is_ctldir;
|
||||||
|
|
||||||
__entry->i_uid = KUID_TO_SUID(ZTOI(zn)->i_uid);
|
__entry->i_uid = KUID_TO_SUID(ZTOI(zn)->i_uid);
|
||||||
@ -119,7 +117,7 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
|
|||||||
"zn_prefetch %u blksz %u seq %u "
|
"zn_prefetch %u blksz %u seq %u "
|
||||||
"mapcnt %llu size %llu pflags %llu "
|
"mapcnt %llu size %llu pflags %llu "
|
||||||
"sync_cnt %u sync_writes_cnt %u async_writes_cnt %u "
|
"sync_cnt %u sync_writes_cnt %u async_writes_cnt %u "
|
||||||
"mode 0x%x is_sa %d is_mapped %d is_ctldir %d "
|
"mode 0x%x is_sa %d is_ctldir %d "
|
||||||
"inode { uid %u gid %u ino %lu nlink %u size %lli "
|
"inode { uid %u gid %u ino %lu nlink %u size %lli "
|
||||||
"blkbits %u bytes %u mode 0x%x generation %x } } "
|
"blkbits %u bytes %u mode 0x%x generation %x } } "
|
||||||
"ace { type %u flags %u access_mask %u } mask_matched %u",
|
"ace { type %u flags %u access_mask %u } mask_matched %u",
|
||||||
@ -128,9 +126,8 @@ DECLARE_EVENT_CLASS(zfs_ace_class,
|
|||||||
__entry->z_seq, __entry->z_mapcnt, __entry->z_size,
|
__entry->z_seq, __entry->z_mapcnt, __entry->z_size,
|
||||||
__entry->z_pflags, __entry->z_sync_cnt,
|
__entry->z_pflags, __entry->z_sync_cnt,
|
||||||
__entry->z_sync_writes_cnt, __entry->z_async_writes_cnt,
|
__entry->z_sync_writes_cnt, __entry->z_async_writes_cnt,
|
||||||
__entry->z_mode, __entry->z_is_sa, __entry->z_is_mapped,
|
__entry->z_mode, __entry->z_is_sa, __entry->z_is_ctldir,
|
||||||
__entry->z_is_ctldir, __entry->i_uid,
|
__entry->i_uid, __entry->i_gid, __entry->i_ino, __entry->i_nlink,
|
||||||
__entry->i_gid, __entry->i_ino, __entry->i_nlink,
|
|
||||||
__entry->i_size, __entry->i_blkbits,
|
__entry->i_size, __entry->i_blkbits,
|
||||||
__entry->i_bytes, __entry->i_mode, __entry->i_generation,
|
__entry->i_bytes, __entry->i_mode, __entry->i_generation,
|
||||||
__entry->z_type, __entry->z_flags, __entry->z_access_mask,
|
__entry->z_type, __entry->z_flags, __entry->z_access_mask,
|
||||||
|
@ -47,9 +47,16 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
|
||||||
#define ZNODE_OS_FIELDS \
|
#define ZNODE_OS_FIELDS \
|
||||||
inode_timespec_t z_btime; /* creation/birth time (cached) */ \
|
inode_timespec_t z_btime; /* creation/birth time (cached) */ \
|
||||||
struct inode z_inode;
|
struct inode z_inode;
|
||||||
|
#else
|
||||||
|
#define ZNODE_OS_FIELDS \
|
||||||
|
inode_timespec_t z_btime; /* creation/birth time (cached) */ \
|
||||||
|
struct inode z_inode; \
|
||||||
|
boolean_t z_is_mapped; /* we are mmap'ed */
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert between znode pointers and inode pointers
|
* Convert between znode pointers and inode pointers
|
||||||
@ -70,7 +77,14 @@ extern "C" {
|
|||||||
#define Z_ISDEV(type) (S_ISCHR(type) || S_ISBLK(type) || S_ISFIFO(type))
|
#define Z_ISDEV(type) (S_ISCHR(type) || S_ISBLK(type) || S_ISFIFO(type))
|
||||||
#define Z_ISDIR(type) S_ISDIR(type)
|
#define Z_ISDIR(type) S_ISDIR(type)
|
||||||
|
|
||||||
#define zn_has_cached_data(zp) ((zp)->z_is_mapped)
|
#if defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
|
||||||
|
#define zn_has_cached_data(zp, start, end) \
|
||||||
|
filemap_range_has_page(ZTOI(zp)->i_mapping, start, end)
|
||||||
|
#else
|
||||||
|
#define zn_has_cached_data(zp, start, end) \
|
||||||
|
((zp)->z_is_mapped)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define zn_flush_cached_data(zp, sync) write_inode_now(ZTOI(zp), sync)
|
#define zn_flush_cached_data(zp, sync) write_inode_now(ZTOI(zp), sync)
|
||||||
#define zn_rlimit_fsize(zp, uio) (0)
|
#define zn_rlimit_fsize(zp, uio) (0)
|
||||||
|
|
||||||
|
@ -188,7 +188,6 @@ typedef struct znode {
|
|||||||
boolean_t z_atime_dirty; /* atime needs to be synced */
|
boolean_t z_atime_dirty; /* atime needs to be synced */
|
||||||
boolean_t z_zn_prefetch; /* Prefetch znodes? */
|
boolean_t z_zn_prefetch; /* Prefetch znodes? */
|
||||||
boolean_t z_is_sa; /* are we native sa? */
|
boolean_t z_is_sa; /* are we native sa? */
|
||||||
boolean_t z_is_mapped; /* are we mmap'ed */
|
|
||||||
boolean_t z_is_ctldir; /* are we .zfs entry */
|
boolean_t z_is_ctldir; /* are we .zfs entry */
|
||||||
boolean_t z_suspended; /* extra ref from a suspend? */
|
boolean_t z_suspended; /* extra ref from a suspend? */
|
||||||
uint_t z_blksz; /* block size in bytes */
|
uint_t z_blksz; /* block size in bytes */
|
||||||
|
@ -498,7 +498,9 @@ zfsctl_inode_alloc(zfsvfs_t *zfsvfs, uint64_t id,
|
|||||||
zp->z_atime_dirty = B_FALSE;
|
zp->z_atime_dirty = B_FALSE;
|
||||||
zp->z_zn_prefetch = B_FALSE;
|
zp->z_zn_prefetch = B_FALSE;
|
||||||
zp->z_is_sa = B_FALSE;
|
zp->z_is_sa = B_FALSE;
|
||||||
|
#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
|
||||||
zp->z_is_mapped = B_FALSE;
|
zp->z_is_mapped = B_FALSE;
|
||||||
|
#endif
|
||||||
zp->z_is_ctldir = B_TRUE;
|
zp->z_is_ctldir = B_TRUE;
|
||||||
zp->z_sa_hdl = NULL;
|
zp->z_sa_hdl = NULL;
|
||||||
zp->z_blksz = 0;
|
zp->z_blksz = 0;
|
||||||
|
@ -987,7 +987,7 @@ top:
|
|||||||
|
|
||||||
mutex_enter(&zp->z_lock);
|
mutex_enter(&zp->z_lock);
|
||||||
may_delete_now = atomic_read(&ZTOI(zp)->i_count) == 1 &&
|
may_delete_now = atomic_read(&ZTOI(zp)->i_count) == 1 &&
|
||||||
!(zp->z_is_mapped);
|
!zn_has_cached_data(zp, 0, LLONG_MAX);
|
||||||
mutex_exit(&zp->z_lock);
|
mutex_exit(&zp->z_lock);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1075,7 +1075,8 @@ top:
|
|||||||
&xattr_obj_unlinked, sizeof (xattr_obj_unlinked));
|
&xattr_obj_unlinked, sizeof (xattr_obj_unlinked));
|
||||||
delete_now = may_delete_now && !toobig &&
|
delete_now = may_delete_now && !toobig &&
|
||||||
atomic_read(&ZTOI(zp)->i_count) == 1 &&
|
atomic_read(&ZTOI(zp)->i_count) == 1 &&
|
||||||
!(zp->z_is_mapped) && xattr_obj == xattr_obj_unlinked &&
|
!zn_has_cached_data(zp, 0, LLONG_MAX) &&
|
||||||
|
xattr_obj == xattr_obj_unlinked &&
|
||||||
zfs_external_acl(zp) == acl_obj;
|
zfs_external_acl(zp) == acl_obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -551,7 +551,9 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
|
|||||||
ASSERT3P(zp->z_xattr_cached, ==, NULL);
|
ASSERT3P(zp->z_xattr_cached, ==, NULL);
|
||||||
zp->z_unlinked = B_FALSE;
|
zp->z_unlinked = B_FALSE;
|
||||||
zp->z_atime_dirty = B_FALSE;
|
zp->z_atime_dirty = B_FALSE;
|
||||||
|
#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
|
||||||
zp->z_is_mapped = B_FALSE;
|
zp->z_is_mapped = B_FALSE;
|
||||||
|
#endif
|
||||||
zp->z_is_ctldir = B_FALSE;
|
zp->z_is_ctldir = B_FALSE;
|
||||||
zp->z_suspended = B_FALSE;
|
zp->z_suspended = B_FALSE;
|
||||||
zp->z_sa_hdl = NULL;
|
zp->z_sa_hdl = NULL;
|
||||||
@ -1641,7 +1643,7 @@ zfs_free_range(znode_t *zp, uint64_t off, uint64_t len)
|
|||||||
* Zero partial page cache entries. This must be done under a
|
* Zero partial page cache entries. This must be done under a
|
||||||
* range lock in order to keep the ARC and page cache in sync.
|
* range lock in order to keep the ARC and page cache in sync.
|
||||||
*/
|
*/
|
||||||
if (zp->z_is_mapped) {
|
if (zn_has_cached_data(zp, off, off + len - 1)) {
|
||||||
loff_t first_page, last_page, page_len;
|
loff_t first_page, last_page, page_len;
|
||||||
loff_t first_page_offset, last_page_offset;
|
loff_t first_page_offset, last_page_offset;
|
||||||
|
|
||||||
|
@ -625,7 +625,6 @@ static int
|
|||||||
zpl_mmap(struct file *filp, struct vm_area_struct *vma)
|
zpl_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||||
{
|
{
|
||||||
struct inode *ip = filp->f_mapping->host;
|
struct inode *ip = filp->f_mapping->host;
|
||||||
znode_t *zp = ITOZ(ip);
|
|
||||||
int error;
|
int error;
|
||||||
fstrans_cookie_t cookie;
|
fstrans_cookie_t cookie;
|
||||||
|
|
||||||
@ -640,9 +639,12 @@ zpl_mmap(struct file *filp, struct vm_area_struct *vma)
|
|||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
#if !defined(HAVE_FILEMAP_RANGE_HAS_PAGE)
|
||||||
|
znode_t *zp = ITOZ(ip);
|
||||||
mutex_enter(&zp->z_lock);
|
mutex_enter(&zp->z_lock);
|
||||||
zp->z_is_mapped = B_TRUE;
|
zp->z_is_mapped = B_TRUE;
|
||||||
mutex_exit(&zp->z_lock);
|
mutex_exit(&zp->z_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
@ -937,7 +939,7 @@ zpl_fadvise(struct file *filp, loff_t offset, loff_t len, int advice)
|
|||||||
case POSIX_FADV_SEQUENTIAL:
|
case POSIX_FADV_SEQUENTIAL:
|
||||||
case POSIX_FADV_WILLNEED:
|
case POSIX_FADV_WILLNEED:
|
||||||
#ifdef HAVE_GENERIC_FADVISE
|
#ifdef HAVE_GENERIC_FADVISE
|
||||||
if (zn_has_cached_data(zp))
|
if (zn_has_cached_data(zp, offset, offset + len - 1))
|
||||||
error = generic_fadvise(filp, offset, len, advice);
|
error = generic_fadvise(filp, offset, len, advice);
|
||||||
#endif
|
#endif
|
||||||
/*
|
/*
|
||||||
|
@ -106,7 +106,7 @@ zfs_holey_common(znode_t *zp, ulong_t cmd, loff_t *off)
|
|||||||
hole = B_FALSE;
|
hole = B_FALSE;
|
||||||
|
|
||||||
/* Flush any mmap()'d data to disk */
|
/* Flush any mmap()'d data to disk */
|
||||||
if (zn_has_cached_data(zp))
|
if (zn_has_cached_data(zp, 0, file_sz - 1))
|
||||||
zn_flush_cached_data(zp, B_FALSE);
|
zn_flush_cached_data(zp, B_FALSE);
|
||||||
|
|
||||||
lr = zfs_rangelock_enter(&zp->z_rangelock, 0, file_sz, RL_READER);
|
lr = zfs_rangelock_enter(&zp->z_rangelock, 0, file_sz, RL_READER);
|
||||||
@ -288,7 +288,8 @@ zfs_read(struct znode *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
|
|||||||
error = mappedread_sf(zp, nbytes, uio);
|
error = mappedread_sf(zp, nbytes, uio);
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
if (zn_has_cached_data(zp) && !(ioflag & O_DIRECT)) {
|
if (zn_has_cached_data(zp, zfs_uio_offset(uio),
|
||||||
|
zfs_uio_offset(uio) + nbytes - 1) && !(ioflag & O_DIRECT)) {
|
||||||
error = mappedread(zp, nbytes, uio);
|
error = mappedread(zp, nbytes, uio);
|
||||||
} else {
|
} else {
|
||||||
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
|
error = dmu_read_uio_dbuf(sa_get_db(zp->z_sa_hdl),
|
||||||
@ -696,7 +697,8 @@ zfs_write(znode_t *zp, zfs_uio_t *uio, int ioflag, cred_t *cr)
|
|||||||
zfs_uioskip(uio, nbytes);
|
zfs_uioskip(uio, nbytes);
|
||||||
tx_bytes = nbytes;
|
tx_bytes = nbytes;
|
||||||
}
|
}
|
||||||
if (tx_bytes && zn_has_cached_data(zp) &&
|
if (tx_bytes &&
|
||||||
|
zn_has_cached_data(zp, woff, woff + tx_bytes - 1) &&
|
||||||
!(ioflag & O_DIRECT)) {
|
!(ioflag & O_DIRECT)) {
|
||||||
update_pages(zp, woff, tx_bytes, zfsvfs->z_os);
|
update_pages(zp, woff, tx_bytes, zfsvfs->z_os);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user