[BACK]Return to tmpfs_vnops.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_vnops.c between version 1.49 and 1.49.10.4

version 1.49, 2008/02/06 11:22:12 version 1.49.10.4, 2009/09/16 13:38:00
Line 16 
Line 16 
  * 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the   *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.   *    documentation and/or other materials provided with the distribution.
  * 3. All advertising materials mentioning features or use of this software  
  *    must display the following acknowledgement:  
  *        This product includes software developed by the NetBSD  
  *        Foundation, Inc. and its contributors.  
  * 4. Neither the name of The NetBSD Foundation nor the names of its  
  *    contributors may be used to endorse or promote products derived  
  *    from this software without specific prior written permission.  
  *   *
  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS   * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
Line 61  __KERNEL_RCSID(0, "$NetBSD$");
Line 54  __KERNEL_RCSID(0, "$NetBSD$");
 #include <uvm/uvm.h>  #include <uvm/uvm.h>
   
 #include <miscfs/fifofs/fifo.h>  #include <miscfs/fifofs/fifo.h>
   #include <miscfs/genfs/genfs.h>
 #include <fs/tmpfs/tmpfs_vnops.h>  #include <fs/tmpfs/tmpfs_vnops.h>
 #include <fs/tmpfs/tmpfs.h>  #include <fs/tmpfs/tmpfs.h>
   
Line 211  tmpfs_lookup(void *v)
Line 205  tmpfs_lookup(void *v)
                                 goto out;                                  goto out;
                         }                          }
   
                         /* If we are deleting or renaming the entry, keep                          /* Check permissions */
                          * track of its tmpfs_dirent so that it can be  
                          * easily deleted later. */  
                         if ((cnp->cn_flags & ISLASTCN) &&                          if ((cnp->cn_flags & ISLASTCN) &&
                             (cnp->cn_nameiop == DELETE ||                              (cnp->cn_nameiop == DELETE ||
                             cnp->cn_nameiop == RENAME)) {                              cnp->cn_nameiop == RENAME)) {
                                   kauth_action_t action = 0;
   
                                   /* This is the file-system's decision. */
                                 if ((dnode->tn_mode & S_ISTXT) != 0 &&                                  if ((dnode->tn_mode & S_ISTXT) != 0 &&
                                     kauth_authorize_generic(cnp->cn_cred,  
                                      KAUTH_GENERIC_ISSUSER, NULL) != 0 &&  
                                     kauth_cred_geteuid(cnp->cn_cred) != dnode->tn_uid &&                                      kauth_cred_geteuid(cnp->cn_cred) != dnode->tn_uid &&
                                     kauth_cred_geteuid(cnp->cn_cred) != tnode->tn_uid)                                      kauth_cred_geteuid(cnp->cn_cred) != tnode->tn_uid)
                                         return EPERM;                                          error = EPERM;
                                 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred);                                  else
                                           error = 0;
   
                                   /* Only bother if we're not already failing it. */
                                   if (!error) {
                                           error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred);
                                   }
   
                                   if (cnp->cn_nameiop == DELETE)
                                           action |= KAUTH_VNODE_DELETE;
                                   else /* if (cnp->cn_nameiop == RENAME) */
                                           action |= KAUTH_VNODE_RENAME;
   
                                   error = kauth_authorize_vnode(cnp->cn_cred,
                                       action, *vpp, dvp, error);
                                 if (error != 0)                                  if (error != 0)
                                         goto out;                                          goto out;
   
                                   cnp->cn_flags |= SAVENAME;
                         } else                          } else
                                 de = NULL;                                  de = NULL;
   
