Skip to content

Commit

Permalink
Make zfs_replay.c work on FreeBSD
Browse files Browse the repository at this point in the history
FreeBSD's vfs currently doesn't permit file systems
to do their own locking. To avoid having to have
duplicate zfs functions with and without locking add
locking here. With luck these changes can be removed
in the future.

Reviewed-by: Sean Eric Fagan <[email protected]>
Reviewed-by: Jorgen Lundman <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Matt Macy <[email protected]>
Closes #9715
  • Loading branch information
mattmacy authored and behlendorf committed Dec 13, 2019
1 parent 9bb0d89 commit 13a9a6f
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 11 deletions.
2 changes: 2 additions & 0 deletions include/os/linux/zfs/sys/zfs_vnops.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ 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_read(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr);
extern int zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr);
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);
Expand Down
36 changes: 36 additions & 0 deletions module/os/linux/zfs/zfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -973,6 +973,42 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
return (0);
}

/*
* Write the bytes to a file.
*
* IN: zp - znode of file to be written to
* data - bytes to write
* len - number of bytes to write
* pos - offset to start writing at
*
* OUT: resid - remaining bytes to write
*
* RETURN: 0 if success
* positive error code if failure
*
* Timestamps:
* zp - ctime|mtime updated if byte count > 0
*/
int
zfs_write_simple(znode_t *zp, const void *data, size_t len,
loff_t pos, size_t *resid)
{
ssize_t written;
int error = 0;

written = zpl_write_common(ZTOI(zp), data, len, &pos,
UIO_SYSSPACE, 0, kcred);
if (written < 0) {
error = -written;
} else if (resid == NULL) {
if (written < len)
error = SET_ERROR(EIO); /* short write */
} else {
*resid = len - written;
}
return (error);
}

/*
* Drop a reference on the passed inode asynchronously. This ensures
* that the caller will never drop the last reference on an inode in
Expand Down
6 changes: 6 additions & 0 deletions module/os/linux/zfs/zfs_znode.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,12 @@ zfs_znode_hold_exit(zfsvfs_t *zfsvfs, znode_hold_t *zh)
kmem_cache_free(znode_hold_cache, zh);
}

dev_t
zfs_cmpldev(uint64_t dev)
{
return (dev);
}

static void
zfs_znode_sa_init(zfsvfs_t *zfsvfs, znode_t *zp,
dmu_buf_t *db, dmu_object_type_t obj_type, sa_handle_t *sa_hdl)
Expand Down
34 changes: 23 additions & 11 deletions module/zfs/zfs_replay.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ zfs_init_vattr(vattr_t *vap, uint64_t mask, uint64_t mode,
vap->va_mode = mode;
vap->va_uid = (uid_t)(IS_EPHEMERAL(uid)) ? -1 : uid;
vap->va_gid = (gid_t)(IS_EPHEMERAL(gid)) ? -1 : gid;
vap->va_rdev = rdev;
vap->va_rdev = zfs_cmpldev(rdev);
vap->va_nodeid = nodeid;
}

Expand Down Expand Up @@ -493,6 +493,9 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
lr->lr_uid, lr->lr_gid);
}

#ifdef __FreeBSD__
vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY);
#endif
switch (txtype) {
case TX_CREATE_ATTR:
lrattr = (lr_attr_t *)(caddr_t)(lr + 1);
Expand Down Expand Up @@ -543,6 +546,9 @@ zfs_replay_create(void *arg1, void *arg2, boolean_t byteswap)
error = SET_ERROR(ENOTSUP);
}

#ifdef __FreeBSD__
VOP_UNLOCK(ZTOV(dzp), 0);
#endif
out:
if (error == 0 && zp != NULL)
zrele(zp);
Expand Down Expand Up @@ -574,6 +580,9 @@ zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
if (lr->lr_common.lrc_txtype & TX_CI)
vflg |= FIGNORECASE;

#ifdef __FreeBSD__
vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY);
#endif
switch ((int)lr->lr_common.lrc_txtype) {
case TX_REMOVE:
error = zfs_remove(dzp, name, kcred, vflg);
Expand All @@ -585,6 +594,9 @@ zfs_replay_remove(void *arg1, void *arg2, boolean_t byteswap)
error = SET_ERROR(ENOTSUP);
}

#ifdef __FreeBSD__
VOP_UNLOCK(ZTOV(dzp), 0);
#endif
zrele(dzp);

return (error);
Expand Down Expand Up @@ -614,8 +626,15 @@ zfs_replay_link(void *arg1, void *arg2, boolean_t byteswap)
if (lr->lr_common.lrc_txtype & TX_CI)
vflg |= FIGNORECASE;

#ifdef __FreeBSD__
vn_lock(ZTOV(dzp), LK_EXCLUSIVE | LK_RETRY);
vn_lock(ZTOV(zp), LK_EXCLUSIVE | LK_RETRY);
#endif
error = zfs_link(dzp, zp, name, kcred, vflg);

#ifdef __FreeBSD__
VOP_UNLOCK(ZTOV(zp), 0);
VOP_UNLOCK(ZTOV(dzp), 0);
#endif
zrele(zp);
zrele(dzp);

Expand Down Expand Up @@ -662,7 +681,7 @@ zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap)
lr_write_t *lr = arg2;
char *data = (char *)(lr + 1); /* data follows lr_write_t */
znode_t *zp;
int error, written;
int error;
uint64_t eod, offset, length;

if (byteswap)
Expand Down Expand Up @@ -706,14 +725,7 @@ zfs_replay_write(void *arg1, void *arg2, boolean_t byteswap)
if (zp->z_size < eod)
zfsvfs->z_replay_eof = eod;
}

written = zpl_write_common(ZTOI(zp), data, length, &offset,
UIO_SYSSPACE, 0, kcred);
if (written < 0)
error = -written;
else if (written < length)
error = SET_ERROR(EIO); /* short write */

error = zfs_write_simple(zp, data, length, offset, NULL);
zrele(zp);
zfsvfs->z_replay_eof = 0; /* safety */

Expand Down

0 comments on commit 13a9a6f

Please sign in to comment.