Skip to content
Permalink
Browse files

Factor out non-portable vnode_t usage

On FreeBSD file offset state is maintained in struct file. A given
vnode can be referenced from many different struct file *. As a
consequence, FreeBSD's SPL doesn't support vn_rdwr with the FAPPEND
flag.

This change replaces the non-portable vnode_t with the portable
file_t in the common code.

Signed-off-by: Matt Macy <mmacy@FreeBSD.org>
  • Loading branch information...
mattmacy committed Sep 30, 2019
1 parent 734de7c commit 6c81850e2099c22fd1f5ec354a71fcf09bf94a6b
@@ -183,6 +183,12 @@ extern file_t *vn_getf(int fd);
extern void vn_releasef(int fd);
extern void vn_areleasef(int fd, uf_info_t *fip);

extern ssize_t spl_kernel_write(struct file *file, const void *buf,
size_t count, loff_t *pos);
extern ssize_t spl_kernel_read(struct file *file, void *buf,
size_t count, loff_t *pos);


int spl_vn_init(void);
void spl_vn_fini(void);

@@ -104,6 +104,7 @@ COMMON_H = \
$(top_srcdir)/include/sys/zfs_context.h \
$(top_srcdir)/include/sys/zfs_debug.h \
$(top_srcdir)/include/sys/zfs_delay.h \
$(top_srcdir)/include/sys/zfs_file.h \
$(top_srcdir)/include/sys/zfs_fuid.h \
$(top_srcdir)/include/sys/zfs_project.h \
$(top_srcdir)/include/sys/zfs_ratelimit.h \
@@ -1071,7 +1071,7 @@ void dmu_traverse_objset(objset_t *os, uint64_t txg_start,
dmu_traverse_cb_t cb, void *arg);

int dmu_diff(const char *tosnap_name, const char *fromsnap_name,
struct vnode *vp, offset_t *offp);
file_t *fp, offset_t *offp);

