Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/external/cddl/osnet/dist/uts/common/fs/zfs Cannot hold zfs o...
details: https://anonhg.NetBSD.org/src/rev/4ed2c6a58c6f
branches: trunk
changeset: 995681:4ed2c6a58c6f
user: hannken <hannken%NetBSD.org@localhost>
date: Tue Jan 01 10:08:00 2019 +0000
description:
Cannot hold zfs object across call to vcache_get() as it might
deadlock with another reclaim.
Add vfs operation zfs_newvnode() to create a new zfs node and
hold the zfs object in zfs_loadvnode() and zfs_newvnode() only.
diffstat:
external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_znode.h | 2 +
external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c | 3 -
external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c | 1 +
external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c | 367 +++++-------
4 files changed, 157 insertions(+), 216 deletions(-)
diffs (truncated from 558 to 300 lines):
diff -r 04b4fa015e50 -r 4ed2c6a58c6f external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_znode.h
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_znode.h Tue Jan 01 10:06:54 2019 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/sys/zfs_znode.h Tue Jan 01 10:08:00 2019 +0000
@@ -334,6 +334,8 @@
#ifdef __NetBSD__
extern int zfs_loadvnode(struct mount *, struct vnode *,
const void *, size_t, const void **);
+extern int zfs_newvnode(struct mount *, struct vnode *, struct vnode *,
+ struct vattr *, kauth_cred_t, void *, size_t *, const void **);
extern int zfs_zget_cleaner(zfsvfs_t *, uint64_t, znode_t **);
#endif
extern int zfs_zget(zfsvfs_t *, uint64_t, znode_t **);
diff -r 04b4fa015e50 -r 4ed2c6a58c6f external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c Tue Jan 01 10:06:54 2019 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_ioctl.c Tue Jan 01 10:08:00 2019 +0000
@@ -7120,7 +7120,6 @@
uint64_t availrmem;
extern struct vfsops zfs_vfsops;
- extern uint_t zfs_loadvnode_key;
extern uint_t zfs_putpage_key;
switch (cmd) {
@@ -7144,7 +7143,6 @@
tsd_create(&zfs_fsyncer_key, NULL);
tsd_create(&rrw_tsd_key, rrw_tsd_destroy);
tsd_create(&zfs_allow_log_key, zfs_allow_log_destroy);
- tsd_create(&zfs_loadvnode_key, zfs_loadvnode_destroy);
tsd_create(&zfs_putpage_key, NULL);
spa_init(FREAD | FWRITE);
@@ -7179,7 +7177,6 @@
spa_fini();
tsd_destroy(&zfs_putpage_key);
- tsd_destroy(&zfs_loadvnode_key);
tsd_destroy(&zfs_fsyncer_key);
tsd_destroy(&rrw_tsd_key);
tsd_destroy(&zfs_allow_log_key);
diff -r 04b4fa015e50 -r 4ed2c6a58c6f external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c Tue Jan 01 10:06:54 2019 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vfsops.c Tue Jan 01 10:08:00 2019 +0000
@@ -163,6 +163,7 @@
.vfs_sync = zfs_netbsd_sync,
.vfs_vget = zfs_vget,
.vfs_loadvnode = zfs_loadvnode,
+ .vfs_newvnode = zfs_newvnode,
.vfs_init = zfs_init,
.vfs_done = zfs_fini,
.vfs_start = (void *)nullop,
diff -r 04b4fa015e50 -r 4ed2c6a58c6f external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c
--- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c Tue Jan 01 10:06:54 2019 +0000
+++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c Tue Jan 01 10:08:00 2019 +0000
@@ -60,15 +60,6 @@
extern int (**zfs_fifoop_p)(void *);
extern int (**zfs_specop_p)(void *);
-struct zfs_loadvnode_args {
- dmu_buf_t *db;
- int blksz;
- dmu_object_type_t obj_type;
- void *sa_hdl;
-};
-
-uint_t zfs_loadvnode_key;
-
#endif
#endif /* _KERNEL */
@@ -621,6 +612,7 @@
vgone(vp);
vput(vp);
}
+#endif /* __FreeBSD__ */
/*
* Construct a new znode/vnode and intialize.
@@ -630,11 +622,18 @@
* return the znode
*/
static znode_t *
+#ifdef __NetBSD__
+zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
+ dmu_object_type_t obj_type, sa_handle_t *hdl, vnode_t *vp)
+#else
zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz,
dmu_object_type_t obj_type, sa_handle_t *hdl)
+#endif
{
znode_t *zp;
+#ifndef __NetBSD__
vnode_t *vp;
+#endif
uint64_t mode;
uint64_t parent;
sa_bulk_attr_t bulk[9];
@@ -643,6 +642,7 @@
zp = kmem_cache_alloc(znode_cache, KM_SLEEP);
+#ifndef __NetBSD__
KASSERT(curthread->td_vp_reserv > 0,
("zfs_znode_alloc: getnewvnode without any vnodes reserved"));
error = getnewvnode("zfs", zfsvfs->z_parent->z_vfs, &zfs_vnodeops, &vp);
@@ -650,6 +650,7 @@
kmem_cache_free(znode_cache, zp);
return (NULL);
}
+#endif
zp->z_vnode = vp;
vp->v_data = zp;
@@ -669,6 +670,12 @@
zp->z_seq = 0x7A4653;
zp->z_sync_cnt = 0;
+#ifdef __NetBSD__
+ vp->v_op = zfs_vnodeop_p;
+ vp->v_tag = VT_ZFS;
+ zp->z_lockf = NULL;
+#endif
+
vp = ZTOV(zp);
zfs_znode_sa_init(zfsvfs, zp, db, obj_type, hdl);
@@ -692,7 +699,9 @@
if (sa_bulk_lookup(zp->z_sa_hdl, bulk, count) != 0 || zp->z_gen == 0) {
if (hdl == NULL)
sa_handle_destroy(zp->z_sa_hdl);
+#ifndef __NetBSD__
zfs_vnode_forget(vp);
+#endif
zp->z_vnode = NULL;
kmem_cache_free(znode_cache, zp);
return (NULL);
@@ -706,7 +715,7 @@
case VDIR:
zp->z_zn_prefetch = B_TRUE; /* z_prefetch default is enabled */
break;
-#ifdef illumos
+#if defined(illumos) || defined(__NetBSD__)
case VBLK:
case VCHR:
{
@@ -714,11 +723,19 @@
VERIFY(sa_lookup(zp->z_sa_hdl, SA_ZPL_RDEV(zfsvfs),
&rdev, sizeof (rdev)) == 0);
+#ifdef illumos
vp->v_rdev = zfs_cmpldev(rdev);
+#else
+ spec_node_init(vp, zfs_cmpldev(rdev));
+#endif
}
break;
#endif
case VFIFO:
+#ifdef __NetBSD__
+ /* XXX NetBSD vp->v_op = zfs_fifoop_p; */
+ break;
+#else /* __NetBSD__ */
#ifdef illumos
case VSOCK:
case VDOOR:
@@ -739,8 +756,15 @@
vn_setops(vp, zfs_evnodeops);
break;
#endif
+#endif /* __NetBSD__ */
}
+#ifdef __NetBSD__
+ extern const struct genfs_ops zfs_genfsops;
+ genfs_node_init(vp, &zfs_genfsops);
+ uvm_vnp_setsize(vp, zp->z_size);
+#endif
+
mutex_enter(&zfsvfs->z_znodes_lock);
list_insert_tail(&zfsvfs->z_all_znodes, zp);
membar_producer();
@@ -751,6 +775,7 @@
zp->z_zfsvfs = zfsvfs;
mutex_exit(&zfsvfs->z_znodes_lock);
+#ifndef __NetBSD__
/*
* Acquire vnode lock before making it available to the world.
*/
@@ -758,13 +783,13 @@
VN_LOCK_AREC(vp);
if (vp->v_type != VFIFO)
VN_LOCK_ASHARE(vp);
+#endif
-#ifdef illumos
+#if defined(illumos) || defined(__NetBSD__)
VFS_HOLD(zfsvfs->z_vfs);
#endif
return (zp);
}
-#endif /* __FreeBSD__ */
static uint64_t empty_xattr;
static uint64_t pad[4];
@@ -786,10 +811,119 @@
* OUT: zpp - allocated znode
*
*/
+#ifdef __NetBSD__
+struct zfs_newvnode_args {
+ dmu_tx_t *tx;
+ uint_t flag;
+ zfs_acl_ids_t *acl_ids;
+};
+
+static void
+zfs_mknode1(znode_t *, vattr_t *, dmu_tx_t *, cred_t *,
+ uint_t, znode_t **, zfs_acl_ids_t *, vnode_t *);
+
+int
+zfs_loadvnode(struct mount *mp, struct vnode *vp,
+ const void *key, size_t key_len, const void **new_key)
+{
+ int err, blksz;
+ uint64_t obj_num;
+ zfsvfs_t *zfsvfs;
+ dmu_buf_t *db;
+ dmu_object_info_t doi;
+ dmu_object_type_t obj_type;
+ sa_handle_t *hdl;
+ znode_t *zp;
+
+ KASSERT(key_len == sizeof(obj_num));
+ memcpy(&obj_num, key, key_len);
+
+ zfsvfs = mp->mnt_data;
+
+ ZFS_OBJ_HOLD_ENTER(zfsvfs, obj_num);
+
+ err = sa_buf_hold(zfsvfs->z_os, obj_num, NULL, &db);
+ if (err) {
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+ return (SET_ERROR(err));
+ }
+
+ dmu_object_info_from_db(db, &doi);
+ if (doi.doi_bonus_type != DMU_OT_SA &&
+ (doi.doi_bonus_type != DMU_OT_ZNODE ||
+ (doi.doi_bonus_type == DMU_OT_ZNODE &&
+ doi.doi_bonus_size < sizeof (znode_phys_t)))) {
+ sa_buf_rele(db, NULL);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+ return (SET_ERROR(EINVAL));
+ }
+ blksz = doi.doi_data_block_size;
+ obj_type = doi.doi_bonus_type;
+ hdl = dmu_buf_get_user(db);
+
+ if (hdl != NULL) {
+ sa_buf_rele(db, NULL);
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+ return (SET_ERROR(ENOENT));
+ }
+
+ zp = zfs_znode_alloc(zfsvfs, db, blksz, obj_type, hdl, vp);
+ if (zp == NULL) {
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+ return (SET_ERROR(ENOENT));
+ }
+ ASSERT(zp == VTOZ(vp));
+
+ ZFS_OBJ_HOLD_EXIT(zfsvfs, obj_num);
+
+ *new_key = &zp->z_id;
+
+ return 0;
+}
+
+int
+zfs_newvnode(struct mount *mp, vnode_t *dvp, vnode_t *vp, vattr_t *vap,
+ cred_t *cr, void *extra, size_t *key_len, const void **new_key)
+{
+ struct zfs_newvnode_args *args = extra;
+ znode_t *zp, *dzp = VTOZ(dvp);
+ dmu_tx_t *tx = args->tx;
+ uint_t flag = args->flag;
+ zfs_acl_ids_t *acl_ids = args->acl_ids;
+
+ zfs_mknode1(dzp, vap, tx, cr, flag, &zp, acl_ids, vp);
+ ASSERT(zp == VTOZ(vp));
+ *key_len = sizeof(zp->z_id);
+ *new_key = &zp->z_id;
+
+ return 0;
+}
+
void
zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
uint_t flag, znode_t **zpp, zfs_acl_ids_t *acl_ids)
{
Home |
Main Index |
Thread Index |
Old Index