hammer2 - Support multiple PFS mounts from the same device
authorMatthew Dillon <dillon@apollo.backplane.com>
Fri, 6 Apr 2012 06:40:03 +0000 (23:40 -0700)
committerMatthew Dillon <dillon@apollo.backplane.com>
Fri, 6 Apr 2012 06:40:03 +0000 (23:40 -0700)
* Implement hammer2_pfsmount_t and move hmp->rchain, hmp->iroot, and
  a few other fields into the new structure.

  struct mount -> struct hammer2_pfsmount (pmp) -> struct hammer2_mount (hmp).

* Implement mount/umount logic to allow the device to be overloaded.
  Multiple PFS labels associated with the same media may now be mounted.

* Generate a unique pfs_fsid for each PFS created, the {pfs_fsid, pfs_id}
  tuple forms a unique key that the userland helper will use to distinguish
  registrations.

sys/vfs/hammer2/hammer2.h
sys/vfs/hammer2/hammer2_chain.c
sys/vfs/hammer2/hammer2_inode.c
sys/vfs/hammer2/hammer2_ioctl.c
sys/vfs/hammer2/hammer2_vfsops.c
sys/vfs/hammer2/hammer2_vnops.c

index 06e9fc9..cb4b071 100644 (file)
@@ -70,6 +70,7 @@
 struct hammer2_chain;
 struct hammer2_inode;
 struct hammer2_mount;
+struct hammer2_pfsmount;
 
 /*
  * The chain structure tracks blockref recursions all the way to
@@ -136,6 +137,7 @@ SPLAY_PROTOTYPE(hammer2_chain_splay, hammer2_chain, snode, hammer2_chain_cmp);
 #define HAMMER2_CHAIN_DEFERRED         0x00000200      /* on a deferral list*/
 #define HAMMER2_CHAIN_DESTROYED                0x00000400      /* destroying */
 #define HAMMER2_CHAIN_MODIFIED_AUX     0x00000800      /* hmp->vchain only */