/* CRC64 table */
#define ZFS_CRC64_POLY 0xC96C5795D7870F42ULL /* ECMA-182, reflected form */
@@ -62,7 +62,7 @@ typedef struct dmu_recv_cookie {
nvlist_t *drc_begin_nvl;

objset_t *drc_os;
vnode_t *drc_vp; /* The vnode to read the stream from */
file_t *drc_fp; /* The file to read the stream from */
uint64_t drc_voff; /* The current offset in the stream */
uint64_t drc_bytes_read;
/*
@@ -82,10 +82,11 @@ typedef struct dmu_recv_cookie {
int dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
boolean_t force, boolean_t resumable, nvlist_t *localprops,
nvlist_t *hidden_args, char *origin, dmu_recv_cookie_t *drc,
vnode_t *vp, offset_t *voffp);
file_t *fp, offset_t *voffp);
int dmu_recv_stream(dmu_recv_cookie_t *drc, int cleanup_fd,
uint64_t *action_handlep, offset_t *voffp);
int dmu_recv_end(dmu_recv_cookie_t *drc, void *owner);
boolean_t dmu_objset_is_receiving(objset_t *os);


#endif /* _DMU_RECV_H */
@@ -524,6 +524,10 @@ typedef struct vnode {
int v_dump_fd;
} vnode_t;

typedef struct file {
vnode_t *f_vnode;
} file_t;

extern char *vn_dumpdir;
#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */

@@ -620,6 +624,12 @@ extern int vn_openat(char *path, int x1, int oflags, int mode, vnode_t **vpp,
extern int vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len,
offset_t offset, int x1, int x2, rlim64_t x3, void *x4, ssize_t *residp);
extern void vn_close(vnode_t *vp);
extern ssize_t spl_kernel_write(file_t *fp, const void *buf,
size_t count, loff_t *pos);
extern ssize_t spl_kernel_read(file_t *fp, void *buf,
size_t count, loff_t *pos);

loff_t vfs_llseek(file_t *fp, loff_t offset, int whence);

#define vn_remove(path, x1, x2) remove(path)
#define vn_rename(from, to, seg) rename((from), (to))
@@ -0,0 +1,29 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/

#ifndef _SYS_ZFS_FILE_H
#define _SYS_ZFS_FILE_H

int zfs_file_write(file_t *, const void *, size_t, loff_t *, ssize_t *);
int zfs_file_read(file_t *, void *, size_t, loff_t *, ssize_t *);
int zfs_file_seek(file_t *, loff_t *, int);

#endif /* _SYS_ZFS_FILE_H */
@@ -144,6 +144,7 @@ KERNEL_C = \
zfeature.c \
zfs_byteswap.c \
zfs_debug.c \
zfs_file_os.c \
zfs_fm.c \
zfs_fuid.c \
zfs_sa.c \
@@ -636,6 +636,39 @@ vn_rdwr(int uio, vnode_t *vp, void *addr, ssize_t len, offset_t offset,
return (0);
}

ssize_t
spl_kernel_write(file_t *fp, const void *buf,
size_t count, loff_t *pos)
{
ssize_t rc;

rc = pwrite64(fp->f_vnode->v_fd, buf, count, *pos);
if (rc < 0)
return (-errno);
*pos += rc;
return (rc);
}

ssize_t
spl_kernel_read(file_t *fp, void *buf,
size_t count, loff_t *pos)
{
ssize_t rc;

rc = pread64(fp->f_vnode->v_fd, buf, count, *pos);
if (rc < 0)
return (-errno);
*pos += rc;
return (rc);
}

loff_t
vfs_llseek(file_t *fp, loff_t offset, int whence)
{

return (lseek(fp->f_vnode->v_fd, offset, whence));
}

void
vn_close(vnode_t *vp)
{
@@ -73,7 +73,7 @@ spl_filp_fsync(struct file *fp, int sync)
#endif /* HAVE_2ARGS_VFS_FSYNC */
}

static ssize_t
ssize_t
spl_kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
{
#if defined(HAVE_KERNEL_WRITE_PPOS)
@@ -92,8 +92,9 @@ spl_kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
return (ret);
#endif
}
EXPORT_SYMBOL(spl_kernel_write);

static ssize_t
ssize_t
spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
{
#if defined(HAVE_KERNEL_READ_PPOS)
@@ -112,6 +113,7 @@ spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
return (ret);
#endif
}
EXPORT_SYMBOL(spl_kernel_read);

vtype_t
vn_mode_to_vtype(mode_t mode)
@@ -26,6 +26,7 @@ $(MODULE)-objs += ../os/linux/zfs/zfs_acl.o
$(MODULE)-objs += ../os/linux/zfs/zfs_ctldir.o
$(MODULE)-objs += ../os/linux/zfs/zfs_debug.o
$(MODULE)-objs += ../os/linux/zfs/zfs_dir.o
$(MODULE)-objs += ../os/linux/zfs/zfs_file_os.o
$(MODULE)-objs += ../os/linux/zfs/zfs_ioctl_os.o
$(MODULE)-objs += ../os/linux/zfs/zfs_onexit_os.o
$(MODULE)-objs += ../os/linux/zfs/zfs_sysfs.o
@@ -0,0 +1,103 @@
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/

#include <sys/dmu.h>
#include <sys/dmu_impl.h>
#include <sys/dmu_recv.h>
#include <sys/dmu_tx.h>
#include <sys/dbuf.h>
#include <sys/dnode.h>
#include <sys/zfs_context.h>
#include <sys/dmu_objset.h>
#include <sys/dmu_traverse.h>
#include <sys/dsl_dataset.h>
#include <sys/dsl_dir.h>
#include <sys/dsl_pool.h>
#include <sys/dsl_synctask.h>
#include <sys/zfs_ioctl.h>
#include <sys/zap.h>
#include <sys/zio_checksum.h>
#include <sys/zfs_znode.h>
#include <sys/zfs_file.h>

/*
* zfs_file_open -> filp_open
* zfs_file_close -> filp_close
* zfs_file_seek -> vfs_llseek
* zfs_file_sync -> spl_filp_fsync
* zfs_file_pwrite -> spl_kernel_write
* zfs_file_pread -> spl_kernel_read
* zfs_file_stat -> vfs_getattr
* zfs_file_unlink -> vfs_unlink
* zfs_file_get -> fget
* zfs_file_put -> fput
*/

#ifdef _KERNEL
#define FILE2FP(file) ((file)->f_file)
#else
#define FILE2FP(file) (file)
#endif

int
zfs_file_write(file_t *file, const void *buf, size_t count, loff_t *offp,
ssize_t *resid)
{
ssize_t rc;
struct file *fp;

fp = FILE2FP(file);
rc = spl_kernel_write(fp, buf, count, offp);
if (rc < 0)
return ((int)-rc);
*resid = count - rc;
return (0);
}

int
zfs_file_read(file_t *file, void *buf, size_t count, loff_t *offp,
ssize_t *resid)
{
ssize_t rc;
struct file *fp;

fp = FILE2FP(file);
rc = spl_kernel_read(fp, buf, count, offp);
if (rc < 0)
return ((int)-rc);
*resid = count - rc;
return (0);
}

int
zfs_file_seek(file_t *file, loff_t *offp, int whence)
{
struct file *fp;
loff_t rc;

fp = FILE2FP(file);
rc = vfs_llseek(fp, *offp, whence);
if (rc < 0)
return (-rc);

*offp = rc;
return (0);
}
@@ -40,33 +40,41 @@
#include <sys/zap.h>
#include <sys/zio_checksum.h>
#include <sys/zfs_znode.h>
#include <sys/zfs_file.h>

struct diffarg {
struct vnode *da_vp; /* file to which we are reporting */

typedef struct dmu_diffarg {
file_t *da_fp; /* file to which we are reporting */
offset_t *da_offp;
int da_err; /* error that stopped diff search */
dmu_diff_record_t da_ddr;
};
} dmu_diffarg_t;

static int
write_record(struct diffarg *da)
int
write_record(dmu_diffarg_t *da)
{
file_t *fp;
loff_t off;
ssize_t resid; /* have to get resid to get detailed errno */

if (da->da_ddr.ddr_type == DDR_NONE) {
da->da_err = 0;
return (0);
}

da->da_err = vn_rdwr(UIO_WRITE, da->da_vp, (caddr_t)&da->da_ddr,
sizeof (da->da_ddr), 0, UIO_SYSSPACE, FAPPEND,
RLIM64_INFINITY, CRED(), &resid);
fp = da->da_fp;
off = (loff_t)0;
da->da_err = zfs_file_seek(fp, &off, SEEK_END);
if (da->da_err && da->da_err != ESPIPE)
return (da->da_err);
da->da_err = zfs_file_write(fp, (caddr_t)&da->da_ddr,
sizeof (da->da_ddr), &off, &resid);
*da->da_offp += sizeof (da->da_ddr);
return (da->da_err);
}

static int
report_free_dnode_range(struct diffarg *da, uint64_t first, uint64_t last)
report_free_dnode_range(dmu_diffarg_t *da, uint64_t first, uint64_t last)
{
ASSERT(first <= last);
if (da->da_ddr.ddr_type != DDR_FREE ||
@@ -83,7 +91,7 @@ report_free_dnode_range(struct diffarg *da, uint64_t first, uint64_t last)
}

static int
report_dnode(struct diffarg *da, uint64_t object, dnode_phys_t *dnp)
report_dnode(dmu_diffarg_t *da, uint64_t object, dnode_phys_t *dnp)
{
ASSERT(dnp != NULL);
if (dnp->dn_type == DMU_OT_NONE)
@@ -110,7 +118,7 @@ static int
diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,
const zbookmark_phys_t *zb, const dnode_phys_t *dnp, void *arg)
{
struct diffarg *da = arg;
dmu_diffarg_t *da = arg;
int err = 0;

if (issig(JUSTLOOKING) && issig(FORREAL))
@@ -162,9 +170,9 @@ diff_cb(spa_t *spa, zilog_t *zilog, const blkptr_t *bp,

int
dmu_diff(const char *tosnap_name, const char *fromsnap_name,
struct vnode *vp, offset_t *offp)
file_t *fp, offset_t *offp)
{
struct diffarg da;
dmu_diffarg_t da;
dsl_dataset_t *fromsnap;
dsl_dataset_t *tosnap;
dsl_pool_t *dp;
@@ -205,7 +213,7 @@ dmu_diff(const char *tosnap_name, const char *fromsnap_name,
dsl_dataset_long_hold(tosnap, FTAG);
dsl_pool_rele(dp, FTAG);

da.da_vp = vp;
da.da_fp = fp;
da.da_offp = offp;
da.da_ddr.ddr_type = DDR_NONE;
da.da_ddr.ddr_first = da.da_ddr.ddr_last = 0;

0 comments on commit 6c81850

Please sign in to comment.
You can’t perform that action at this time.