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 <mmacy@FreeBSD.org>
  • Loading branch information
mattmacy committed Nov 12, 2019
1 parent 035ebb3 commit d42257f
Show file tree
Hide file tree
Showing 19 changed files with 337 additions and 229 deletions.
2 changes: 0 additions & 2 deletions include/os/linux/spl/sys/kobj.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ typedef struct _buf buf_t;

extern struct _buf *kobj_open_file(const char *name);
extern void kobj_close_file(struct _buf *file);
extern int kobj_read_file(struct _buf *file, char *buf, unsigned size,
unsigned off);
extern int kobj_get_filesize(struct _buf *file, uint64_t *size);

#endif /* SPL_KOBJ_H */
3 changes: 0 additions & 3 deletions include/os/linux/spl/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,6 @@ extern int vn_open(const char *path, uio_seg_t seg, int flags, int mode,
vnode_t **vpp, int x1, void *x2);
extern int vn_openat(const char *path, uio_seg_t seg, int flags, int mode,
vnode_t **vpp, int x1, void *x2, vnode_t *vp, int fd);
extern int vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len,
offset_t off, uio_seg_t seg, int x1, rlim64_t x2,
void *x3, ssize_t *residp);
extern int vn_close(vnode_t *vp, int flags, int x1, int x2, void *x3, void *x4);
extern int vn_seek(vnode_t *vp, offset_t o, offset_t *op, void *ct);

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
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 */
10 changes: 6 additions & 4 deletions include/sys/zfs_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,12 @@ typedef struct vnode {
int v_dump_fd;
} vnode_t;

typedef struct file {
int f_fd;
loff_t f_pos;
loff_t f_offset;
} file_t;

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

Expand Down Expand Up @@ -617,8 +623,6 @@ extern int vn_open(char *path, int x1, int oflags, int mode, vnode_t **vpp,
int x2, int x3);
extern int vn_openat(char *path, int x1, int oflags, int mode, vnode_t **vpp,
int x2, int x3, vnode_t *vp, int fd);
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);

#define vn_remove(path, x1, x2) remove(path)
Expand Down Expand Up @@ -760,8 +764,6 @@ typedef struct ace_object {
#define ACE_SYSTEM_ALARM_OBJECT_ACE_TYPE 0x08

extern struct _buf *kobj_open_file(char *name);
extern int kobj_read_file(struct _buf *file, char *buf, unsigned size,
unsigned off);
extern void kobj_close_file(struct _buf *file);
extern int kobj_get_filesize(struct _buf *file, uint64_t *size);
extern int zfs_secpolicy_snapshot_perms(const char *name, cred_t *cr);
Expand Down
29 changes: 29 additions & 0 deletions include/sys/zfs_file.h
Original file line number Diff line number Diff line change
@@ -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 */
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
64 changes: 0 additions & 64 deletions lib/libzpool/kernel.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,58 +584,6 @@ vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
return (ret);
}

/*ARGSUSED*/
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)
{
ssize_t rc, done = 0, split;

if (uio == UIO_READ) {
rc = pread64(vp->v_fd, addr, len, offset);
if (vp->v_dump_fd != -1 && rc != -1) {
int status;
status = pwrite64(vp->v_dump_fd, addr, rc, offset);
ASSERT(status != -1);
}
} else {
/*
* To simulate partial disk writes, we split writes into two
* system calls so that the process can be killed in between.
*/
int sectors = len >> SPA_MINBLOCKSHIFT;
split = (sectors > 0 ? rand() % sectors : 0) <<
SPA_MINBLOCKSHIFT;
rc = pwrite64(vp->v_fd, addr, split, offset);
if (rc != -1) {
done = rc;
rc = pwrite64(vp->v_fd, (char *)addr + split,
len - split, offset + split);
}
}

#ifdef __linux__
if (rc == -1 && errno == EINVAL) {
/*
* Under Linux, this most likely means an alignment issue
* (memory or disk) due to O_DIRECT, so we abort() in order to
* catch the offender.
*/
abort();
}
#endif
if (rc == -1)
return (errno);

done += rc;

if (residp)
*residp = len - done;
else if (done != len)
return (EIO);
return (0);
}

void
vn_close(vnode_t *vp)
{
Expand Down Expand Up @@ -879,18 +827,6 @@ kobj_open_file(char *name)
return (file);
}

int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
{
ssize_t resid = 0;

if (vn_rdwr(UIO_READ, (vnode_t *)file->_fd, buf, size, (offset_t)off,
UIO_SYSSPACE, 0, 0, 0, &resid) != 0)
return (-1);

return (size - resid);
}

void
kobj_close_file(struct _buf *file)
{
Expand Down
25 changes: 24 additions & 1 deletion module/os/linux/spl/spl-generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,27 @@ ddi_copyout(const void *from, void *to, size_t len, int flags)
}
EXPORT_SYMBOL(ddi_copyout);