+#define HAMMER2_CHAIN_MOUNTED          0x00001000      /* PFS is mounted */
 
 /*
  * Flags passed to hammer2_chain_lookup() and hammer2_chain_next()
@@ -204,7 +206,8 @@ SPLAY_PROTOTYPE(hammer2_chain_splay, hammer2_chain, snode, hammer2_chain_cmp);
  * A hammer2 inode.
  */
 struct hammer2_inode {
-       struct hammer2_mount    *hmp;
+       struct hammer2_mount    *hmp;           /* Global mount */
+       struct hammer2_pfsmount *pmp;           /* PFS mount */
        struct hammer2_inode    *pip;           /* parent inode */
        struct vnode            *vp;
        hammer2_chain_t         chain;
@@ -233,13 +236,13 @@ struct hammer2_data {
 typedef struct hammer2_data hammer2_data_t;
 
 /*
- * Governing mount structure for filesystem (aka vp->v_mount)
+ * Global (per device) mount structure for device (aka vp->v_mount->hmp)
  */
 struct hammer2_mount {
-       struct mount    *mp;            /* kernel mount */
        struct vnode    *devvp;         /* device vnode */
-       struct netexport export;        /* nfs export */
        int             ronly;          /* read-only mount */
+       int             pmp_count;      /* PFS mounts backed by us */
+       TAILQ_ENTRY(hammer2_mount) mntentry; /* hammer2_mntlist */
 
        struct malloc_type *minode;
        int             ninodes;
@@ -250,8 +253,6 @@ struct hammer2_mount {
        int             maxipstacks;
        hammer2_chain_t vchain;         /* anchor chain */
        hammer2_chain_t *schain;        /* super-root */
-       hammer2_chain_t *rchain;        /* label-root */
-       struct hammer2_inode *iroot;
        struct lock     alloclk;        /* lockmgr lock */
        struct lock     voldatalk;      /* lockmgr lock */
 
@@ -261,25 +262,39 @@ struct hammer2_mount {
 
 typedef struct hammer2_mount hammer2_mount_t;
 
+/*
+ * Per-PFS mount structure for device (aka vp->v_mount)
+ */
+struct hammer2_pfsmount {
+       struct mount            *mp;            /* kernel mount */
+       struct hammer2_mount    *hmp;           /* device global mount */
+       hammer2_chain_t         *rchain;        /* PFS root chain */
+       hammer2_inode_t         *iroot;         /* PFS root inode */
+       struct netexport        export;         /* nfs export */
+       int                     ronly;          /* read-only mount */
+};
+
+typedef struct hammer2_pfsmount hammer2_pfsmount_t;
+
 #if defined(_KERNEL)
 
 MALLOC_DECLARE(M_HAMMER2);
 
+#define VTOI(vp)       ((hammer2_inode_t *)(vp)->v_data)
+#define ITOV(ip)       ((ip)->vp)
+
 static __inline
-struct mount *
-H2TOMP(struct hammer2_mount *hmp)
+hammer2_pfsmount_t *
+MPTOPMP(struct mount *mp)
 {
-       return (struct mount *) hmp->mp;
+       return ((hammer2_pfsmount_t *)mp->mnt_data);
 }
 
-#define VTOI(vp)       ((hammer2_inode_t *)(vp)->v_data)
-#define ITOV(ip)       ((ip)->vp)
-
 static __inline
-struct hammer2_mount *
-MPTOH2(struct mount *mp)
+hammer2_mount_t *
+MPTOHMP(struct mount *mp)
 {
-       return (hammer2_mount_t *) mp->mnt_data;
+       return (((hammer2_pfsmount_t *)mp->mnt_data)->hmp);
 }
 
 extern struct vop_ops hammer2_vnode_vops;
@@ -336,17 +351,16 @@ int hammer2_calc_logical(hammer2_inode_t *ip, hammer2_off_t uoff,
  */
 struct vnode *hammer2_igetv(hammer2_inode_t *ip, int *errorp);
 
-hammer2_inode_t *hammer2_inode_alloc(hammer2_mount_t *hmp, void *data);
+hammer2_inode_t *hammer2_inode_alloc(hammer2_pfsmount_t *pmp, void *data);
 void hammer2_inode_free(hammer2_inode_t *ip);
 void hammer2_inode_ref(hammer2_inode_t *ip);
 void hammer2_inode_drop(hammer2_inode_t *ip);
 int hammer2_inode_calc_alloc(hammer2_key_t filesize);
 
-int hammer2_inode_create(hammer2_mount_t *hmp,
-                       struct vattr *vap, struct ucred *cred,
-                       hammer2_inode_t *dip,
-                       const uint8_t *name, size_t name_len,
-                       hammer2_inode_t **nipp);
+int hammer2_inode_create(hammer2_inode_t *dip,
+                        struct vattr *vap, struct ucred *cred,
+                        const uint8_t *name, size_t name_len,
+                        hammer2_inode_t **nipp);
 
 int hammer2_inode_connect(hammer2_inode_t *dip, hammer2_inode_t *nip,
                        const uint8_t *name, size_t name_len);
index 90fec61..579efcc 100644 (file)
@@ -942,8 +942,10 @@ hammer2_chain_get(hammer2_mount_t *hmp, hammer2_chain_t *parent,
        if (bref->type == HAMMER2_BREF_TYPE_INODE) {
                while (parent->bref.type == HAMMER2_BREF_TYPE_INDIRECT)
                        parent = parent->parent;
-               if (parent->bref.type == HAMMER2_BREF_TYPE_INODE)
+               if (parent->bref.type == HAMMER2_BREF_TYPE_INODE) {
                        chain->u.ip->pip = parent->u.ip;
+                       chain->u.ip->pmp = parent->u.ip->pmp;
+               }
        }
 
        /*
@@ -1504,8 +1506,10 @@ again:
                hammer2_chain_t *scan = parent;
                while (scan->bref.type == HAMMER2_BREF_TYPE_INDIRECT)
                        scan = scan->parent;
-               if (scan->bref.type == HAMMER2_BREF_TYPE_INODE)
+               if (scan->bref.type == HAMMER2_BREF_TYPE_INODE) {
                        chain->u.ip->pip = scan->u.ip;
+                       chain->u.ip->pmp = scan->u.ip->pmp;
+               }
        }
 
        /*
index d8fd256..3a4b18d 100644 (file)
@@ -78,9 +78,10 @@ struct vnode *
 hammer2_igetv(hammer2_inode_t *ip, int *errorp)
 {
        struct vnode *vp;
-       hammer2_mount_t *hmp;
+       hammer2_pfsmount_t *pmp;
 
-       hmp = ip->hmp;
+       pmp = ip->pmp;
+       KKASSERT(pmp != NULL);
        *errorp = 0;
 
        for (;;) {
@@ -124,7 +125,7 @@ hammer2_igetv(hammer2_inode_t *ip, int *errorp)
                 * allocation races.  This function will return an
                 * exclusively locked and referenced vnode.
                 */
-               *errorp = getnewvnode(VT_HAMMER2, H2TOMP(hmp), &vp, 0, 0);
+               *errorp = getnewvnode(VT_HAMMER2, pmp->mp, &vp, 0, 0);
                if (*errorp) {
                        vp = NULL;
                        break;
@@ -169,12 +170,12 @@ hammer2_igetv(hammer2_inode_t *ip, int *errorp)
                        break;
                }
 
-               if (ip == hmp->iroot)
+               if (ip == pmp->iroot)
                        vsetflags(vp, VROOT);
 
                vp->v_data = ip;
                ip->vp = vp;
-               hammer2_chain_ref(hmp, &ip->chain);     /* vp association */
+               hammer2_chain_ref(ip->hmp, &ip->chain); /* vp association */
                hammer2_inode_unlock_ex(ip);
                break;
        }
@@ -201,12 +202,12 @@ hammer2_igetv(hammer2_inode_t *ip, int *errorp)
  * under the super-root, so the inode number is set to 1 in this case.
  */
 int
-hammer2_inode_create(hammer2_mount_t *hmp,
+hammer2_inode_create(hammer2_inode_t *dip,
                     struct vattr *vap, struct ucred *cred,
-                    hammer2_inode_t *dip,
                     const uint8_t *name, size_t name_len,
                     hammer2_inode_t **nipp)
 {
+       hammer2_mount_t *hmp = dip->hmp;
        hammer2_chain_t *chain;
        hammer2_chain_t *parent;
        hammer2_inode_t *nip;
index f0606d0..74ab131 100644 (file)
@@ -355,14 +355,14 @@ hammer2_ioctl_pfs_create(hammer2_inode_t *ip, void *data)
        int error;
 
        pfs->name[sizeof(pfs->name) - 1] = 0;   /* ensure 0-termination */
-       error = hammer2_inode_create(hmp, NULL, NULL, hmp->schain->u.ip,
+       error = hammer2_inode_create(hmp->schain->u.ip, NULL, NULL,
                                     pfs->name, strlen(pfs->name),
                                     &nip);
        if (error == 0) {
                hammer2_chain_modify(hmp, &nip->chain, 0);
                nip->ip_data.pfs_type = pfs->pfs_type;
                nip->ip_data.pfs_id = pfs->pfs_id;
-               /* nip->ip_data.pfsfsid = XXX */
+               nip->ip_data.pfs_fsid = pfs->pfs_fsid;
                hammer2_chain_unlock(hmp, &nip->chain);
        }
        return (error);
index 2ece8ad..9d4958a 100644 (file)
@@ -52,6 +52,10 @@ struct hammer2_sync_info {
        int waitfor;
 };
 
+TAILQ_HEAD(hammer2_mntlist, hammer2_mount);
+static struct hammer2_mntlist hammer2_mntlist;
+static struct lock hammer2_mntlk;
+
 int hammer2_debug;
 int hammer2_cluster_enable = 1;
 long hammer2_iod_file_read;
@@ -170,6 +174,9 @@ hammer2_vfs_init(struct vfsconf *conf)
        if (error)
                kprintf("HAMMER2 structure size mismatch; cannot continue.\n");
 
+       lockinit(&hammer2_mntlk, "mntlk", 0, 0);
+       TAILQ_INIT(&hammer2_mntlist);
+
        return (error);
 }
 
@@ -199,6 +206,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
              struct ucred *cred)
 {
        struct hammer2_mount_info info;
+       hammer2_pfsmount_t *pmp;
        hammer2_mount_t *hmp;
        hammer2_key_t lhc;
        struct vnode *devvp;
@@ -212,9 +220,11 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
        char *dev;
        char *label;
        int ronly = 1;
+       int create_hmp;
        int error;
 
        hmp = NULL;
+       pmp = NULL;
        dev = NULL;
        label = NULL;
        devvp = NULL;
@@ -253,7 +263,7 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
                if (mp->mnt_flag & MNT_UPDATE) {
                        /* Update mount */
                        /* HAMMER2 implements NFS export via mountctl */
-                       hmp = MPTOH2(mp);
+                       hmp = MPTOHMP(mp);
                        devvp = hmp->devvp;
                        error = hammer2_remount(mp, path, devvp, cred);
                        return error;
@@ -275,28 +285,51 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
                if (vn_isdisk(devvp, &error))
                        error = vfs_mountedon(devvp);
        }
-       if (error == 0 && vcount(devvp) > 0)
-               error = EBUSY;
 
        /*
-        * Now open the device
+        * Determine if the device has already been mounted.  After this
+        * check hmp will be non-NULL if we are doing the second or more
+        * hammer2 mounts from the same device.
         */
-       if (error == 0) {
-               ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
-               vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
-               error = vinvalbuf(devvp, V_SAVE, 0, 0);
+       lockmgr(&hammer2_mntlk, LK_EXCLUSIVE);
+       TAILQ_FOREACH(hmp, &hammer2_mntlist, mntentry) {
+               if (hmp->devvp == devvp)
+                       break;
+       }
+
+       /*
+        * Open the device if this isn't a secondary mount
+        */
+       if (hmp) {
+               create_hmp = 0;
+       } else {
+               create_hmp = 1;
+               if (error == 0 && vcount(devvp) > 0)
+                       error = EBUSY;
+
+               /*
+                * Now open the device
+                */
                if (error == 0) {
-                       error = VOP_OPEN(devvp, ronly ? FREAD : FREAD | FWRITE,
-                                        FSCRED, NULL);
+                       ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
+                       vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY);
+                       error = vinvalbuf(devvp, V_SAVE, 0, 0);
+                       if (error == 0) {
+                               error = VOP_OPEN(devvp,
+                                                ronly ? FREAD : FREAD | FWRITE,
+                                                FSCRED, NULL);
+                       }
+                       vn_unlock(devvp);
+               }
+               if (error && devvp) {
+                       vrele(devvp);
+                       devvp = NULL;
+               }
+               if (error) {
+                       lockmgr(&hammer2_mntlk, LK_RELEASE);
+                       return error;
                }
-               vn_unlock(devvp);
-       }
-       if (error && devvp) {
-               vrele(devvp);
-               devvp = NULL;
        }
-       if (error)
-               return error;
 
        /*
         * Block device opened successfully, finish initializing the
@@ -304,37 +337,48 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
         *
         * From this point on we have to call hammer2_unmount() on failure.
         */
-       hmp = kmalloc(sizeof(*hmp), M_HAMMER2, M_WAITOK | M_ZERO);
-       mp->mnt_data = (qaddr_t)hmp;
-       hmp->mp = mp;
-       hmp->ronly = ronly;
-       hmp->devvp = devvp;
-       kmalloc_create(&hmp->minode, "HAMMER2-inodes");
-       kmalloc_create(&hmp->mchain, "HAMMER2-chains");
+       pmp = kmalloc(sizeof(*pmp), M_HAMMER2, M_WAITOK | M_ZERO);
+       mp->mnt_data = (qaddr_t)pmp;
+       pmp->mp = mp;
+
+       if (create_hmp) {
+               hmp = kmalloc(sizeof(*hmp), M_HAMMER2, M_WAITOK | M_ZERO);
+               hmp->ronly = ronly;
+               hmp->devvp = devvp;
+               kmalloc_create(&hmp->minode, "HAMMER2-inodes");
+               kmalloc_create(&hmp->mchain, "HAMMER2-chains");
+               TAILQ_INSERT_TAIL(&hammer2_mntlist, hmp, mntentry);
+       }
+       pmp->hmp = hmp;
+       ++hmp->pmp_count;
+       lockmgr(&hammer2_mntlk, LK_RELEASE);
+       kprintf("hammer2_mount hmp=%p pmpcnt=%d\n", hmp, hmp->pmp_count);
        
        mp->mnt_flag = MNT_LOCAL;
        mp->mnt_kern_flag |= MNTK_ALL_MPSAFE;   /* all entry pts are SMP */
 
-       /*
-        * vchain setup. vchain.data is special cased to NULL.  vchain.refs
-        * is initialized and will never drop to 0.
-        */
-       hmp->vchain.bref.type = HAMMER2_BREF_TYPE_VOLUME;
-       hmp->vchain.refs = 1;
-       hmp->vchain.data = (void *)&hmp->voldata;
-       hmp->vchain.bref.data_off = 0 | HAMMER2_PBUFRADIX;
-       /* hmp->vchain.u.xxx is left NULL */
-       lockinit(&hmp->vchain.lk, "volume", 0, LK_CANRECURSE);
-       lockinit(&hmp->alloclk, "h2alloc", 0, 0);
-       lockinit(&hmp->voldatalk, "voldata", 0, LK_CANRECURSE);
+       if (create_hmp) {
+               /*
+                * vchain setup. vchain.data is special cased to NULL.
+                * vchain.refs is initialized and will never drop to 0.
+                */
+               hmp->vchain.bref.type = HAMMER2_BREF_TYPE_VOLUME;
+               hmp->vchain.refs = 1;
+               hmp->vchain.data = (void *)&hmp->voldata;
+               hmp->vchain.bref.data_off = 0 | HAMMER2_PBUFRADIX;
+               /* hmp->vchain.u.xxx is left NULL */
+               lockinit(&hmp->vchain.lk, "volume", 0, LK_CANRECURSE);
+               lockinit(&hmp->alloclk, "h2alloc", 0, 0);
+               lockinit(&hmp->voldatalk, "voldata", 0, LK_CANRECURSE);
 
-       /*
-        * Install the volume header
-        */
-       error = hammer2_install_volume_header(hmp);
-       if (error) {
-               hammer2_vfs_unmount(mp, MNT_FORCE);
-               return error;
+               /*
+                * Install the volume header
+                */
+               error = hammer2_install_volume_header(hmp);
+               if (error) {
+                       hammer2_vfs_unmount(mp, MNT_FORCE);
+                       return error;
+               }
        }
 
        /*
@@ -358,20 +402,26 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
         * Then locate the root inode by scanning the directory keyspace
         * represented by the label.
         */
-       lhc = hammer2_dirhash(label, strlen(label));
-       parent = &hmp->vchain;
-       hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
-       schain = hammer2_chain_lookup(hmp, &parent,
+       if (create_hmp) {
+               parent = &hmp->vchain;
+               hammer2_chain_lock(hmp, parent, HAMMER2_RESOLVE_ALWAYS);
+               schain = hammer2_chain_lookup(hmp, &parent,
                                      HAMMER2_SROOT_KEY, HAMMER2_SROOT_KEY, 0);
-       hammer2_chain_unlock(hmp, parent);
-       if (schain == NULL) {
-               kprintf("hammer2_mount: invalid super-root\n");
-               hammer2_vfs_unmount(mp, MNT_FORCE);
-               return EINVAL;
+               hammer2_chain_unlock(hmp, parent);
+               if (schain == NULL) {
+                       kprintf("hammer2_mount: invalid super-root\n");
+                       hammer2_vfs_unmount(mp, MNT_FORCE);
+                       return EINVAL;
+               }
+               hammer2_chain_ref(hmp, schain); /* for hmp->schain */
+               hmp->schain = schain;           /* left locked */
+       } else {
+               schain = hmp->schain;
+               hammer2_chain_lock(hmp, schain, HAMMER2_RESOLVE_ALWAYS);
        }
 
-       hammer2_chain_ref(hmp, schain); /* for hmp->schain */
        parent = schain;
+       lhc = hammer2_dirhash(label, strlen(label));
        rchain = hammer2_chain_lookup(hmp, &parent,
                                      lhc, lhc + HAMMER2_DIRHASH_LOMASK,
                                      0);
@@ -387,18 +437,24 @@ hammer2_vfs_mount(struct mount *mp, char *path, caddr_t data,
        }
        hammer2_chain_unlock(hmp, parent);
        if (rchain == NULL) {
-               kprintf("hammer2_mount: root label not found\n");
-               hammer2_chain_drop(hmp, schain);
+               kprintf("hammer2_mount: PFS label not found\n");
                hammer2_vfs_unmount(mp, MNT_FORCE);
                return EINVAL;
        }
-       hammer2_chain_ref(hmp, rchain); /* for hmp->rchain */
-       hammer2_chain_unlock(hmp, rchain);
+       if (rchain->flags & HAMMER2_CHAIN_MOUNTED) {
+               hammer2_chain_unlock(hmp, rchain);
+               kprintf("hammer2_mount: PFS label already mounted!\n");
+               hammer2_vfs_unmount(mp, MNT_FORCE);
+               return EINVAL;
+       }
+       atomic_set_int(&rchain->flags, HAMMER2_CHAIN_MOUNTED);
 
-       hmp->schain = schain;           /* left held & unlocked */
-       hmp->rchain = rchain;           /* left held & unlocked */
-       hmp->iroot = rchain->u.ip;      /* implied hold from rchain */
-       kprintf("iroot %p\n", rchain->u.ip);
+       hammer2_chain_ref(hmp, rchain); /* for pmp->rchain */
+       hammer2_chain_unlock(hmp, rchain);
+       pmp->rchain = rchain;           /* left held & unlocked */
+       pmp->iroot = rchain->u.ip;      /* implied hold from rchain */
+       pmp->iroot->pmp = pmp;
+       kprintf("iroot %p\n", pmp->iroot);
 
        vfs_getnewfsid(mp);
        vfs_add_vnodeops(mp, &hammer2_vnode_vops, &mp->mnt_vn_norm_ops);
@@ -429,15 +485,15 @@ static
 int
 hammer2_vfs_unmount(struct mount *mp, int mntflags)
 {
+       hammer2_pfsmount_t *pmp;
        hammer2_mount_t *hmp;
        int flags;
        int error = 0;
        int ronly = ((mp->mnt_flag & MNT_RDONLY) != 0);
        struct vnode *devvp;
 
-       kprintf("hammer2_unmount\n");
-
-       hmp = MPTOH2(mp);
+       pmp = MPTOPMP(mp);
+       hmp = pmp->hmp;
        flags = 0;
 
        if (mntflags & MNT_FORCE)
@@ -449,12 +505,16 @@ hammer2_vfs_unmount(struct mount *mp, int mntflags)
         * If mount initialization proceeded far enough we must flush
         * its vnodes.
         */
-       if (hmp->iroot)
+       if (pmp->iroot)
                error = vflush(mp, 0, flags);
 
        if (error)
                return error;
 
+       lockmgr(&hammer2_mntlk, LK_EXCLUSIVE);
+       --hmp->pmp_count;
+       kprintf("hammer2_unmount hmp=%p pmpcnt=%d\n", hmp, hmp->pmp_count);
+
        /*
         * Flush any left over chains.  The voldata lock is only used
         * to synchronize against HAMMER2_CHAIN_MODIFIED_AUX.
@@ -468,50 +528,60 @@ hammer2_vfs_unmount(struct mount *mp, int mntflags)
        } else {
                hammer2_voldata_unlock(hmp);
        }
-       if (hmp->vchain.flags & (HAMMER2_CHAIN_MODIFIED |
-                                HAMMER2_CHAIN_MODIFIED_AUX |
-                                HAMMER2_CHAIN_SUBMODIFIED)) {
-               kprintf("hammer2_unmount: chains left over after final sync\n");
-               if (hammer2_debug & 0x0010)
-                       Debugger("entered debugger");
+       if (hmp->pmp_count == 0) {
+               if (hmp->vchain.flags & (HAMMER2_CHAIN_MODIFIED |
+                                        HAMMER2_CHAIN_MODIFIED_AUX |
+                                        HAMMER2_CHAIN_SUBMODIFIED)) {
+                       kprintf("hammer2_unmount: chains left over after "
+                               "final sync\n");
+                       if (hammer2_debug & 0x0010)
+                               Debugger("entered debugger");
+               }
        }
 
        /*
         * Cleanup the root and super-root chain elements (which should be
         * clean).
         */
-       hmp->iroot = NULL;
-       if (hmp->rchain) {
-               KKASSERT(hmp->rchain->refs == 1);
-               hammer2_chain_drop(hmp, hmp->rchain);
-               hmp->rchain = NULL;
-       }
-       if (hmp->schain) {
-               KKASSERT(hmp->schain->refs == 1);
-               hammer2_chain_drop(hmp, hmp->schain);
-               hmp->schain = NULL;
+       pmp->iroot = NULL;
+       if (pmp->rchain) {
+               atomic_clear_int(&pmp->rchain->flags, HAMMER2_CHAIN_MOUNTED);
+               KKASSERT(pmp->rchain->refs == 1);
+               hammer2_chain_drop(hmp, pmp->rchain);
+               pmp->rchain = NULL;
        }
+       if (hmp->pmp_count == 0) {
+               if (hmp->schain) {
+                       KKASSERT(hmp->schain->refs == 1);
+                       hammer2_chain_drop(hmp, hmp->schain);
+                       hmp->schain = NULL;
+               }
 
-       /*
-        * Finish up with the device vnode
-        */
-       if ((devvp = hmp->devvp) != NULL) {
-               vinvalbuf(devvp, (ronly ? 0 : V_SAVE), 0, 0);
-               hmp->devvp = NULL;
-               VOP_CLOSE(devvp, (ronly ? FREAD : FREAD|FWRITE));
-               vrele(devvp);
-               devvp = NULL;
+               /*
+                * Finish up with the device vnode
+                */
+               if ((devvp = hmp->devvp) != NULL) {
+                       vinvalbuf(devvp, (ronly ? 0 : V_SAVE), 0, 0);
+                       hmp->devvp = NULL;
+                       VOP_CLOSE(devvp, (ronly ? FREAD : FREAD|FWRITE));
+                       vrele(devvp);
+                       devvp = NULL;
+               }
+               kmalloc_destroy(&hmp->minode);
+               kmalloc_destroy(&hmp->mchain);
        }
-
-       kmalloc_destroy(&hmp->minode);
-       kmalloc_destroy(&hmp->mchain);
-
        hammer2_mount_unlock(hmp);
 
+       pmp->mp = NULL;
+       pmp->hmp = NULL;
        mp->mnt_data = NULL;
-       hmp->mp = NULL;
-       kfree(hmp, M_HAMMER2);
 
+       kfree(pmp, M_HAMMER2);
+       if (hmp->pmp_count == 0) {
+               TAILQ_REMOVE(&hammer2_mntlist, hmp, mntentry);
+               kfree(hmp, M_HAMMER2);
+       }
+       lockmgr(&hammer2_mntlk, LK_RELEASE);
        return (error);
 }
 
@@ -528,22 +598,22 @@ static
 int
 hammer2_vfs_root(struct mount *mp, struct vnode **vpp)
 {
-       hammer2_mount_t *hmp;
+       hammer2_pfsmount_t *pmp;
        int error;
        struct vnode *vp;
 
-       hmp = MPTOH2(mp);
-       hammer2_mount_exlock(hmp);
-       if (hmp->iroot == NULL) {
+       pmp = MPTOPMP(mp);
+       hammer2_mount_exlock(pmp->hmp);
+       if (pmp->iroot == NULL) {
                *vpp = NULL;
                error = EINVAL;
        } else {
-               vp = hammer2_igetv(hmp->iroot, &error);
+               vp = hammer2_igetv(pmp->iroot, &error);
                *vpp = vp;
                if (vp == NULL)
                        kprintf("vnodefail\n");
        }
-       hammer2_mount_unlock(hmp);
+       hammer2_mount_unlock(pmp->hmp);
 
        return (error);
 }
@@ -554,7 +624,7 @@ hammer2_vfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
 {
        hammer2_mount_t *hmp;
 
-       hmp = MPTOH2(mp);
+       hmp = MPTOHMP(mp);
 
        mp->mnt_stat.f_files = 10;
        mp->mnt_stat.f_bfree = 10;
@@ -570,7 +640,7 @@ hammer2_vfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred)
 {
        hammer2_mount_t *hmp;
 
-       hmp = MPTOH2(mp);
+       hmp = MPTOHMP(mp);
 
        mp->mnt_vstat.f_bsize = HAMMER2_PBUFSIZE;
        mp->mnt_vstat.f_files = 0;
@@ -606,7 +676,7 @@ hammer2_vfs_sync(struct mount *mp, int waitfor)
        int error;
        int haswork;
 
-       hmp = MPTOH2(mp);
+       hmp = MPTOHMP(mp);
 
        flags = VMSC_GETVP;
        if (waitfor & MNT_LAZY)
index 9b4409e..6f90043 100644 (file)
@@ -205,7 +205,7 @@ static
 int
 hammer2_vop_getattr(struct vop_getattr_args *ap)
 {
-       hammer2_mount_t *hmp;
+       hammer2_pfsmount_t *pmp;
        hammer2_inode_t *ip;
        struct vnode *vp;
        struct vattr *vap;
@@ -214,11 +214,11 @@ hammer2_vop_getattr(struct vop_getattr_args *ap)
        vap = ap->a_vap;
 
        ip = VTOI(vp);
-       hmp = ip->hmp;
+       pmp = ip->pmp;
 
        hammer2_inode_lock_sh(ip);
 
-       vap->va_fsid = hmp->mp->mnt_stat.f_fsid.val[0];
+       vap->va_fsid = pmp->mp->mnt_stat.f_fsid.val[0];
        vap->va_fileid = ip->ip_data.inum;
        vap->va_mode = ip->ip_data.mode;
        vap->va_nlink = ip->ip_data.nlinks;
@@ -388,7 +388,7 @@ hammer2_vop_readdir(struct vop_readdir_args *ap)
                        goto done;
        }
        if (saveoff == 1) {
-               if (ip->pip == NULL || ip == hmp->iroot)
+               if (ip->pip == NULL || ip == ip->pmp->iroot)
                        xip = ip;
                else
                        xip = ip->pip;
@@ -1313,8 +1313,8 @@ hammer2_vop_nmkdir(struct vop_nmkdir_args *ap)
        name = ncp->nc_name;
        name_len = ncp->nc_nlen;
 
-       error = hammer2_inode_create(hmp, ap->a_vap, ap->a_cred,
-                                    dip, name, name_len, &nip);
+       error = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
+                                    name, name_len, &nip);
        if (error) {
                KKASSERT(nip == NULL);
                *ap->a_vpp = NULL;
@@ -1521,8 +1521,8 @@ hammer2_vop_ncreate(struct vop_ncreate_args *ap)
        name = ncp->nc_name;
        name_len = ncp->nc_nlen;
 
-       error = hammer2_inode_create(hmp, ap->a_vap, ap->a_cred,
-                                    dip, name, name_len, &nip);
+       error = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
+                                    name, name_len, &nip);
        if (error) {
                KKASSERT(nip == NULL);
                *ap->a_vpp = NULL;
@@ -1564,8 +1564,8 @@ hammer2_vop_nsymlink(struct vop_nsymlink_args *ap)
 
        ap->a_vap->va_type = VLNK;      /* enforce type */
 
-       error = hammer2_inode_create(hmp, ap->a_vap, ap->a_cred,
-                                    dip, name, name_len, &nip);
+       error = hammer2_inode_create(dip, ap->a_vap, ap->a_cred,
+                                    name, name_len, &nip);
        if (error) {
                KKASSERT(nip == NULL);
                *ap->a_vpp = NULL;
@@ -1970,18 +1970,18 @@ int
 hammer2_vop_mountctl(struct vop_mountctl_args *ap)
 {
        struct mount *mp;
-       struct hammer2_mount *hmp;
+       hammer2_pfsmount_t *pmp;
        int rc;
 
        switch (ap->a_op) {
        case (MOUNTCTL_SET_EXPORT):
                mp = ap->a_head.a_ops->head.vv_mount;
-               hmp = MPTOH2(mp);
+               pmp = MPTOPMP(mp);
 
                if (ap->a_ctllen != sizeof(struct export_args))
                        rc = (EINVAL);
                else
-                       rc = vfs_export(mp, &hmp->export,
+                       rc = vfs_export(mp, &pmp->export,
                                        (const struct export_args *)ap->a_ctl);
                break;
        default: