Skip to content

Commit

Permalink
Factor out non-portable vnode_t usage
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
mattmacy committed Nov 6, 2019
1 parent ae38e00 commit 87cf8a0
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 36 deletions.
4 changes: 4 additions & 0 deletions include/os/linux/spl/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,10 @@ 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);


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

Expand Down
1 change: 1 addition & 0 deletions include/sys/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
2 changes: 1 addition & 1 deletion include/sys/dmu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 1 addition & 0 deletions include/sys/dmu_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ typedef struct dmu_sendstatus {
uint64_t dss_blocks; /* blocks visited during the sending process */
} dmu_sendstatus_t;

int dmu_send_write(file_t *fp, char *buf, int len, ssize_t *resid);
void dmu_object_zapify(objset_t *, uint64_t, dmu_object_type_t, dmu_tx_t *);
void dmu_object_free_zapified(objset_t *, uint64_t, dmu_tx_t *);
int dmu_buf_hold_noread(objset_t *, uint64_t, uint64_t,
Expand Down
5 changes: 3 additions & 2 deletions include/sys/dmu_recv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
/*
Expand All @@ -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 */
8 changes: 8 additions & 0 deletions include/sys/zfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down Expand Up @@ -620,6 +624,10 @@ 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);

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))
Expand Down
28 changes: 28 additions & 0 deletions include/sys/zfs_file.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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 *);
loff_t zfs_file_seek(file_t *, loff_t, int);

#endif /* _SYS_ZFS_FILE_H */
1 change: 1 addition & 0 deletions lib/libzpool/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
20 changes: 20 additions & 0 deletions lib/libzpool/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,26 @@ 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);
}

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)
{
Expand Down
3 changes: 2 additions & 1 deletion module/os/linux/spl/spl-vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -92,6 +92,7 @@ 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
spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
Expand Down
1 change: 1 addition & 0 deletions module/os/linux/zfs/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
82 changes: 82 additions & 0 deletions module/os/linux/zfs/zfs_file_os.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* 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 = rc;
return (0);
}

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

fp = FILE2FP(file);
return (vfs_llseek(fp, off, whence));
}
33 changes: 19 additions & 14 deletions module/zfs/dmu_diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,33 +40,38 @@
#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 = zfs_file_seek(fp, 0, SEEK_END);
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 ||
Expand All @@ -83,7 +88,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)
Expand All @@ -110,7 +115,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))
Expand Down Expand Up @@ -162,9 +167,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;
Expand Down Expand Up @@ -205,7 +210,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;
Expand Down
16 changes: 9 additions & 7 deletions module/zfs/dmu_recv.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#ifdef _KERNEL
#include <sys/zfs_vfsops.h>
#endif
#include <sys/zfs_file.h>

int zfs_recv_queue_length = SPA_MAXBLOCKSIZE;
int zfs_recv_queue_ff = 20;
Expand Down Expand Up @@ -1103,7 +1104,7 @@ dmu_recv_resume_begin_sync(void *arg, dmu_tx_t *tx)
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,
nvlist_t *hidden_args, char *origin, dmu_recv_cookie_t *drc, file_t *fp,
offset_t *voffp)
{
dmu_recv_begin_arg_t drba = { 0 };
Expand Down Expand Up @@ -1131,7 +1132,7 @@ dmu_recv_begin(char *tofs, char *tosnap, dmu_replay_record_t *drr_begin,
return (SET_ERROR(EINVAL));
}

drc->drc_vp = vp;
drc->drc_fp = fp;
drc->drc_voff = *voffp;
drc->drc_featureflags =
DMU_GET_FEATUREFLAGS(drc->drc_drrb->drr_versioninfo);
Expand Down Expand Up @@ -1248,12 +1249,13 @@ receive_read(dmu_recv_cookie_t *drc, int len, void *buf)

while (done < len) {
ssize_t resid;
file_t *fp;
loff_t off;

drc->drc_err = vn_rdwr(UIO_READ, drc->drc_vp,
(char *)buf + done, len - done,
drc->drc_voff, UIO_SYSSPACE, FAPPEND,
RLIM64_INFINITY, CRED(), &resid);

fp = drc->drc_fp;
off = zfs_file_seek(fp, 0, SEEK_END);
drc->drc_err = zfs_file_write(fp, (char *)buf + done,
len - done, &off, &resid);
if (resid == len - done) {
/*
* Note: ECKSUM indicates that the receive
Expand Down
Loading

0 comments on commit 87cf8a0

Please sign in to comment.