aboutsummaryrefslogtreecommitdiffstats
path: root/module
diff options
context:
space:
mode:
authorMatthew Macy <[email protected]>2019-12-13 07:54:10 -0800
committerBrian Behlendorf <[email protected]>2019-12-13 07:54:10 -0800
commit13a9a6f5e872fe45684f9ba12d1e322ced577849 (patch)
tree0fedd1c5ffb8fcb48b4139af7937cf4238e7b0de /module
parent9bb0d89c5c7f1bbf16ab410c25a087b691d428ac (diff)
Make zfs_replay.c work on FreeBSD
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
Diffstat (limited to 'module')
-rw-r--r--module/os/linux/zfs/zfs_vnops.c36
-rw-r--r--module/os/linux/zfs/zfs_znode.c6
-rw-r--r--module/zfs/zfs_replay.c34
3 files changed, 65 insertions, 11 deletions
diff --git a/module/os/linux/zfs/zfs_vnops.c b/module/os/linux/zfs/zfs_vnops.c
index b1fa89167..ec63dbdeb 100644
--- a/module/os/linux/zfs/zfs_vnops.c
+++ b/module/os/linux/zfs/zfs_vnops.c
@@ -974,6 +974,42 @@ zfs_write(struct inode *ip, uio_t *uio, int ioflag, cred_t *cr)
}
/*
+ * 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
* the current context. Doing so while holding open a tx could result
diff --git a/module/os/linux/zfs/zfs_znode.c b/module/os/linux/zfs/zfs_znode.c
index a476e58dd..45f19785d 100644
--- a/module/os/linux/zfs/zfs_znode.c
+++ b/module/os/linux/zfs/zfs_znode.c
@@ -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)
diff --git a/module/zfs/zfs_replay.c b/module/zfs/zfs_replay.c
index b94c946dd..59a219983 100644
--- a/module/zfs/zfs_replay.c
+++ b/module/zfs/zfs_replay.c
@@ -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;
}
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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);
@@ -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)
@@ -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 */