Line 277  tmpfs_mknod(void *v)
Line 286  tmpfs_mknod(void *v)
         struct vattr *vap = ((struct vop_mknod_args *)v)->a_vap;          struct vattr *vap = ((struct vop_mknod_args *)v)->a_vap;
   
         if (vap->va_type != VBLK && vap->va_type != VCHR &&          if (vap->va_type != VBLK && vap->va_type != VCHR &&
             vap->va_type != VFIFO)              vap->va_type != VFIFO) {
                   vput(dvp);
                 return EINVAL;                  return EINVAL;
           }
   
         return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);          return tmpfs_alloc_file(dvp, vpp, vap, cnp, NULL);
 }  }
Line 334  tmpfs_close(void *v)
Line 345  tmpfs_close(void *v)
         if (node->tn_links > 0) {          if (node->tn_links > 0) {
                 /* Update node times.  No need to do it if the node has                  /* Update node times.  No need to do it if the node has
                  * been deleted, because it will vanish after we return. */                   * been deleted, because it will vanish after we return. */
                 tmpfs_update(vp, NULL, NULL, UPDATE_CLOSE);                  tmpfs_update(vp, NULL, NULL, NULL, UPDATE_CLOSE);
         }          }
   
         return 0;          return 0;
Line 342  tmpfs_close(void *v)
Line 353  tmpfs_close(void *v)
   
 /* --------------------------------------------------------------------- */  /* --------------------------------------------------------------------- */
   
 int  static int
 tmpfs_access(void *v)  tmpfs_check_possible(struct vnode *vp, struct tmpfs_node *node, mode_t mode)
 {  {
         struct vnode *vp = ((struct vop_access_args *)v)->a_vp;          int error = 0;
         int mode = ((struct vop_access_args *)v)->a_mode;  
         kauth_cred_t cred = ((struct vop_access_args *)v)->a_cred;  
   
         int error;  
         struct tmpfs_node *node;  
   
         KASSERT(VOP_ISLOCKED(vp));  
   
         node = VP_TO_TMPFS_NODE(vp);  
   
         switch (vp->v_type) {          switch (vp->v_type) {
         case VDIR:          case VDIR:
Line 387  tmpfs_access(void *v)
Line 389  tmpfs_access(void *v)
                 goto out;                  goto out;
         }          }
   
         error = vaccess(vp->v_type, node->tn_mode, node->tn_uid,   out:
           return error;
   }
   
   static int
   tmpfs_check_permitted(struct vnode *vp, struct tmpfs_node *node, mode_t mode,
       kauth_cred_t cred)
   {
   
           return genfs_can_access(vp->v_type, node->tn_mode, node->tn_uid,
             node->tn_gid, mode, cred);              node->tn_gid, mode, cred);
   }
   
   int
   tmpfs_access(void *v)
   {
           struct vnode *vp = ((struct vop_access_args *)v)->a_vp;
           int mode = ((struct vop_access_args *)v)->a_mode;
           kauth_cred_t cred = ((struct vop_access_args *)v)->a_cred;
   
           int error;
           struct tmpfs_node *node;
   
           KASSERT(VOP_ISLOCKED(vp));
   
           node = VP_TO_TMPFS_NODE(vp);
   
           error = tmpfs_check_possible(vp, node, mode);
           if (error)
                   goto out;
   
           error = tmpfs_check_permitted(vp, node, mode, cred);
   
           error = kauth_authorize_vnode(cred, kauth_mode_to_action(mode), vp,
               NULL, error);
   
 out:  out:
         KASSERT(VOP_ISLOCKED(vp));          KASSERT(VOP_ISLOCKED(vp));
Line 410  tmpfs_getattr(void *v)
Line 445  tmpfs_getattr(void *v)
   
         VATTR_NULL(vap);          VATTR_NULL(vap);
   
         tmpfs_itimes(vp, NULL, NULL);          tmpfs_itimes(vp, NULL, NULL, NULL);
   
         vap->va_type = vp->v_type;          vap->va_type = vp->v_type;
         vap->va_mode = node->tn_mode;          vap->va_mode = node->tn_mode;
Line 439  tmpfs_getattr(void *v)
Line 474  tmpfs_getattr(void *v)
   
 /* --------------------------------------------------------------------- */  /* --------------------------------------------------------------------- */
   
   #define GOODTIME(tv)    ((tv)->tv_sec != VNOVAL || (tv)->tv_nsec != VNOVAL)
 /* XXX Should this operation be atomic?  I think it should, but code in  /* XXX Should this operation be atomic?  I think it should, but code in
  * XXX other places (e.g., ufs) doesn't seem to be... */   * XXX other places (e.g., ufs) doesn't seem to be... */
 int  int
Line 461  tmpfs_setattr(void *v)
Line 497  tmpfs_setattr(void *v)
             vap->va_fsid != VNOVAL ||              vap->va_fsid != VNOVAL ||
             vap->va_fileid != VNOVAL ||              vap->va_fileid != VNOVAL ||
             vap->va_blocksize != VNOVAL ||              vap->va_blocksize != VNOVAL ||
             vap->va_ctime.tv_sec != VNOVAL ||              GOODTIME(&vap->va_ctime) ||
             vap->va_ctime.tv_nsec != VNOVAL ||  
             vap->va_birthtime.tv_sec != VNOVAL ||  
             vap->va_birthtime.tv_nsec != VNOVAL ||  
             vap->va_gen != VNOVAL ||              vap->va_gen != VNOVAL ||
             vap->va_rdev != VNOVAL ||              vap->va_rdev != VNOVAL ||
             vap->va_bytes != VNOVAL)              vap->va_bytes != VNOVAL)
