dirfs WIP wip2
authorAntonio Huete Jimenez <tuxillo@quantumachine.net>
Fri, 21 Mar 2014 07:40:44 +0000 (00:40 -0700)
committerAntonio Huete Jimenez <tuxillo@quantumachine.net>
Fri, 21 Mar 2014 07:40:44 +0000 (00:40 -0700)
sys/vfs/dirfs/dirfs.h
sys/vfs/dirfs/dirfs_subr.c
sys/vfs/dirfs/dirfs_vfsops.c
sys/vfs/dirfs/dirfs_vnops.c

index e0d900d..4af2986 100644 (file)
@@ -54,12 +54,12 @@ MALLOC_DECLARE(M_DIRFS_MISC);
 #define DIRFS_NOFD     -1      /* No fd present */
 
 #define DIRFS_ROOT     0x00000001
-#define DIRFS_PASVFD   0x00000002
+#define DIRFS_DOOMED   0x00000002
 #define DIRFS_NODE_RD  0x00000004
 #define DIRFS_NODE_WR  0x00000008
 #define DIRFS_NODE_EXE 0x00000010
 
-#define DIRFS_TXTFLG "pasvfd"
+#define DIRFS_TXTFLG "doomed"
 
 /* Used for buffer cache operations */
 #define BSIZE  16384
@@ -117,6 +117,7 @@ extern int statfs(const char *, struct statfs *);
  * Misc macros
  */
 #define dirfs_node_isroot(n)   (n->dn_state & DIRFS_ROOT)
+#define dirfs_node_hasfd(n)    (n->dn_fd != DIRFS_NOFD)
 
 /*
  * Main in-memory node structure which will represent a host file when active.
@@ -129,7 +130,6 @@ struct dirfs_node {
 
        int                     dn_state;       /* Node state flags */
 
-       TAILQ_ENTRY(dirfs_node) dn_fdentry;     /* Passive fd cache */
        RB_ENTRY(dirfs_node)    dn_rbentry;     /* Inode no. lookup */
 
        int                     dn_refcnt;      /* Refs from children */
@@ -172,7 +172,6 @@ typedef struct dirfs_node *dirfs_node_t;
  */
 struct dirfs_mount {
        RB_HEAD(, dn_rbentry) dm_inotree;
-       TAILQ_HEAD(, dirfs_node) dm_fdlist;
 
        struct lock             dm_lock;
        struct lwkt_token       dm_token;
@@ -201,8 +200,6 @@ typedef struct dirfs_mount *dirfs_mount_t;
 extern int debuglvl;
 extern int dirfs_fd_limit;
 extern int dirfs_fd_used;
-extern long passive_fd_list_miss;
-extern long passive_fd_list_hits;
 
 extern struct vop_ops dirfs_vnode_vops;
 
@@ -212,17 +209,26 @@ extern struct vop_ops dirfs_vnode_vops;
 static __inline void
 dirfs_node_ref(dirfs_node_t dnp)
 {
+       lockmgr(&dnp->dn_lock, LK_EXCLUSIVE);
        atomic_add_int(&dnp->dn_refcnt, 1);
+       lockmgr(&dnp->dn_lock, LK_RELEASE);
 }
 
 static __inline int
 dirfs_node_unref(dirfs_node_t dnp)
 {
+       int ret = 0;
+
        /*
         * Returns non-zero on last unref.
         */
        KKASSERT(dnp->dn_refcnt > 0);
-       return (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1);
+
+       lockmgr(&dnp->dn_lock, LK_EXCLUSIVE);
+       ret = (atomic_fetchadd_int(&dnp->dn_refcnt, -1) == 1);
+       lockmgr(&dnp->dn_lock, LK_RELEASE);
+
+       return ret;
 }
 
 static __inline void
@@ -248,9 +254,8 @@ void dirfs_node_setname(dirfs_node_t, const char *, int);
 char *dirfs_node_fullpath(dirfs_mount_t, const char *);
 int dirfs_node_free(dirfs_mount_t, dirfs_node_t);
 void dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp);
-void dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state);
 void dirfs_alloc_vp(struct mount *, struct vnode **, int, dirfs_node_t);
