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 <behlendorf1@llnl.gov> Reviewed-by: Ryan Moeller <ryan@iXsystems.com> Signed-off-by: Matt Macy <mmacy@FreeBSD.org> Closes #11125
This commit is contained in:
parent
073f3c7826
commit
a909190683
|
@ -30,6 +30,7 @@
|
||||||
#define _OPENSOLARIS_SYS_MISC_H_
|
#define _OPENSOLARIS_SYS_MISC_H_
|
||||||
|
|
||||||
#include <sys/limits.h>
|
#include <sys/limits.h>
|
||||||
|
#include <sys/filio.h>
|
||||||
|
|
||||||
#define MAXUID UID_MAX
|
#define MAXUID UID_MAX
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@
|
||||||
#define _FIOGDIO (INT_MIN+1)
|
#define _FIOGDIO (INT_MIN+1)
|
||||||
#define _FIOSDIO (INT_MIN+2)
|
#define _FIOSDIO (INT_MIN+2)
|
||||||
|
|
||||||
#define _FIO_SEEK_DATA FIOSEEKDATA
|
#define F_SEEK_DATA FIOSEEKDATA
|
||||||
#define _FIO_SEEK_HOLE FIOSEEKHOLE
|
#define F_SEEK_HOLE FIOSEEKHOLE
|
||||||
|
|
||||||
struct opensolaris_utsname {
|
struct opensolaris_utsname {
|
||||||
char *sysname;
|
char *sysname;
|
||||||
|
|
|
@ -52,6 +52,12 @@
|
||||||
|
|
||||||
#define F_FREESP 11 /* Free file space */
|
#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.
|
* The vnode AT_ flags are mapped to the Linux ATTR_* flags.
|
||||||
* This allows them to be used safely with an iattr structure.
|
* This allows them to be used safely with an iattr structure.
|
||||||
|
|
|
@ -40,10 +40,8 @@ extern "C" {
|
||||||
|
|
||||||
extern int zfs_open(struct inode *ip, int mode, int flag, cred_t *cr);
|
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_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,
|
extern int zfs_write_simple(znode_t *zp, const void *data, size_t len,
|
||||||
loff_t pos, size_t *resid);
|
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,
|
extern int zfs_lookup(znode_t *dzp, char *nm, znode_t **zpp, int flags,
|
||||||
cred_t *cr, int *direntflags, pathname_t *realpnp);
|
cred_t *cr, int *direntflags, pathname_t *realpnp);
|
||||||
extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
|
extern int zfs_create(znode_t *dzp, char *name, vattr_t *vap, int excl,
|
||||||
|
|
|
@ -29,8 +29,11 @@
|
||||||
extern int zfs_fsync(znode_t *, int, cred_t *);
|
extern int zfs_fsync(znode_t *, int, cred_t *);
|
||||||
extern int zfs_read(znode_t *, uio_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_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_holey(znode_t *, ulong_t, loff_t *);
|
||||||
extern int zfs_setsecattr(znode_t *zp, vsecattr_t *vsecp, int flag, cred_t *cr);
|
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(znode_t *, int, uio_t *);
|
||||||
extern int mappedread_sf(znode_t *, int, uio_t *);
|
extern int mappedread_sf(znode_t *, int, uio_t *);
|
||||||
|
|
|
@ -270,69 +270,13 @@ zfs_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *cr)
|
||||||
return (0);
|
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 */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred,
|
zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred,
|
||||||
int *rvalp)
|
int *rvalp)
|
||||||
{
|
{
|
||||||
offset_t off;
|
loff_t off;
|
||||||
int error;
|
int error;
|
||||||
zfsvfs_t *zfsvfs;
|
|
||||||
znode_t *zp;
|
|
||||||
|
|
||||||
switch (com) {
|
switch (com) {
|
||||||
case _FIOFFS:
|
case _FIOFFS:
|
||||||
|
@ -350,18 +294,12 @@ zfs_ioctl(vnode_t *vp, ulong_t com, intptr_t data, int flag, cred_t *cred,
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
case _FIO_SEEK_DATA:
|
case F_SEEK_DATA:
|
||||||
case _FIO_SEEK_HOLE:
|
case F_SEEK_HOLE:
|
||||||
{
|
{
|
||||||
off = *(offset_t *)data;
|
off = *(offset_t *)data;
|
||||||
zp = VTOZ(vp);
|
|
||||||
zfsvfs = zp->z_zfsvfs;
|
|
||||||
ZFS_ENTER(zfsvfs);
|
|
||||||
ZFS_VERIFY_ZP(zp);
|
|
||||||
|
|
||||||
/* offset parameter is in/out */
|
/* offset parameter is in/out */
|
||||||
error = zfs_holey(vp, com, &off);
|
error = zfs_holey(VTOZ(vp), com, &off);
|
||||||
ZFS_EXIT(zfsvfs);
|
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
*(offset_t *)data = off;
|
*(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);
|
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
|
static int
|
||||||
zfs_dd_callback(struct mount *mp, void *arg, int lkflags, struct vnode **vpp)
|
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);
|
accmode = ap->a_accmode & (VREAD|VWRITE|VEXEC|VAPPEND);
|
||||||
if (accmode != 0)
|
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().
|
* VADMIN has to be handled by vaccess().
|
||||||
|
|
|
@ -243,78 +243,6 @@ zfs_close(struct inode *ip, int flag, cred_t *cr)
|
||||||
return (0);
|
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)
|
#if defined(_KERNEL)
|
||||||
/*
|
/*
|
||||||
* When a file is memory mapped, we must keep the IO data synchronized
|
* 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);
|
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.
|
* Lookup an entry in a directory, or an extended attribute directory.
|
||||||
* If it exists, return a held inode reference for it.
|
* 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)
|
#if defined(_KERNEL)
|
||||||
EXPORT_SYMBOL(zfs_open);
|
EXPORT_SYMBOL(zfs_open);
|
||||||
EXPORT_SYMBOL(zfs_close);
|
EXPORT_SYMBOL(zfs_close);
|
||||||
EXPORT_SYMBOL(zfs_access);
|
|
||||||
EXPORT_SYMBOL(zfs_lookup);
|
EXPORT_SYMBOL(zfs_lookup);
|
||||||
EXPORT_SYMBOL(zfs_create);
|
EXPORT_SYMBOL(zfs_create);
|
||||||
EXPORT_SYMBOL(zfs_tmpfile);
|
EXPORT_SYMBOL(zfs_tmpfile);
|
||||||
|
|
|
@ -504,7 +504,7 @@ zpl_llseek(struct file *filp, loff_t offset, int whence)
|
||||||
|
|
||||||
spl_inode_lock_shared(ip);
|
spl_inode_lock_shared(ip);
|
||||||
cookie = spl_fstrans_mark();
|
cookie = spl_fstrans_mark();
|
||||||
error = -zfs_holey(ip, whence, &offset);
|
error = -zfs_holey(ITOZ(ip), whence, &offset);
|
||||||
spl_fstrans_unmark(cookie);
|
spl_fstrans_unmark(cookie);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
error = lseek_execute(filp, ip, offset, maxbytes);
|
error = lseek_execute(filp, ip, offset, maxbytes);
|
||||||
|
|
|
@ -74,6 +74,96 @@ zfs_fsync(znode_t *zp, int syncflag, cred_t *cr)
|
||||||
return (0);
|
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 */
|
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);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT_SYMBOL(zfs_access);
|
||||||
EXPORT_SYMBOL(zfs_fsync);
|
EXPORT_SYMBOL(zfs_fsync);
|
||||||
|
EXPORT_SYMBOL(zfs_holey);
|
||||||
EXPORT_SYMBOL(zfs_read);
|
EXPORT_SYMBOL(zfs_read);
|
||||||
EXPORT_SYMBOL(zfs_write);
|
EXPORT_SYMBOL(zfs_write);
|
||||||
EXPORT_SYMBOL(zfs_getsecattr);
|
EXPORT_SYMBOL(zfs_getsecattr);
|
||||||
|
|
Loading…
Reference in New Issue