static ssize_t
spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
{
#if defined(HAVE_KERNEL_READ_PPOS)
return (kernel_read(file, buf, count, pos));
#else
mm_segment_t saved_fs;
ssize_t ret;

saved_fs = get_fs();
set_fs(KERNEL_DS);

ret = vfs_read(file, (void __user *)buf, count, pos);

set_fs(saved_fs);

return (ret);
#endif
}


/*
* Read the unique system identifier from the /etc/hostid file.
*
Expand Down Expand Up @@ -566,6 +587,7 @@ hostid_read(uint32_t *hostid)
struct _buf *file;
uint32_t value = 0;
int error;
loff_t off;

file = kobj_open_file(spl_hostid_path);
if (file == (struct _buf *)-1)
Expand All @@ -582,11 +604,12 @@ hostid_read(uint32_t *hostid)
return (EINVAL);
}

off = 0;
/*
* Read directly into the variable like eglibc does.
* Short reads are okay; native behavior is preserved.
*/
error = kobj_read_file(file, (char *)&value, sizeof (value), 0);
error = spl_kernel_read(file->vp->v_file, &value, sizeof (value), &off);
if (error < 0) {
kobj_close_file(file);
return (EIO);
Expand Down
13 changes: 0 additions & 13 deletions module/os/linux/spl/spl-kobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,6 @@ kobj_close_file(struct _buf *file)
} /* kobj_close_file() */
EXPORT_SYMBOL(kobj_close_file);

int
kobj_read_file(struct _buf *file, char *buf, unsigned size, unsigned off)
{
ssize_t resid;

if (vn_rdwr(UIO_READ, file->vp, buf, size, (offset_t)off,
UIO_SYSSPACE, 0, 0, 0, &resid) != 0)
return (-1);

return (size - resid);
} /* kobj_read_file() */
EXPORT_SYMBOL(kobj_read_file);

int
kobj_get_filesize(struct _buf *file, uint64_t *size)
{
Expand Down
76 changes: 0 additions & 76 deletions module/os/linux/spl/spl-vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,46 +73,6 @@ spl_filp_fsync(struct file *fp, int sync)
#endif /* HAVE_2ARGS_VFS_FSYNC */
}

static ssize_t
spl_kernel_write(struct file *file, const void *buf, size_t count, loff_t *pos)
{
#if defined(HAVE_KERNEL_WRITE_PPOS)
return (kernel_write(file, buf, count, pos));
#else
mm_segment_t saved_fs;
ssize_t ret;

saved_fs = get_fs();
set_fs(KERNEL_DS);

ret = vfs_write(file, (__force const char __user *)buf, count, pos);

set_fs(saved_fs);

return (ret);
#endif
}

static ssize_t
spl_kernel_read(struct file *file, void *buf, size_t count, loff_t *pos)
{
#if defined(HAVE_KERNEL_READ_PPOS)
return (kernel_read(file, buf, count, pos));
#else
mm_segment_t saved_fs;
ssize_t ret;

saved_fs = get_fs();
set_fs(KERNEL_DS);

ret = vfs_read(file, (void __user *)buf, count, pos);

set_fs(saved_fs);

return (ret);
#endif
}

vtype_t
vn_mode_to_vtype(mode_t mode)
{
Expand Down Expand Up @@ -282,42 +242,6 @@ vn_openat(const char *path, uio_seg_t seg, int flags, int mode,
} /* vn_openat() */
EXPORT_SYMBOL(vn_openat);

int
vn_rdwr(uio_rw_t uio, vnode_t *vp, void *addr, ssize_t len, offset_t off,
uio_seg_t seg, int ioflag, rlim64_t x2, void *x3, ssize_t *residp)
{
struct file *fp = vp->v_file;
loff_t offset = off;
int rc;

ASSERT(uio == UIO_WRITE || uio == UIO_READ);
ASSERT(seg == UIO_SYSSPACE);
ASSERT((ioflag & ~FAPPEND) == 0);

if (ioflag & FAPPEND)
offset = fp->f_pos;

if (uio & UIO_WRITE)
rc = spl_kernel_write(fp, addr, len, &offset);
else
rc = spl_kernel_read(fp, addr, len, &offset);

fp->f_pos = offset;

if (rc < 0)
return (-rc);

if (residp) {
*residp = len - rc;
} else {
if (rc != len)
return (EIO);
}

return (0);
} /* vn_rdwr() */
EXPORT_SYMBOL(vn_rdwr);

int
vn_close(vnode_t *vp, int flags, int x1, int x2, void *x3, void *x4)
{
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
Loading

0 comments on commit d42257f

Please sign in to comment.