Line 482  tmpfs_setattr(void *v)
Line 515  tmpfs_setattr(void *v)
         if (error == 0 && (vap->va_mode != VNOVAL))          if (error == 0 && (vap->va_mode != VNOVAL))
                 error = tmpfs_chmod(vp, vap->va_mode, cred, l);                  error = tmpfs_chmod(vp, vap->va_mode, cred, l);
   
         if (error == 0 && ((vap->va_atime.tv_sec != VNOVAL &&          if (error == 0 && (GOODTIME(&vap->va_atime) || GOODTIME(&vap->va_mtime)
             vap->va_atime.tv_nsec != VNOVAL) ||              || GOODTIME(&vap->va_birthtime)))
             (vap->va_mtime.tv_sec != VNOVAL &&                  if ((error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,
             vap->va_mtime.tv_nsec != VNOVAL)))                      &vap->va_birthtime, vap->va_vaflags, cred, l)) == 0)
                 error = tmpfs_chtimes(vp, &vap->va_atime, &vap->va_mtime,                          return 0;
                     vap->va_vaflags, cred, l);  
   
         /* Update the node times.  We give preference to the error codes          /* Update the node times.  We give preference to the error codes
          * generated by this function rather than the ones that may arise           * generated by this function rather than the ones that may arise
          * from tmpfs_update. */           * from tmpfs_update. */
         tmpfs_update(vp, NULL, NULL, 0);          tmpfs_update(vp, NULL, NULL, NULL, 0);
   
         KASSERT(VOP_ISLOCKED(vp));          KASSERT(VOP_ISLOCKED(vp));
   
