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/a6a4831c1613
branches:  trunk
changeset: 447129:a6a4831c1613
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 5a259da3cf81 -r a6a4831c1613 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 5a259da3cf81 -r a6a4831c1613 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 5a259da3cf81 -r a6a4831c1613 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 5a259da3cf81 -r a6a4831c1613 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