-void dirfs_free_vp(dirfs_mount_t, dirfs_node_t);
+void dirfs_free_vp(dirfs_node_t);
 int dirfs_alloc_file(dirfs_mount_t, dirfs_node_t *, dirfs_node_t,
     struct namecache *, struct vnode **, struct vattr *, int);
 dirfs_node_t dirfs_findfd(dirfs_mount_t dmp, dirfs_node_t cur,
index 020ae78..7a92af3 100644 (file)
@@ -85,9 +85,6 @@ dirfs_node_alloc(struct mount *mp)
         return dnp;
 }
 
-/*
- * Drops a reference to the node and. Node is freed when in the last reference.
- */
 void
 dirfs_node_drop(dirfs_mount_t dmp, dirfs_node_t dnp)
 {
@@ -110,8 +107,6 @@ dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
        KKASSERT(dnp != NULL);
        debug_node2(dnp);
 
-       KKASSERT(dirfs_node_refcnt(dnp) == 0);
-
        vp = NODE_TO_VP(dnp);
        /*
         * Remove the inode from the passive fds list
@@ -120,16 +115,17 @@ dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
         */
        dirfs_mount_gettoken(dmp);
 
-       if (dnp->dn_parent) {   /* NULL when children reaped parents */
+       if (dnp->dn_parent) {
                dirfs_node_drop(dmp, dnp->dn_parent);
                dnp->dn_parent = NULL;
        }
-       dirfs_node_setpassive(dmp, dnp, 0);
        if (dnp->dn_name) {
                kfree(dnp->dn_name, M_DIRFS_MISC);
                dnp->dn_name = NULL;
        }
 
+       close(dnp->dn_fd);
+
        /*
         * The file descriptor should have been closed already by the
         * previous call to dirfs_set-passive. If not, force a sync and
@@ -141,8 +137,8 @@ dirfs_node_free(dirfs_mount_t dmp, dirfs_node_t dnp)
                close(dnp->dn_fd);
                dnp->dn_fd = DIRFS_NOFD;
        }
-
        lockuninit(&dnp->dn_lock);
+
        kfree(dnp, M_DIRFS_NODE);
        dnp = NULL;
 
@@ -205,7 +201,7 @@ dirfs_alloc_file(dirfs_mount_t dmp, dirfs_node_t *dnpp, dirfs_node_t pdnp,
        if (error) {            /* XXX Handle errors */
                error = errno;
                if (vp)
-                       dirfs_free_vp(dmp, dnp);
+                       dirfs_free_vp(dnp);
                dirfs_node_free(dmp, dnp);
                dirfs_dropfd(dmp, pathnp, pathfree);
                return error;
@@ -251,7 +247,7 @@ dirfs_alloc_vp(struct mount *mp, struct vnode **vpp, int lkflags,
                                vp->v_type = dnp->dn_type;
                                if (dmp->dm_root == dnp)
                                        vsetflags(vp, VROOT);
-                               dirfs_node_ref(dnp);    /* ref for dnp<->vp */
+//                             dirfs_node_ref(dnp);    /* ref for dnp<->vp */
 
                                /* Type-specific initialization. */
                                switch (dnp->dn_type) {
@@ -292,13 +288,12 @@ dirfs_alloc_vp(struct mount *mp, struct vnode **vpp, int lkflags,
  * Do not call locked!
  */
 void
-dirfs_free_vp(dirfs_mount_t dmp, dirfs_node_t dnp)
+dirfs_free_vp(dirfs_node_t dnp)
 {
-       struct vnode *vp = NODE_TO_VP(dnp);
+//     struct vnode *vp = NODE_TO_VP(dnp);
 
-       dnp->dn_vnode = NULL;
-       vp->v_data = NULL;
-       dirfs_node_drop(dmp, dnp);
+//     vp->v_data = NULL;
+//     dnp->dn_vnode = NULL;
 }
 
 int
@@ -801,72 +796,6 @@ dirfs_node_chsize(dirfs_node_t dnp, off_t nsize)
        return error;
 }
 
-void
-dirfs_node_setpassive(dirfs_mount_t dmp, dirfs_node_t dnp, int state)
-{
-       struct vnode *vp;
-
-       if (state && (dnp->dn_state & DIRFS_PASVFD) == 0 &&
-           dnp->dn_fd != DIRFS_NOFD) {
-               dirfs_node_ref(dnp);
-               dirfs_node_setflags(dnp, DIRFS_PASVFD);
-               TAILQ_INSERT_TAIL(&dmp->dm_fdlist, dnp, dn_fdentry);
-               ++dirfs_fd_used;
-               ++dmp->dm_fd_used;
-
-               /*
-                * If we are over our limit remove nodes from the
-                * passive fd cache.
-                */
-               while (dmp->dm_fd_used > dirfs_fd_limit) {
-                       dnp = TAILQ_FIRST(&dmp->dm_fdlist);
-                       dirfs_node_setpassive(dmp, dnp, 0);
-               }
-       }
-       if (state == 0 && (dnp->dn_state & DIRFS_PASVFD)) {
-               dirfs_node_clrflags(dnp, DIRFS_PASVFD);
-               TAILQ_REMOVE(&dmp->dm_fdlist, dnp, dn_fdentry);
-               --dirfs_fd_used;
-               --dmp->dm_fd_used;
-               dbg(5, "dnp=%p removed from fdlist. %d used\n",
-                   dnp, dirfs_fd_used);
-
-               /*
-                * Attempt to close the descriptor.  We can only do this
-                * if the related vnode is inactive and has exactly two
-                * refs (representing the vp<->dnp and PASVFD).  Otherwise
-                * someone might have ref'd the node in order to use the
-                * dn_fd.
-                *
-                * Also, if the vnode is in any way dirty we leave the fd
-                * open for the buffer cache code.  The syncer will eventually
-                * come along and fsync the vnode, and the next inactive
-                * transition will deal with the descriptor.
-                *
-                * The descriptor for the root node is NEVER closed by
-                * this function.
-                */
-               vp = dnp->dn_vnode;
-               if (dirfs_node_refcnt(dnp) == 2 && vp &&
-                   dnp->dn_fd != DIRFS_NOFD &&
-                   !dirfs_node_isroot(dnp) &&
-                   (vp->v_flag & (VINACTIVE|VOBJDIRTY)) == VINACTIVE &&
-                   RB_EMPTY(&vp->v_rbdirty_tree)) {
-                       dbg(5, "passive cache: closing %d\n", dnp->dn_fd);
-                       close(dnp->dn_fd);
-                       dnp->dn_fd = DIRFS_NOFD;
-               } else {
-                       if (dirfs_node_refcnt(dnp) == 1 && dnp->dn_vnode == NULL &&
-                           dnp->dn_fd != DIRFS_NOFD &&
-                           dnp != dmp->dm_root) {
-                               dbg(5, "passive cache: closing %d\n", dnp->dn_fd);
-                               close(dnp->dn_fd);
-                               dnp->dn_fd = DIRFS_NOFD;
-                       }
-               }
-               dirfs_node_drop(dmp, dnp);
-       }
-}
 
 char *
 dirfs_flag2str(dirfs_node_t dnp)
@@ -874,7 +803,7 @@ dirfs_flag2str(dirfs_node_t dnp)
        const char *txtflg[] = { DIRFS_TXTFLG };
        static char str[512] = {0};
 
-       if (dnp->dn_state & DIRFS_PASVFD)
+       if (dnp->dn_state & DIRFS_DOOMED)
                ksprintf(str, "%s ", txtflg[0]);
 
        return str;
@@ -891,4 +820,3 @@ debug(int level, const char *fmt, ...)
                __va_end(ap);
        }
 }
-
index afdf19a..2e849ab 100644 (file)
@@ -77,8 +77,6 @@ KTR_INFO(KTR_DIRFS, dirfs, unmount, 22,
 int debuglvl = 0;
 int dirfs_fd_limit = 100;
 int dirfs_fd_used = 0;
-long passive_fd_list_miss = 0;
-long passive_fd_list_hits = 0;
 
 SYSCTL_NODE(_vfs, OID_AUTO, dirfs, CTLFLAG_RW, 0,
     "dirfs filesystem for vkernels");
@@ -88,10 +86,6 @@ SYSCTL_INT(_vfs_dirfs, OID_AUTO, fd_limit, CTLFLAG_RW,
     &dirfs_fd_limit, 0, "Maximum number of passive nodes to cache");
 SYSCTL_INT(_vfs_dirfs, OID_AUTO, fd_used, CTLFLAG_RD,
     &dirfs_fd_used, 0, "Current number of passive nodes cached");
-SYSCTL_LONG(_vfs_dirfs, OID_AUTO, passive_fd_list_miss, CTLFLAG_RD,
-    &passive_fd_list_miss, 0, "Passive fd list cache misses");
-SYSCTL_LONG(_vfs_dirfs, OID_AUTO, passive_fd_list_hits, CTLFLAG_RD,
-    &passive_fd_list_hits, 0, "Passive fd list cache misses");
 
 static int dirfs_statfs(struct mount *, struct statfs *, struct ucred *);
 
@@ -160,7 +154,6 @@ dirfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        dmp->dm_uid = getuid();
        dmp->dm_gid = getgid();
 
-       TAILQ_INIT(&dmp->dm_fdlist);
        RB_INIT(&dmp->dm_inotree);
 
        kmalloc_raise_limit(M_DIRFS_NODE, 0);
@@ -191,14 +184,6 @@ dirfs_unmount(struct mount *mp, int mntflags)
                goto failure;
 
        /*
-        * Clean up dm_fdlist.  There should be no vnodes left so the
-        * only ref should be from the fdlist.
-        */
-       while ((dnp = TAILQ_FIRST(&dmp->dm_fdlist)) != NULL) {
-               dirfs_node_setpassive(dmp, dnp, 0);
-       }
-
-       /*
         * Cleanup root node. In the case the filesystem is mounted
         * but no operation is done on it, there will be no call to
         * VFS_ROOT() so better check dnp is not NULL before attempting
@@ -259,7 +244,7 @@ dirfs_root(struct mount *mp, struct vnode **vpp)
                fd = open(dmp->dm_path, O_DIRECTORY);
                if (fd == -1) {
                        dbg(5, "failed to open ROOT node\n");
-                       dirfs_free_vp(dmp, dnp);
+                       dirfs_free_vp(dnp);
                        dirfs_node_free(dmp, dnp);
                        return errno;
                }
index df08540..d2696b8 100644 (file)
@@ -196,25 +196,7 @@ dirfs_nresolve(struct vop_nresolve_args *ap)
        pdnp = VP_TO_NODE(dvp);
        dmp = VFS_TO_DIRFS(mp);
 
-       dirfs_node_lock(pdnp);
-       TAILQ_FOREACH_MUTABLE(d1, &dmp->dm_fdlist, dn_fdentry, d2) {
-               if (d1->dn_parent == pdnp &&
-                   (strcmp(d1->dn_name, ncp->nc_name) == 0)) {
-                       dnp = d1;
-                       dirfs_node_ref(dnp);
-                       passive_fd_list_hits++;
-                       break;
-               }
-       }
-       dirfs_node_unlock(pdnp);
-
-       if (dnp) {
-               dirfs_alloc_vp(mp, &vp, LK_CANRECURSE, dnp);
-               dirfs_node_drop(dmp, dnp);
-       } else {
-               passive_fd_list_miss++;
-               error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, &vp, NULL, 0);
-       }
+       error = dirfs_alloc_file(dmp, &dnp, pdnp, ncp, &vp, NULL, 0);
 
        if (vp) {
                if (error && error == ENOENT) {
@@ -310,11 +292,11 @@ dirfs_open(struct vop_open_args *ap)
        error = 0;
 
        /*
-        * Root inode has been allocated and opened in VFS_ROOT() so
-        * no reason to attempt to open it again.
         */
-       if (dmp->dm_root != dnp && dnp->dn_fd == DIRFS_NOFD) {
-               error = dirfs_open_helper(dmp, dnp, DIRFS_NOFD, NULL);
+       if (!dirfs_node_isroot(dnp)) {
+               if (!dirfs_node_hasfd(dnp))
+                       error = dirfs_open_helper(dmp, dnp, DIRFS_NOFD, NULL);
+
                if (error)
                        return error;
        }
@@ -327,6 +309,7 @@ dirfs_open(struct vop_open_args *ap)
 static int
 dirfs_close(struct vop_close_args *ap)
 {
+       dirfs_mount_t dmp;
        struct vnode *vp;
        dirfs_node_t dnp;
        int error;
@@ -335,6 +318,7 @@ dirfs_close(struct vop_close_args *ap)
 
        error = 0;
        vp = ap->a_vp;
+       dmp = VFS_TO_DIRFS(vp->v_mount);
        dnp = VP_TO_NODE(vp);
 
        if (vp->v_type == VREG) {
@@ -342,19 +326,16 @@ dirfs_close(struct vop_close_args *ap)
                if (error)
                        dbg(5, "vfsync error=%d\n", error);
        }
-       vop_stdclose(ap);
 
-       /*
-        * XXX - Currently VOP_INACTIVE() is not being called unless there is
-        * vnode pressure so, by now, call inactive directly on last close.
-        */
-       vn_lock(vp, LK_UPGRADE | LK_RETRY);
-       if (vp->v_opencount == 0 && vp->v_writecount == 0)
-               VOP_INACTIVE(vp);
+       if (!dirfs_node_isroot(dnp) && vp->v_opencount == 1) {
+               dirfs_node_setflags(dnp, DIRFS_DOOMED);
+       }
 
        KTR_LOG(dirfs_close, dnp, dnp->dn_fd, vp->v_opencount,
            vp->v_writecount, error);
 
+       vop_stdclose(ap);
+
        return 0;
 }
 
@@ -932,7 +913,6 @@ dirfs_nremove(struct vop_nremove_args *ap)
                error = unlinkat(pathnp->dn_fd, tmp, 0);
                if (error == 0) {
                        cache_unlink(nch);
-                       dirfs_node_setpassive(dmp, dnp, 0);
                        if (dnp->dn_parent) {
                                dirfs_node_drop(dmp, dnp->dn_parent);
                                dnp->dn_parent = NULL;
@@ -1016,7 +996,6 @@ dirfs_nrename(struct vop_nrename_args *ap)
                        dbg(5, "RENAME2\n");
                        dnp = VP_TO_NODE(vp);
                        cache_unlink(ap->a_tnch);
-                       dirfs_node_setpassive(dmp, dnp, 0);
                        if (dnp->dn_parent) {
                                dirfs_node_drop(dmp, dnp->dn_parent);
                                dnp->dn_parent = NULL;
@@ -1139,7 +1118,6 @@ dirfs_nrmdir(struct vop_nrmdir_args *ap)
                error = rmdir(tmp);
                if (error == 0) {
                        cache_unlink(nch);
-                       dirfs_node_setpassive(dmp, dnp, 0);
                        if (dnp->dn_parent) {
                                dirfs_node_drop(dmp, dnp->dn_parent);
                                dnp->dn_parent = NULL;
@@ -1377,7 +1355,7 @@ dirfs_inactive(struct vop_inactive_args *ap)
        dirfs_node_t dnp;
 
        debug_called();
-
+       kprintf("Called VOP_INACTIVE()\n");
        vp = ap->a_vp;
        dmp = VFS_TO_DIRFS(vp->v_mount);
        dnp = VP_TO_NODE(vp);
@@ -1389,7 +1367,8 @@ dirfs_inactive(struct vop_inactive_args *ap)
                return 0;
        }
 
-       dirfs_mount_gettoken(dmp);
+       if (dirfs_node_refcnt(dnp) == 0)
+               dirfs_node_free(dmp,dnp);
 
        /*
         * Deal with the case the inode has 0 links which means it was unlinked.
@@ -1401,12 +1380,7 @@ dirfs_inactive(struct vop_inactive_args *ap)
                goto out;
        }
 
-       /*
-        * Try to retain the fd in our fd cache.
-        */
-       dirfs_node_setpassive(dmp, dnp, 1);
 out:
-       dirfs_mount_reltoken(dmp);
 
        return 0;
 
@@ -1425,9 +1399,10 @@ dirfs_reclaim(struct vop_reclaim_args *ap)
        dnp = VP_TO_NODE(vp);
        dmp = VFS_TO_DIRFS(vp->v_mount);
 
-       dirfs_free_vp(dmp, dnp);
+//     dirfs_free_vp(dnp);
+       vp->v_data = NULL;
        /* dnp is now invalid, may have been destroyed */
-
+       dbg(5, "ending reclaim\n");
        return 0;
 }