Line 506  tmpfs_read(void *v)
Line 538  tmpfs_read(void *v)
 {  {
         struct vnode *vp = ((struct vop_read_args *)v)->a_vp;          struct vnode *vp = ((struct vop_read_args *)v)->a_vp;
         struct uio *uio = ((struct vop_read_args *)v)->a_uio;          struct uio *uio = ((struct vop_read_args *)v)->a_uio;
           int ioflag = ((struct vop_read_args *)v)->a_ioflag;
   
         int error;          int error;
         int flags;  
         struct tmpfs_node *node;          struct tmpfs_node *node;
         struct uvm_object *uobj;          struct uvm_object *uobj;
   
Line 529  tmpfs_read(void *v)
Line 561  tmpfs_read(void *v)
         node->tn_status |= TMPFS_NODE_ACCESSED;          node->tn_status |= TMPFS_NODE_ACCESSED;
   
         uobj = node->tn_spec.tn_reg.tn_aobj;          uobj = node->tn_spec.tn_reg.tn_aobj;
         flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;  
         error = 0;          error = 0;
         while (error == 0 && uio->uio_resid > 0) {          while (error == 0 && uio->uio_resid > 0) {
                 vsize_t len;                  vsize_t len;
                 void *win;  
   
                 if (node->tn_size <= uio->uio_offset)                  if (node->tn_size <= uio->uio_offset)
                         break;                          break;
Line 542  tmpfs_read(void *v)
Line 572  tmpfs_read(void *v)
                 if (len == 0)                  if (len == 0)
                         break;                          break;
   
                 win = ubc_alloc(uobj, uio->uio_offset, &len, UVM_ADV_NORMAL,                  error = ubc_uiomove(uobj, uio, len, IO_ADV_DECODE(ioflag),
                     UBC_READ);                      UBC_READ | UBC_PARTIALOK | UBC_UNMAP_FLAG(vp));
                 error = uiomove(win, len, uio);  
                 ubc_release(win, flags);  
         }          }
   
 out:  out:
Line 565  tmpfs_write(void *v)
Line 593  tmpfs_write(void *v)
   
         bool extended;          bool extended;
         int error;          int error;
         int flags;  
         off_t oldsize;          off_t oldsize;
         struct tmpfs_node *node;          struct tmpfs_node *node;
         struct uvm_object *uobj;          struct uvm_object *uobj;
Line 596  tmpfs_write(void *v)
Line 623  tmpfs_write(void *v)
         }          }
   
         uobj = node->tn_spec.tn_reg.tn_aobj;          uobj = node->tn_spec.tn_reg.tn_aobj;
         flags = UBC_WANT_UNMAP(vp) ? UBC_UNMAP : 0;  
         error = 0;          error = 0;
         while (error == 0 && uio->uio_resid > 0) {          while (error == 0 && uio->uio_resid > 0) {
                 vsize_t len;                  vsize_t len;
                 void *win;  
   
                 len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);                  len = MIN(node->tn_size - uio->uio_offset, uio->uio_resid);
                 if (len == 0)                  if (len == 0)
                         break;                          break;
   
                 win = ubc_alloc(uobj, uio->uio_offset, &len, UVM_ADV_NORMAL,                  error = ubc_uiomove(uobj, uio, len, IO_ADV_DECODE(ioflag),
                     UBC_WRITE);                      UBC_WRITE | UBC_UNMAP_FLAG(vp));
                 error = uiomove(win, len, uio);  
                 ubc_release(win, flags);  
         }          }
   
         node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED |          node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED |
Line 637  tmpfs_fsync(void *v)
Line 660  tmpfs_fsync(void *v)
   
         KASSERT(VOP_ISLOCKED(vp));          KASSERT(VOP_ISLOCKED(vp));
   
         tmpfs_update(vp, NULL, NULL, 0);          tmpfs_update(vp, NULL, NULL, NULL, 0);
   
         return 0;          return 0;
 }  }
Line 669  tmpfs_remove(void *v)
Line 692  tmpfs_remove(void *v)
         node = VP_TO_TMPFS_NODE(vp);          node = VP_TO_TMPFS_NODE(vp);
         tmp = VFS_TO_TMPFS(vp->v_mount);          tmp = VFS_TO_TMPFS(vp->v_mount);
         de = tmpfs_dir_lookup(dnode, cnp);          de = tmpfs_dir_lookup(dnode, cnp);
         if (de == NULL) {          KASSERT(de);
                 error = ENOENT;  
                 goto out;  
         }  
         KASSERT(de->td_node == node);          KASSERT(de->td_node == node);
   
         /* Files marked as immutable or append-only cannot be deleted. */          /* Files marked as immutable or append-only cannot be deleted. */
