From a909190683493f5f73337e15174cc0f87f538f61 Mon Sep 17 00:00:00 2001 From: Matthew Macy Date: Sat, 31 Oct 2020 09:40:08 -0700 Subject: [PATCH] Consolidate zfs_holey and zfs_access The zfs_holey() and zfs_access() functions can be made common to both FreeBSD and Linux. Reviewed-by: Brian Behlendorf Reviewed-by: Ryan Moeller Signed-off-by: Matt Macy Closes #11125 --- include/os/freebsd/spl/sys/misc.h | 5 +- include/os/linux/spl/sys/vnode.h | 6 ++ include/os/linux/zfs/sys/zfs_vnops_os.h | 2 - include/sys/zfs_vnops.h | 7 +- module/os/freebsd/zfs/zfs_vnops_os.c | 93 ++----------------------- module/os/linux/zfs/zfs_vnops_os.c | 93 ------------------------- module/os/linux/zfs/zpl_file.c | 2 +- module/zfs/zfs_vnops.c | 92 ++++++++++++++++++++++++ 8 files changed, 112 insertions(+), 188 deletions(-) diff --git a/include/os/freebsd/spl/sys/misc.h b/include/os/freebsd/spl/sys/misc.h index f2dcdbb9fd..3481507d2c 100644 --- a/include/os/freebsd/spl/sys/misc.h +++ b/include/os/freebsd/spl/sys/misc.h @@ -30,6 +30,7 @@ #define _OPENSOLARIS_SYS_MISC_H_ #include +#include #define MAXUID UID_MAX @@ -40,8 +41,8 @@ #define _FIOGDIO (INT_MIN+1) #define _FIOSDIO (INT_MIN+2) -#define _FIO_SEEK_DATA FIOSEEKDATA -#define _FIO_SEEK_HOLE FIOSEEKHOLE +#define F_SEEK_DATA FIOSEEKDATA +#define F_SEEK_HOLE FIOSEEKHOLE struct opensolaris_utsname { char *sysname; diff --git a/include/os/linux/spl/sys/vnode.h b/include/os/linux/spl/sys/vnode.h index 6f17db89fe..64c2706502 100644 --- a/include/os/linux/spl/sys/vnode.h +++ b/include/os/linux/spl/sys/vnode.h @@ -52,6 +52,12 @@ #define F_FREESP 11 /* Free file space */ + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) +#define F_SEEK_DATA SEEK_DATA +#define F_SEEK_HOLE SEEK_HOLE +#endif + /* * The vnode AT_ flags are mapped to the Linux ATTR_* flags. * This allows them to be used safely with an iattr structure. diff --git a/include/os/linux/zfs/sys/zfs_vnops_os.h b/include/os/linux/zfs/sys/zfs_vnops_os.h index ba83f5dd83..d3b80753d1 100644 --- a/include/os/linux/zfs/sys/zfs_vnops_os.h +++ b/include/os/linux/zfs/sys/zfs_vnops_os.h @@ -40,10 +40,8 @@ extern "C" { extern int zfs_open(struct inode *ip, int mode, int flag, cred_t *cr); extern int zfs_close(struct inode *ip, int flag, cred_t *cr); -extern int zfs_holey(struct inode *ip, int cmd, loff_t *off); extern int zfs_write_simple(znode_t *zp, const void *data, size_t len, loff_t pos, size_t *resid); -extern int zfs_access(struct inode *ip, int mode, int flag, cred_t *cr); extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags, cred_t *cr, int *direntflags, pathname_t *realpnp); extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl, diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h index 6b5d9726cc..9c76e48556 100644 --- a/include/sys/zfs_vnops.h +++ b/include/sys/zfs_vnops.h @@ -29,8 +29,11 @@ extern int zfs_fsync(znode_t *, int, cred_t *); extern int zfs_read(znode_t *, uio_t *, int, cred_t *); extern int zfs_write(znode_t *, uio_t *, int, cred_t *); -extern int zfs_getsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr); -extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr); +extern int zfs_holey(znode_t *, ulong_t, loff_t *); +extern int zfs_access(znode_t *, int, int, cred_t *); + +extern int zfs_getsecattr(znode_t *, vsecattr_t *, int, cred_t *); +extern int zfs_setsecattr(znode_t *, vsecattr_t *, int, cred_t *); extern int mappedread(znode_t *, int, uio_t *); extern int mappedread_sf(znode_t *, int, uio_t *); diff --git a/module/os/freebsd/zfs/zfs_vnops_os.c b/module/os/freebsd/zfs/zfs_vnops_os.c index be8ac1fc6c..079f7a2ecb 100644 --- a/module/os/freebsd/zfs/zfs_vnops_os.c +++ b/module/os/freebsd/zfs/zfs_vnops_os.c @@ -270,69 +270,13 @@ zfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr) return (0); } -/* - * Lseek support for finding holes (cmd == _FIO_SEEK_HOLE) and - * data (cmd == _FIO_SEEK_DATA). "off" is an in/out parameter. - */ -static int -zfs_holey(vnode_t *vp, ulong_t cmd, offset_t *off) -{ - znode_t *zp = VTOZ(vp); - uint64_t noff = (uint64_t)*off; /* new offset */ - uint64_t file_sz; - int error; - boolean_t hole; - - file_sz = zp->z_size; - if (noff >= file_sz) { - return (SET_ERROR(ENXIO)); - } - - if (cmd == _FIO_SEEK_HOLE) - hole = B_TRUE; - else - hole = B_FALSE; - - error = dmu_offset_next(zp->z_zfsvfs->z_os, zp->z_id, hole, &noff); - - if (error == ESRCH) - return (SET_ERROR(ENXIO)); - - /* file was dirty, so fall back to using generic logic */ - if (error == EBUSY) { - if (hole) - *off = file_sz; - - return (0); - } - - /* - * We could find a hole that begins after the logical end-of-file, - * because dmu_offset_next() only works on whole blocks. If the - * EOF falls mid-block, then indicate that the "virtual hole" - * at the end of the file begins at the logical EOF, rather than - * at the end of the last block. - */ - if (noff > file_sz) { - ASSERT(hole); - noff = file_sz; - } - - if (noff < *off) - return (error); - *off = noff; - return (error); -} - /* ARGSUSED */ static int zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred, int *rvalp) { - offset_t off; + loff_t off; int error; - zfsvfs_t *zfsvfs; - znode_t *zp; switch (com) { case _FIOFFS: @@ -350,18 +294,12 @@ zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred, return (0); } - case _FIO_SEEK_DATA: - case _FIO_SEEK_HOLE: + case F_SEEK_DATA: + case F_SEEK_HOLE: { off = *(offset_t *)data; - zp = VTOZ(vp); - zfsvfs = zp->z_zfsvfs; - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - /* offset parameter is in/out */ - error = zfs_holey(vp, com, &off); - ZFS_EXIT(zfsvfs); + error = zfs_holey(VTOZ(vp), com, &off); if (error) return (error); *(offset_t *)data = off; @@ -890,27 +828,6 @@ zfs_get_data(void *arg, lr_write_t *lr, char *buf, struct lwb *lwb, zio_t *zio) return (error); } -/*ARGSUSED*/ -static int -zfs_access(vnode_t *vp, int mode, int flag, cred_t *cr, - caller_context_t *ct) -{ - znode_t *zp = VTOZ(vp); - zfsvfs_t *zfsvfs = zp->z_zfsvfs; - int error; - - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - - if (flag & V_ACE_MASK) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); - else - error = zfs_zaccess_rwx(zp, mode, flag, cr); - - ZFS_EXIT(zfsvfs); - return (error); -} - static int zfs_dd_callback(struct mount *mp, void *arg, int lkflags, struct vnode **vpp) { @@ -4750,7 +4667,7 @@ zfs_freebsd_access(struct vop_access_args *ap) */ accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND); if (accmode != 0) - error = zfs_access(ap->a_vp, accmode, 0, ap->a_cred, NULL); + error = zfs_access(zp, accmode, 0, ap->a_cred); /* * VADMIN has to be handled by vaccess(). diff --git a/module/os/linux/zfs/zfs_vnops_os.c b/module/os/linux/zfs/zfs_vnops_os.c index a48659b28b..3b1658524b 100644 --- a/module/os/linux/zfs/zfs_vnops_os.c +++ b/module/os/linux/zfs/zfs_vnops_os.c @@ -243,78 +243,6 @@ zfs_close(struct inode *ip, int flag, cred_t *cr) return (0); } -#if defined(SEEK_HOLE) && defined(SEEK_DATA) -/* - * Lseek support for finding holes (cmd == SEEK_HOLE) and - * data (cmd == SEEK_DATA). "off" is an in/out parameter. - */ -static int -zfs_holey_common(struct inode *ip, int cmd, loff_t *off) -{ - znode_t *zp = ITOZ(ip); - uint64_t noff = (uint64_t)*off; /* new offset */ - uint64_t file_sz; - int error; - boolean_t hole; - - file_sz = zp->z_size; - if (noff >= file_sz) { - return (SET_ERROR(ENXIO)); - } - - if (cmd == SEEK_HOLE) - hole = B_TRUE; - else - hole = B_FALSE; - - error = dmu_offset_next(ZTOZSB(zp)->z_os, zp->z_id, hole, &noff); - - if (error == ESRCH) - return (SET_ERROR(ENXIO)); - - /* file was dirty, so fall back to using generic logic */ - if (error == EBUSY) { - if (hole) - *off = file_sz; - - return (0); - } - - /* - * We could find a hole that begins after the logical end-of-file, - * because dmu_offset_next() only works on whole blocks. If the - * EOF falls mid-block, then indicate that the "virtual hole" - * at the end of the file begins at the logical EOF, rather than - * at the end of the last block. - */ - if (noff > file_sz) { - ASSERT(hole); - noff = file_sz; - } - - if (noff < *off) - return (error); - *off = noff; - return (error); -} - -int -zfs_holey(struct inode *ip, int cmd, loff_t *off) -{ - znode_t *zp = ITOZ(ip); - zfsvfs_t *zfsvfs = ITOZSB(ip); - int error; - - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - - error = zfs_holey_common(ip, cmd, off); - - ZFS_EXIT(zfsvfs); - return (error); -} -#endif /* SEEK_HOLE && SEEK_DATA */ - #if defined(_KERNEL) /* * When a file is memory mapped, we must keep the IO data synchronized @@ -659,26 +587,6 @@ zfs_get_data(void *arg, uint64_t gen, lr_write_t *lr, char *buf, return (error); } -/*ARGSUSED*/ -int -zfs_access(struct inode *ip, int mode, int flag, cred_t *cr) -{ - znode_t *zp = ITOZ(ip); - zfsvfs_t *zfsvfs = ITOZSB(ip); - int error; - - ZFS_ENTER(zfsvfs); - ZFS_VERIFY_ZP(zp); - - if (flag & V_ACE_MASK) - error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); - else - error = zfs_zaccess_rwx(zp, mode, flag, cr); - - ZFS_EXIT(zfsvfs); - return (error); -} - /* * Lookup an entry in a directory, or an extended attribute directory. * If it exists, return a held inode reference for it. @@ -4403,7 +4311,6 @@ zfs_retzcbuf(struct inode *ip, xuio_t *xuio, cred_t *cr) #if defined(_KERNEL) EXPORT_SYMBOL(zfs_open); EXPORT_SYMBOL(zfs_close); -EXPORT_SYMBOL(zfs_access); EXPORT_SYMBOL(zfs_lookup); EXPORT_SYMBOL(zfs_create); EXPORT_SYMBOL(zfs_tmpfile); diff --git a/module/os/linux/zfs/zpl_file.c b/module/os/linux/zfs/zpl_file.c index 1447525bc1..10a07f3270 100644 --- a/module/os/linux/zfs/zpl_file.c +++ b/module/os/linux/zfs/zpl_file.c @@ -504,7 +504,7 @@ zpl_llseek(struct file *filp, loff_t offset, int whence) spl_inode_lock_shared(ip); cookie = spl_fstrans_mark(); - error = -zfs_holey(ip, whence, &offset); + error = -zfs_holey(ITOZ(ip), whence, &offset); spl_fstrans_unmark(cookie); if (error == 0) error = lseek_execute(filp, ip, offset, maxbytes); diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index 9029f83c3a..83e08630b5 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -74,6 +74,96 @@ zfs_fsync(znode_t *zp, int syncflag, cred_t *cr) return (0); } + +#if defined(SEEK_HOLE) && defined(SEEK_DATA) +/* + * Lseek support for finding holes (cmd == SEEK_HOLE) and + * data (cmd == SEEK_DATA). "off" is an in/out parameter. + */ +static int +zfs_holey_common(znode_t *zp, ulong_t cmd, loff_t *off) +{ + uint64_t noff = (uint64_t)*off; /* new offset */ + uint64_t file_sz; + int error; + boolean_t hole; + + file_sz = zp->z_size; + if (noff >= file_sz) { + return (SET_ERROR(ENXIO)); + } + + if (cmd == F_SEEK_HOLE) + hole = B_TRUE; + else + hole = B_FALSE; + + error = dmu_offset_next(ZTOZSB(zp)->z_os, zp->z_id, hole, &noff); + + if (error == ESRCH) + return (SET_ERROR(ENXIO)); + + /* file was dirty, so fall back to using generic logic */ + if (error == EBUSY) { + if (hole) + *off = file_sz; + + return (0); + } + + /* + * We could find a hole that begins after the logical end-of-file, + * because dmu_offset_next() only works on whole blocks. If the + * EOF falls mid-block, then indicate that the "virtual hole" + * at the end of the file begins at the logical EOF, rather than + * at the end of the last block. + */ + if (noff > file_sz) { + ASSERT(hole); + noff = file_sz; + } + + if (noff < *off) + return (error); + *off = noff; + return (error); +} + +int +zfs_holey(znode_t *zp, ulong_t cmd, loff_t *off) +{ + zfsvfs_t *zfsvfs = ZTOZSB(zp); + int error; + + ZFS_ENTER(zfsvfs); + ZFS_VERIFY_ZP(zp); + + error = zfs_holey_common(zp, cmd, off); + + ZFS_EXIT(zfsvfs); + return (error); +} +#endif /* SEEK_HOLE && SEEK_DATA */ + +/*ARGSUSED*/ +int +zfs_access(znode_t *zp, int mode, int flag, cred_t *cr) +{ + zfsvfs_t *zfsvfs = ZTOZSB(zp); + int error; + + ZFS_ENTER(zfsvfs); + ZFS_VERIFY_ZP(zp); + + if (flag & V_ACE_MASK) + error = zfs_zaccess(zp, mode, flag, B_FALSE, cr); + else + error = zfs_zaccess_rwx(zp, mode, flag, cr); + + ZFS_EXIT(zfsvfs); + return (error); +} + static unsigned long zfs_vnops_read_chunk_size = 1024 * 1024; /* Tunable */ /* @@ -637,7 +727,9 @@ zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr) return (error); } +EXPORT_SYMBOL(zfs_access); EXPORT_SYMBOL(zfs_fsync); +EXPORT_SYMBOL(zfs_holey); EXPORT_SYMBOL(zfs_read); EXPORT_SYMBOL(zfs_write); EXPORT_SYMBOL(zfs_getsecattr);