[BACK]Return to tmpfs_vfsops.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / fs / tmpfs

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/fs/tmpfs/tmpfs_vfsops.c between version 1.46 and 1.46.2.1

version 1.46, 2010/06/26 03:38:14 version 1.46.2.1, 2011/06/06 09:09:24
Line 51  __KERNEL_RCSID(0, "$NetBSD$");
Line 51  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/stat.h>  #include <sys/stat.h>
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/vnode.h>  #include <sys/vnode.h>
 #include <sys/proc.h>  
 #include <sys/module.h>  #include <sys/module.h>
   
 #include <miscfs/genfs/genfs.h>  #include <miscfs/genfs/genfs.h>
Line 60  __KERNEL_RCSID(0, "$NetBSD$");
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
   
 MODULE(MODULE_CLASS_VFS, tmpfs, NULL);  MODULE(MODULE_CLASS_VFS, tmpfs, NULL);
   
 /* --------------------------------------------------------------------- */  struct pool     tmpfs_dirent_pool;
   struct pool     tmpfs_node_pool;
   
 static int      tmpfs_mount(struct mount *, const char *, void *, size_t *);  static int      tmpfs_mount(struct mount *, const char *, void *, size_t *);
 static int      tmpfs_start(struct mount *, int);  static int      tmpfs_start(struct mount *, int);
 static int      tmpfs_unmount(struct mount *, int);  static int      tmpfs_unmount(struct mount *, int);
 static int      tmpfs_root(struct mount *, struct vnode **);  static int      tmpfs_root(struct mount *, vnode_t **);
 static int      tmpfs_vget(struct mount *, ino_t, struct vnode **);  static int      tmpfs_vget(struct mount *, ino_t, vnode_t **);
 static int      tmpfs_fhtovp(struct mount *, struct fid *, struct vnode **);  static int      tmpfs_fhtovp(struct mount *, struct fid *, vnode_t **);
 static int      tmpfs_vptofh(struct vnode *, struct fid *, size_t *);  static int      tmpfs_vptofh(struct vnode *, struct fid *, size_t *);
 static int      tmpfs_statvfs(struct mount *, struct statvfs *);  static int      tmpfs_statvfs(struct mount *, struct statvfs *);
 static int      tmpfs_sync(struct mount *, int, kauth_cred_t);  static int      tmpfs_sync(struct mount *, int, kauth_cred_t);
 static void     tmpfs_init(void);  static void     tmpfs_init(void);
 static void     tmpfs_done(void);  static void     tmpfs_done(void);
 static int      tmpfs_snapshot(struct mount *, struct vnode *,  static int      tmpfs_snapshot(struct mount *, vnode_t *, struct timespec *);
                     struct timespec *);  
   
 /* --------------------------------------------------------------------- */  static void
   tmpfs_init(void)
   {
   
           pool_init(&tmpfs_dirent_pool, sizeof(tmpfs_dirent_t), 0, 0, 0,
               "tmpfs_dirent", &pool_allocator_nointr, IPL_NONE);
           pool_init(&tmpfs_node_pool, sizeof(tmpfs_node_t), 0, 0, 0,
               "tmpfs_node", &pool_allocator_nointr, IPL_NONE);
   }
   
   static void
   tmpfs_done(void)
   {
   
           pool_destroy(&tmpfs_dirent_pool);
           pool_destroy(&tmpfs_node_pool);
   }
   
 static int  static int
 tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)  tmpfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len)
 {  {
         struct tmpfs_mount *tmp;  
         struct tmpfs_node *root;  
         struct tmpfs_args *args = data;          struct tmpfs_args *args = data;
           tmpfs_mount_t *tmp;
           tmpfs_node_t *root;
         uint64_t memlimit;          uint64_t memlimit;
         ino_t nodes;          ino_t nodes;
         int error;          int error;
   
         if (*data_len < sizeof *args)          /* Validate the version. */
           if (*data_len < sizeof(*args) ||
               args->ta_version != TMPFS_ARGS_VERSION)
                 return EINVAL;                  return EINVAL;
   
         /* Handle retrieval of mount point arguments. */          /* Handle retrieval of mount point arguments. */
Line 111  tmpfs_mount(struct mount *mp, const char
Line 128  tmpfs_mount(struct mount *mp, const char
         }          }
   
         if (mp->mnt_flag & MNT_UPDATE) {          if (mp->mnt_flag & MNT_UPDATE) {
                 /* XXX: There is no support yet to update file system                  /* TODO */
                  * settings.  Should be added. */  
   
                 return EOPNOTSUPP;                  return EOPNOTSUPP;
         }          }
   
         if (args->ta_version != TMPFS_ARGS_VERSION)          /* Prohibit mounts if there is not enough memory. */
                 return EINVAL;  
   
         /* Do not allow mounts if we do not have enough memory to preserve  
          * the minimum reserved pages. */  
         if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED)          if (tmpfs_mem_info(true) < TMPFS_PAGES_RESERVED)
                 return EINVAL;                  return EINVAL;
   
Line 142  tmpfs_mount(struct mount *mp, const char
Line 153  tmpfs_mount(struct mount *mp, const char
         KASSERT(nodes >= 3);          KASSERT(nodes >= 3);
   
         /* Allocate the tmpfs mount structure and fill it. */          /* Allocate the tmpfs mount structure and fill it. */
         tmp = kmem_alloc(sizeof(struct tmpfs_mount), KM_SLEEP);          tmp = kmem_zalloc(sizeof(tmpfs_mount_t), KM_SLEEP);
         if (tmp == NULL)          if (tmp == NULL)
                 return ENOMEM;                  return ENOMEM;
   
Line 155  tmpfs_mount(struct mount *mp, const char
Line 166  tmpfs_mount(struct mount *mp, const char
   
         /* Allocate the root node. */          /* Allocate the root node. */
         error = tmpfs_alloc_node(tmp, VDIR, args->ta_root_uid,          error = tmpfs_alloc_node(tmp, VDIR, args->ta_root_uid,
             args->ta_root_gid, args->ta_root_mode & ALLPERMS, NULL, NULL,              args->ta_root_gid, args->ta_root_mode & ALLPERMS, NULL,
             VNOVAL, &root);              VNOVAL, &root);
         KASSERT(error == 0 && root != NULL);          KASSERT(error == 0 && root != NULL);
   
           /*
            * Parent of the root inode is itself.  Also, root inode has no
            * directory entry (i.e. is never attached), thus hold an extra
            * reference (link) for it.
            */
         root->tn_links++;          root->tn_links++;
           root->tn_spec.tn_dir.tn_parent = root;
         tmp->tm_root = root;          tmp->tm_root = root;
   
         mp->mnt_data = tmp;          mp->mnt_data = tmp;
Line 169  tmpfs_mount(struct mount *mp, const char
Line 187  tmpfs_mount(struct mount *mp, const char
         mp->mnt_iflag |= IMNT_MPSAFE;          mp->mnt_iflag |= IMNT_MPSAFE;
         vfs_getnewfsid(mp);          vfs_getnewfsid(mp);
   
         return set_statvfs_info(path, UIO_USERSPACE, "tmpfs", UIO_SYSSPACE,          error = set_statvfs_info(path, UIO_USERSPACE, "tmpfs", UIO_SYSSPACE,
             mp->mnt_op->vfs_name, mp, curlwp);              mp->mnt_op->vfs_name, mp, curlwp);
           if (error) {
                   (void)tmpfs_unmount(mp, MNT_FORCE);
           }
           return error;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_start(struct mount *mp, int flags)  tmpfs_start(struct mount *mp, int flags)
 {  {
Line 182  tmpfs_start(struct mount *mp, int flags)
Line 202  tmpfs_start(struct mount *mp, int flags)
         return 0;          return 0;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 /* ARGSUSED2 */  
 static int  static int
 tmpfs_unmount(struct mount *mp, int mntflags)  tmpfs_unmount(struct mount *mp, int mntflags)
 {  {
         int error;          tmpfs_mount_t *tmp;
         int flags = 0;          tmpfs_node_t *node;
         struct tmpfs_mount *tmp;          int error, flags = 0;
         struct tmpfs_node *node;  
   
         /* Handle forced unmounts. */          /* Handle forced unmounts. */
         if (mntflags & MNT_FORCE)          if (mntflags & MNT_FORCE)
Line 204  tmpfs_unmount(struct mount *mp, int mntf
Line 220  tmpfs_unmount(struct mount *mp, int mntf
   
         tmp = VFS_TO_TMPFS(mp);          tmp = VFS_TO_TMPFS(mp);
   
         /* Free all associated data.  The loop iterates over the linked list          /* Destroy any existing inodes. */
          * we have containing all used nodes.  For each of them that is          while ((node = LIST_FIRST(&tmp->tm_nodes)) != NULL) {
          * a directory, we free all its directory entries.  Note that after  
          * freeing a node, it will automatically go to the available list,  
          * so we will later have to iterate over it to release its items. */  
         node = LIST_FIRST(&tmp->tm_nodes);  
         while (node != NULL) {  
                 struct tmpfs_node *next;  
   
                 if (node->tn_type == VDIR) {                  if (node->tn_type == VDIR) {
                         struct tmpfs_dirent *de;                          tmpfs_dirent_t *de;
   
                           /* Destroy any directory entries. */
                         de = TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir);                          de = TAILQ_FIRST(&node->tn_spec.tn_dir.tn_dir);
                         while (de != NULL) {                          while (de != NULL) {
                                 struct tmpfs_dirent *nde;                                  tmpfs_dirent_t *nde;
   
                                 nde = TAILQ_NEXT(de, td_entries);                                  nde = TAILQ_NEXT(de, td_entries);
                                 tmpfs_free_dirent(tmp, de, false);                                  tmpfs_free_dirent(tmp, de);
                                   node->tn_size -= sizeof(tmpfs_dirent_t);
                                 de = nde;                                  de = nde;
                                 node->tn_size -= sizeof(struct tmpfs_dirent);  
                         }                          }
                 }                  }
                   /* Removes inode from the list. */
                 next = LIST_NEXT(node, tn_entries);  
                 tmpfs_free_node(tmp, node);                  tmpfs_free_node(tmp, node);
                 node = next;  
         }          }
   
         /* Throw away the tmpfs_mount structure. */          /* Throw away the tmpfs_mount structure. */
Line 241  tmpfs_unmount(struct mount *mp, int mntf
Line 249  tmpfs_unmount(struct mount *mp, int mntf
         return 0;          return 0;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_root(struct mount *mp, struct vnode **vpp)  tmpfs_root(struct mount *mp, vnode_t **vpp)
 {  {
           tmpfs_node_t *node = VFS_TO_TMPFS(mp)->tm_root;
   
         return tmpfs_alloc_vp(mp, VFS_TO_TMPFS(mp)->tm_root, vpp);          mutex_enter(&node->tn_vlock);
           return tmpfs_vnode_get(mp, node, vpp);
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_vget(struct mount *mp, ino_t ino,  tmpfs_vget(struct mount *mp, ino_t ino, vnode_t **vpp)
     struct vnode **vpp)  
 {  {
   
         printf("tmpfs_vget called; need for it unknown yet\n");          printf("tmpfs_vget called; need for it unknown yet\n");
         return EOPNOTSUPP;          return EOPNOTSUPP;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)  tmpfs_fhtovp(struct mount *mp, struct fid *fhp, vnode_t **vpp)
 {  {
         bool found;          tmpfs_mount_t *tmp = VFS_TO_TMPFS(mp);
         struct tmpfs_fid tfh;          tmpfs_node_t *node;
         struct tmpfs_mount *tmp;          tmpfs_fid_t tfh;
         struct tmpfs_node *node;  
   
         tmp = VFS_TO_TMPFS(mp);  
   
         if (fhp->fid_len != sizeof(struct tmpfs_fid))  
                 return EINVAL;  
   
         memcpy(&tfh, fhp, sizeof(struct tmpfs_fid));  
   
         if (tfh.tf_id >= tmp->tm_nodes_max)          if (fhp->fid_len != sizeof(tmpfs_fid_t)) {
                 return EINVAL;                  return EINVAL;
           }
           memcpy(&tfh, fhp, sizeof(tmpfs_fid_t));
   
         found = false;  
         mutex_enter(&tmp->tm_lock);          mutex_enter(&tmp->tm_lock);
         LIST_FOREACH(node, &tmp->tm_nodes, tn_entries) {          LIST_FOREACH(node, &tmp->tm_nodes, tn_entries) {
                 if (node->tn_id == tfh.tf_id &&                  if (node->tn_id != tfh.tf_id) {
                     node->tn_gen == tfh.tf_gen) {                          continue;
                         found = true;                  }
                         break;                  if (TMPFS_NODE_GEN(node) != tfh.tf_gen) {
                           continue;
                 }                  }
                   mutex_enter(&node->tn_vlock);
                   break;
         }          }
         mutex_exit(&tmp->tm_lock);          mutex_exit(&tmp->tm_lock);
   
         /* XXXAD nothing to prevent 'node' from being removed. */          /* Will release the tn_vlock. */
         return found ? tmpfs_alloc_vp(mp, node, vpp) : EINVAL;          return node ? tmpfs_vnode_get(mp, node, vpp) : ESTALE;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_vptofh(struct vnode *vp, struct fid *fhp, size_t *fh_size)  tmpfs_vptofh(vnode_t *vp, struct fid *fhp, size_t *fh_size)
 {  {
         struct tmpfs_fid tfh;          tmpfs_fid_t tfh;
         struct tmpfs_node *node;          tmpfs_node_t *node;
   
         if (*fh_size < sizeof(struct tmpfs_fid)) {          if (*fh_size < sizeof(tmpfs_fid_t)) {
                 *fh_size = sizeof(struct tmpfs_fid);                  *fh_size = sizeof(tmpfs_fid_t);
                 return E2BIG;                  return E2BIG;
         }          }
         *fh_size = sizeof(struct tmpfs_fid);          *fh_size = sizeof(tmpfs_fid_t);
         node = VP_TO_TMPFS_NODE(vp);          node = VP_TO_TMPFS_NODE(vp);
   
         memset(&tfh, 0, sizeof(tfh));          memset(&tfh, 0, sizeof(tfh));
         tfh.tf_len = sizeof(struct tmpfs_fid);          tfh.tf_len = sizeof(tmpfs_fid_t);
         tfh.tf_gen = node->tn_gen;          tfh.tf_gen = TMPFS_NODE_GEN(node);
         tfh.tf_id = node->tn_id;          tfh.tf_id = node->tn_id;
         memcpy(fhp, &tfh, sizeof(tfh));          memcpy(fhp, &tfh, sizeof(tfh));
   
         return 0;          return 0;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_statvfs(struct mount *mp, struct statvfs *sbp)  tmpfs_statvfs(struct mount *mp, struct statvfs *sbp)
 {  {
         struct tmpfs_mount *tmp;          tmpfs_mount_t *tmp;
         fsfilcnt_t freenodes;          fsfilcnt_t freenodes;
         size_t avail;          size_t avail;
   
Line 340  tmpfs_statvfs(struct mount *mp, struct s
Line 335  tmpfs_statvfs(struct mount *mp, struct s
         sbp->f_bresvd = 0;          sbp->f_bresvd = 0;
   
         freenodes = MIN(tmp->tm_nodes_max - tmp->tm_nodes_cnt,          freenodes = MIN(tmp->tm_nodes_max - tmp->tm_nodes_cnt,
             avail * PAGE_SIZE / sizeof(struct tmpfs_node));              avail * PAGE_SIZE / sizeof(tmpfs_node_t));
   
         sbp->f_files = tmp->tm_nodes_cnt + freenodes;          sbp->f_files = tmp->tm_nodes_cnt + freenodes;
         sbp->f_favail = sbp->f_ffree = freenodes;          sbp->f_favail = sbp->f_ffree = freenodes;
Line 352  tmpfs_statvfs(struct mount *mp, struct s
Line 347  tmpfs_statvfs(struct mount *mp, struct s
         return 0;          return 0;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 /* ARGSUSED0 */  
 static int  static int
 tmpfs_sync(struct mount *mp, int waitfor,  tmpfs_sync(struct mount *mp, int waitfor, kauth_cred_t uc)
     kauth_cred_t uc)  
 {  {
   
         return 0;          return 0;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 static void  
 tmpfs_init(void)  
 {  
   
 }  
   
 /* --------------------------------------------------------------------- */  
   
 static void  
 tmpfs_done(void)  
 {  
   
 }  
   
 /* --------------------------------------------------------------------- */  
   
 static int  static int
 tmpfs_snapshot(struct mount *mp, struct vnode *vp,  tmpfs_snapshot(struct mount *mp, vnode_t *vp, struct timespec *ctime)
     struct timespec *ctime)  
 {  {
   
         return EOPNOTSUPP;          return EOPNOTSUPP;
 }  }
   
 /* --------------------------------------------------------------------- */  
   
 /*  /*
  * tmpfs vfs operations.   * tmpfs vfs operations.
  */   */

Legend:
Removed from v.1.46  
changed lines
  Added in v.1.46.2.1

CVSweb <webmaster@jp.NetBSD.org>