Line 698  out:
Line 718  out:
                 vrele(dvp);                  vrele(dvp);
         else          else
                 vput(dvp);                  vput(dvp);
           PNBUF_PUT(cnp->cn_pnbuf);
   
         return error;          return error;
 }  }
Line 768  tmpfs_link(void *v)
Line 789  tmpfs_link(void *v)
   
         /* vp link count has changed, so update node times. */          /* vp link count has changed, so update node times. */
         node->tn_status |= TMPFS_NODE_CHANGED;          node->tn_status |= TMPFS_NODE_CHANGED;
         tmpfs_update(vp, NULL, NULL, 0);          tmpfs_update(vp, NULL, NULL, NULL, 0);
   
         error = 0;          error = 0;
   
Line 826  tmpfs_rename(void *v)
Line 847  tmpfs_rename(void *v)
         tdnode = VP_TO_TMPFS_DIR(tdvp);          tdnode = VP_TO_TMPFS_DIR(tdvp);
         tmp = VFS_TO_TMPFS(tdvp->v_mount);          tmp = VFS_TO_TMPFS(tdvp->v_mount);
   
           if (fdvp == tvp) {
                   error = 0;
                   goto out_unlocked;
           }
   
         /* If we need to move the directory between entries, lock the          /* If we need to move the directory between entries, lock the
          * source so that we can safely operate on it. */           * source so that we can safely operate on it. */
   
Line 836  tmpfs_rename(void *v)
Line 862  tmpfs_rename(void *v)
                         goto out_unlocked;                          goto out_unlocked;
         }          }
   
           /*
            * If the node we were renaming has scarpered, just give up.
            */
         de = tmpfs_dir_lookup(fdnode, fcnp);          de = tmpfs_dir_lookup(fdnode, fcnp);
         if (de == NULL) {          if (de == NULL || de->td_node != fnode) {
                 error = ENOENT;                  error = ENOENT;
                 goto out;                  goto out;
         }          }
         KASSERT(de->td_node == fnode);  
   
         /* If source and target are the same file, there is nothing to do. */          /* If source and target are the same file, there is nothing to do. */
         if (fvp == tvp) {          if (fvp == tvp) {
Line 849  tmpfs_rename(void *v)
Line 877  tmpfs_rename(void *v)
                 goto out;                  goto out;
         }          }
   
         /* Avoid manipulating '.' and '..' entries. */  
         if (de == NULL) {  
                 KASSERT(fvp->v_type == VDIR);  
                 error = EINVAL;  
                 goto out;  
         }  
         KASSERT(de->td_node == fnode);  
   
         /* If replacing an existing entry, ensure we can do the operation. */          /* If replacing an existing entry, ensure we can do the operation. */
         if (tvp != NULL) {          if (tvp != NULL) {
                 KASSERT(tnode != NULL);                  KASSERT(tnode != NULL);
Line 1049  tmpfs_rmdir(void *v)
Line 1069  tmpfs_rmdir(void *v)
   
         /* Get the directory entry associated with node (vp). */          /* Get the directory entry associated with node (vp). */
         de = tmpfs_dir_lookup(dnode, cnp);          de = tmpfs_dir_lookup(dnode, cnp);
         if (de == NULL) {          KASSERT(de);
                 error = ENOENT;  
                 goto out;  
         }  
         KASSERT(de->td_node == node);          KASSERT(de->td_node == node);
   
         /* Check flags to see if we are allowed to remove the directory. */          /* Check flags to see if we are allowed to remove the directory. */
Line 1084  tmpfs_rmdir(void *v)
Line 1101  tmpfs_rmdir(void *v)
         /* Release the nodes. */          /* Release the nodes. */
         vput(dvp);          vput(dvp);
         vput(vp);          vput(vp);
           PNBUF_PUT(cnp->cn_pnbuf);
   
         return error;          return error;
 }  }

Legend:
Removed from v.1.49  
changed lines
  Added in v.1.49.10.4

CVSweb <webmaster@jp.NetBSD.org>