use rb-tree for directory lookups
[dragonfly.git] / sys / vfs / tmpfs / tmpfs_vfsops.c
index f5af54f..de23cb7 100644 (file)
@@ -186,14 +186,21 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
 
        pages_limit = vm_swap_max + vmstats.v_page_count / 2;
 
-       if (size_max == 0)
+       if (size_max == 0) {
                pages = pages_limit / 2;
-       else if (size_max < PAGE_SIZE)
+       } else if (size_max < PAGE_SIZE) {
                pages = 1;
-       else if (OFF_TO_IDX(size_max) > pages_limit)
-               pages = pages_limit;
-       else
+       } else if (OFF_TO_IDX(size_max) > pages_limit) {
+               /*
+                * do not force pages = pages_limit for this case, otherwise
+                * we might not honor tmpfs size requests from /etc/fstab
+                * during boot because they are mounted prior to swap being
+                * turned on.
+                */
+               pages = OFF_TO_IDX(size_max);
+       } else {
                pages = OFF_TO_IDX(size_max);
+       }
 
        if (nodes_max == 0)
                nodes = 3 + pages * PAGE_SIZE / 1024;
@@ -244,6 +251,8 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
            tmpfs_node_init, tmpfs_node_fini,
            &tmp->tm_node_zone_malloc_args);
 
+       tmp->tm_ino = 2;
+
        /* Allocate the root node. */
        error = tmpfs_alloc_node(tmp, VDIR, root_uid, root_gid,
                                 root_mode & ALLPERMS, NULL, NULL,
@@ -269,7 +278,8 @@ tmpfs_mount(struct mount *mp, char *path, caddr_t data, struct ucred *cred)
        mp->mnt_kern_flag |= MNTK_RD_MPSAFE | MNTK_WR_MPSAFE | MNTK_GA_MPSAFE  |
                             MNTK_IN_MPSAFE | MNTK_SG_MPSAFE;
 #endif
-       mp->mnt_kern_flag |= MNTK_RD_MPSAFE | MNTK_SG_MPSAFE;
+       mp->mnt_kern_flag |= MNTK_RD_MPSAFE | MNTK_GA_MPSAFE | MNTK_SG_MPSAFE;
+       mp->mnt_kern_flag |= MNTK_WR_MPSAFE;
        mp->mnt_kern_flag |= MNTK_NOMSYNC;
        mp->mnt_data = (qaddr_t)tmp;
        vfs_getnewfsid(mp);
@@ -341,8 +351,8 @@ tmpfs_unmount(struct mount *mp, int mntflags)
                if (node->tn_type == VDIR) {
                        struct tmpfs_dirent *de;
 
-                       while (!TAILQ_EMPTY(&node->tn_dir.tn_dirhead)) {
-                               de = TAILQ_FIRST(&node->tn_dir.tn_dirhead);
+                       while (!RB_EMPTY(&node->tn_dir.tn_dirtree)) {
+                               de = RB_FIRST(tmpfs_dirtree, &node->tn_dir.tn_dirtree);
                                tmpfs_dir_detach(node, de);
                                tmpfs_free_dirent(tmp, de);
                                node->tn_size -= sizeof(struct tmpfs_dirent);
@@ -499,8 +509,44 @@ tmpfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred)
        return 0;
 }
 
+/* --------------------------------------------------------------------- */ 
+
+static int
+tmpfs_vptofh(struct vnode *vp, struct fid *fhp)
+{
+       struct tmpfs_node *node;
+       struct tmpfs_fid tfh;
+       node = VP_TO_TMPFS_NODE(vp);
+       memset(&tfh, 0, sizeof(tfh));
+       tfh.tf_len = sizeof(struct tmpfs_fid);
+       tfh.tf_gen = node->tn_gen;
+       tfh.tf_id = node->tn_id;
+       memcpy(fhp, &tfh, sizeof(tfh));
+       return (0);
+}
+
 /* --------------------------------------------------------------------- */
 
+static int 
+tmpfs_checkexp(struct mount *mp, struct sockaddr *nam, int *exflagsp, 
+              struct ucred **credanonp) 
+{ 
+       struct tmpfs_mount *tmp; 
+       struct netcred *nc; 
+       tmp = (struct tmpfs_mount *) mp->mnt_data;
+       nc = vfs_export_lookup(mp, &tmp->tm_export, nam); 
+       if (nc == NULL) 
+               return (EACCES); 
+
+       *exflagsp = nc->netc_exflags; 
+       *credanonp = &nc->netc_anon; 
+       return (0); 
+} 
+
+/* --------------------------------------------------------------------- */ 
+
 /*
  * tmpfs vfs operations.
  */
@@ -511,7 +557,10 @@ static struct vfsops tmpfs_vfsops = {
        .vfs_root =                     tmpfs_root,
        .vfs_statfs =                   tmpfs_statfs,
        .vfs_fhtovp =                   tmpfs_fhtovp,
-       .vfs_sync =                     vfs_stdsync
+       .vfs_vptofh =                   tmpfs_vptofh, 
+       .vfs_sync =                     vfs_stdsync,
+       .vfs_checkexp =                 tmpfs_checkexp,
 };
 
 VFS_SET(tmpfs_vfsops, tmpfs, 0);
+MODULE_VERSION(tmpfs, 1);