[BACK]Return to ulfs_lookup.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / ufs / lfs

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

Diff for /src/sys/ufs/lfs/ulfs_lookup.c between version 1.12.2.2 and 1.12.2.3

version 1.12.2.2, 2013/06/23 06:18:39 version 1.12.2.3, 2014/08/20 00:04:45
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
Line 59  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/proc.h>  #include <sys/proc.h>
 #include <sys/kmem.h>  #include <sys/kmem.h>
   
   #include <ufs/lfs/lfs_extern.h>
   
 #include <ufs/lfs/ulfs_inode.h>  #include <ufs/lfs/ulfs_inode.h>
 #ifdef LFS_DIRHASH  #ifdef LFS_DIRHASH
 #include <ufs/lfs/ulfs_dirhash.h>  #include <ufs/lfs/ulfs_dirhash.h>
Line 111  int lfs_dirchk = 0;
Line 113  int lfs_dirchk = 0;
 int  int
 ulfs_lookup(void *v)  ulfs_lookup(void *v)
 {  {
         struct vop_lookup_args /* {          struct vop_lookup_v2_args /* {
                 struct vnode *a_dvp;                  struct vnode *a_dvp;
                 struct vnode **a_vpp;                  struct vnode **a_vpp;
                 struct componentname *a_cnp;                  struct componentname *a_cnp;
Line 147  ulfs_lookup(void *v)
Line 149  ulfs_lookup(void *v)
         kauth_cred_t cred = cnp->cn_cred;          kauth_cred_t cred = cnp->cn_cred;
         int flags;          int flags;
         int nameiop = cnp->cn_nameiop;          int nameiop = cnp->cn_nameiop;
         struct ulfsmount *ump = dp->i_ump;          struct lfs *fs = dp->i_lfs;
         const int needswap = ULFS_MPNEEDSWAP(ump);          const int needswap = ULFS_MPNEEDSWAP(fs);
         int dirblksiz = ump->um_dirblksiz;          int dirblksiz = fs->um_dirblksiz;
         ino_t foundino;          ino_t foundino;
         struct ulfs_lookup_results *results;          struct ulfs_lookup_results *results;
         int iswhiteout;                 /* temp result from cache_lookup() */          int iswhiteout;                 /* temp result from cache_lookup() */
Line 286  ulfs_lookup(void *v)
Line 288  ulfs_lookup(void *v)
                     NULL, &bp, false)))                      NULL, &bp, false)))
                         goto out;                          goto out;
                 numdirpasses = 2;                  numdirpasses = 2;
                 nchstats.ncs_2passes++;                  namecache_count_2passes();
         }          }
         prevoff = results->ulr_offset;          prevoff = results->ulr_offset;
         endsearch = roundup(dp->i_size, dirblksiz);          endsearch = roundup(dp->i_size, dirblksiz);
Line 522  notfound:
Line 524  notfound:
   
 found:  found:
         if (numdirpasses == 2)          if (numdirpasses == 2)
                 nchstats.ncs_pass2++;                  namecache_count_pass2();
         /*          /*
          * Check that directory length properly reflects presence           * Check that directory length properly reflects presence
          * of this entry.           * of this entry.
Line 682  found:
Line 684  found:
         error = 0;          error = 0;
   
 out:  out:
           if (error == 0 && *vpp != vdp)
                   VOP_UNLOCK(*vpp);
         fstrans_done(vdp->v_mount);          fstrans_done(vdp->v_mount);
         return error;          return error;
 }  }
Line 713  ulfs_dirbadentry(struct vnode *dp, struc
Line 717  ulfs_dirbadentry(struct vnode *dp, struc
         int i;          int i;
         int namlen;          int namlen;
         struct ulfsmount *ump = VFSTOULFS(dp->v_mount);          struct ulfsmount *ump = VFSTOULFS(dp->v_mount);
         const int needswap = ULFS_MPNEEDSWAP(ump);          struct lfs *fs = ump->um_lfs;
         int dirblksiz = ump->um_dirblksiz;          const int needswap = ULFS_MPNEEDSWAP(fs);
           int dirblksiz = fs->um_dirblksiz;
   
 #if (BYTE_ORDER == LITTLE_ENDIAN)  #if (BYTE_ORDER == LITTLE_ENDIAN)
         if (FSFMT(dp) && needswap == 0)          if (FSFMT(dp) && needswap == 0)
Line 811  ulfs_direnter(struct vnode *dvp, const s
Line 816  ulfs_direnter(struct vnode *dvp, const s
     struct componentname *cnp, struct buf *newdirbp)      struct componentname *cnp, struct buf *newdirbp)
 {  {
         kauth_cred_t cr;          kauth_cred_t cr;
         struct lwp *l;  
         int newentrysize;          int newentrysize;
         struct inode *dp;          struct inode *dp;
         struct buf *bp;          struct buf *bp;
Line 821  ulfs_direnter(struct vnode *dvp, const s
Line 825  ulfs_direnter(struct vnode *dvp, const s
         char *dirbuf;          char *dirbuf;
         struct timespec ts;          struct timespec ts;
         struct ulfsmount *ump = VFSTOULFS(dvp->v_mount);          struct ulfsmount *ump = VFSTOULFS(dvp->v_mount);
         const int needswap = ULFS_MPNEEDSWAP(ump);          struct lfs *fs = ump->um_lfs;
         int dirblksiz = ump->um_dirblksiz;          const int needswap = ULFS_MPNEEDSWAP(fs);
           int dirblksiz = fs->um_dirblksiz;
   
         error = 0;          error = 0;
         cr = cnp->cn_cred;          cr = cnp->cn_cred;
         l = curlwp;  
   
         dp = VTOI(dvp);          dp = VTOI(dvp);
         newentrysize = LFS_DIRSIZ(0, dirp, 0);          newentrysize = LFS_DIRSIZ(0, dirp, 0);
Line 840  ulfs_direnter(struct vnode *dvp, const s
Line 844  ulfs_direnter(struct vnode *dvp, const s
                  */                   */
                 if (ulr->ulr_offset & (dirblksiz - 1))                  if (ulr->ulr_offset & (dirblksiz - 1))
                         panic("ulfs_direnter: newblk");                          panic("ulfs_direnter: newblk");
                 if ((error = ULFS_BALLOC(dvp, (off_t)ulr->ulr_offset, dirblksiz,                  if ((error = lfs_balloc(dvp, (off_t)ulr->ulr_offset, dirblksiz,
                     cr, B_CLRBUF | B_SYNC, &bp)) != 0) {                      cr, B_CLRBUF | B_SYNC, &bp)) != 0) {
                         return (error);                          return (error);
                 }                  }
Line 873  ulfs_direnter(struct vnode *dvp, const s
Line 877  ulfs_direnter(struct vnode *dvp, const s
 #endif  #endif
                 error = VOP_BWRITE(bp->b_vp, bp);                  error = VOP_BWRITE(bp->b_vp, bp);
                 vfs_timestamp(&ts);                  vfs_timestamp(&ts);
                 ret = ULFS_UPDATE(dvp, &ts, &ts, UPDATE_DIROP);                  ret = lfs_update(dvp, &ts, &ts, UPDATE_DIROP);
                 if (error == 0)                  if (error == 0)
                         return (ret);                          return (ret);
                 return (error);                  return (error);
Line 1016  ulfs_direnter(struct vnode *dvp, const s
Line 1020  ulfs_direnter(struct vnode *dvp, const s
                 if (dp->i_dirhash != NULL)                  if (dp->i_dirhash != NULL)
                         ulfsdirhash_dirtrunc(dp, ulr->ulr_endoff);                          ulfsdirhash_dirtrunc(dp, ulr->ulr_endoff);
 #endif  #endif
                 (void) ULFS_TRUNCATE(dvp, (off_t)ulr->ulr_endoff, IO_SYNC, cr);                  (void) lfs_truncate(dvp, (off_t)ulr->ulr_endoff, IO_SYNC, cr);
         }          }
         return (error);          return (error);
 }  }
Line 1064  ulfs_dirremove(struct vnode *dvp, const 
Line 1068  ulfs_dirremove(struct vnode *dvp, const 
         struct lfs_direct *ep;          struct lfs_direct *ep;
         struct buf *bp;          struct buf *bp;
         int error;          int error;
 #ifdef LFS_EI          const int needswap = ULFS_MPNEEDSWAP(dp->i_lfs);
         const int needswap = ULFS_MPNEEDSWAP(dp->i_ump);  
 #endif  
   
         if (flags & DOWHITEOUT) {          if (flags & DOWHITEOUT) {
                 /*                  /*
Line 1112  ulfs_dirremove(struct vnode *dvp, const 
Line 1114  ulfs_dirremove(struct vnode *dvp, const 
   
 #ifdef LFS_DIRHASH  #ifdef LFS_DIRHASH
         if (dp->i_dirhash != NULL) {          if (dp->i_dirhash != NULL) {
                 int dirblksiz = ip->i_ump->um_dirblksiz;                  int dirblksiz = ip->i_lfs->um_dirblksiz;
                 ulfsdirhash_checkblock(dp, (char *)ep -                  ulfsdirhash_checkblock(dp, (char *)ep -
                     ((ulr->ulr_offset - ulr->ulr_count) & (dirblksiz - 1)),                      ((ulr->ulr_offset - ulr->ulr_count) & (dirblksiz - 1)),
                     ulr->ulr_offset & ~(dirblksiz - 1));                      ulr->ulr_offset & ~(dirblksiz - 1));
Line 1174  ulfs_dirrewrite(struct inode *dp, off_t 
Line 1176  ulfs_dirrewrite(struct inode *dp, off_t 
         error = ulfs_blkatoff(vdp, offset, (void *)&ep, &bp, true);          error = ulfs_blkatoff(vdp, offset, (void *)&ep, &bp, true);
         if (error)          if (error)
                 return (error);                  return (error);
         ep->d_ino = ulfs_rw32(newinum, ULFS_MPNEEDSWAP(dp->i_ump));          ep->d_ino = ulfs_rw32(newinum, ULFS_IPNEEDSWAP(dp));
         if (!FSFMT(vdp))          if (!FSFMT(vdp))
                 ep->d_type = newtype;                  ep->d_type = newtype;
         oip->i_nlink--;          oip->i_nlink--;
Line 1260  ulfs_dirempty(struct inode *ip, ino_t pa
Line 1262  ulfs_dirempty(struct inode *ip, ino_t pa
         return (1);          return (1);
 }  }
   
 /*  
  * Check if source directory is in the path of the target directory.  
  * Target is supplied locked, source is unlocked.  
  * The target is always vput before returning.  
  */  
 int  
 ulfs_checkpath(struct inode *source, struct inode *target, kauth_cred_t cred)  
 {  
         struct vnode *nextvp, *vp;  
         int error, rootino, namlen;  
         struct lfs_dirtemplate dirbuf;  
         const int needswap = ULFS_MPNEEDSWAP(target->i_ump);  
   
         vp = ITOV(target);  
         if (target->i_number == source->i_number) {  
                 error = EEXIST;  
                 goto out;  
         }  
         rootino = ULFS_ROOTINO;  
         error = 0;  
         if (target->i_number == rootino)  
                 goto out;  
   
         for (;;) {  
                 if (vp->v_type != VDIR) {  
                         error = ENOTDIR;  
                         break;  
                 }  
                 error = vn_rdwr(UIO_READ, vp, (void *)&dirbuf,  
                     sizeof (struct lfs_dirtemplate), (off_t)0, UIO_SYSSPACE,  
                     IO_NODELOCKED, cred, NULL, NULL);  
                 if (error != 0)  
                         break;  
 #if (BYTE_ORDER == LITTLE_ENDIAN)  
                 if (FSFMT(vp) && needswap == 0)  
                         namlen = dirbuf.dotdot_type;  
                 else  
                         namlen = dirbuf.dotdot_namlen;  
 #else  
                 if (FSFMT(vp) && needswap != 0)  
                         namlen = dirbuf.dotdot_type;  
                 else  
                         namlen = dirbuf.dotdot_namlen;  
 #endif  
                 if (namlen != 2 ||  
                     dirbuf.dotdot_name[0] != '.' ||  
                     dirbuf.dotdot_name[1] != '.') {  
                         error = ENOTDIR;  
                         break;  
                 }  
                 if (ulfs_rw32(dirbuf.dotdot_ino, needswap) == source->i_number) {  
                         error = EINVAL;  
                         break;  
                 }  
                 if (ulfs_rw32(dirbuf.dotdot_ino, needswap) == rootino)  
                         break;  
                 VOP_UNLOCK(vp);  
                 error = VFS_VGET(vp->v_mount,  
                     ulfs_rw32(dirbuf.dotdot_ino, needswap), &nextvp);  
                 vrele(vp);  
                 if (error) {  
                         vp = NULL;  
                         break;  
                 }  
                 vp = nextvp;  
         }  
   
 out:  
         if (error == ENOTDIR)  
                 printf("checkpath: .. not a directory\n");  
         if (vp != NULL)  
                 vput(vp);  
         return (error);  
 }  
   
 /*  
  * Extract the inode number of ".." from a directory.  
  * Helper for ulfs_parentcheck.  
  */  
 static int  
 ulfs_readdotdot(struct vnode *vp, int needswap, kauth_cred_t cred, ino_t *result)  
 {  
         struct lfs_dirtemplate dirbuf;  
         int namlen, error;  
   
         error = vn_rdwr(UIO_READ, vp, &dirbuf,  
                     sizeof (struct lfs_dirtemplate), (off_t)0, UIO_SYSSPACE,  
                     IO_NODELOCKED, cred, NULL, NULL);  
         if (error) {  
                 return error;  
         }  
   
 #if (BYTE_ORDER == LITTLE_ENDIAN)  
         if (FSFMT(vp) && needswap == 0)  
                 namlen = dirbuf.dotdot_type;  
         else  
                 namlen = dirbuf.dotdot_namlen;  
 #else  
         if (FSFMT(vp) && needswap != 0)  
                 namlen = dirbuf.dotdot_type;  
         else  
                 namlen = dirbuf.dotdot_namlen;  
 #endif  
         if (namlen != 2 ||  
             dirbuf.dotdot_name[0] != '.' ||  
             dirbuf.dotdot_name[1] != '.') {  
                 printf("ulfs_readdotdot: directory %llu contains "  
                        "garbage instead of ..\n",  
                        (unsigned long long) VTOI(vp)->i_number);  
                 return ENOTDIR;  
         }  
         *result = ulfs_rw32(dirbuf.dotdot_ino, needswap);  
         return 0;  
 }  
   
 /*  
  * Check if LOWER is a descendent of UPPER. If we find UPPER, return  
  * nonzero in FOUND and return a reference to the immediate descendent  
  * of UPPER in UPPERCHILD. If we don't find UPPER (that is, if we  
  * reach the volume root and that isn't UPPER), return zero in FOUND  
  * and null in UPPERCHILD.  
  *  
  * Neither UPPER nor LOWER should be locked.  
  *  
  * On error (such as a permissions error checking up the directory  
  * tree) fail entirely.  
  *  
  * Note that UPPER and LOWER must be on the same volume, and because  
  * we inspect only that volume NEEDSWAP can be constant.  
  */  
 int  
 ulfs_parentcheck(struct vnode *upper, struct vnode *lower, kauth_cred_t cred,  
                 int *found_ret, struct vnode **upperchild_ret)  
 {  
         const int needswap = ULFS_MPNEEDSWAP(VTOI(lower)->i_ump);  
         ino_t upper_ino, found_ino;  
         struct vnode *current, *next;  
         int error;  
   
         if (upper == lower) {  
                 vref(upper);  
                 *found_ret = 1;  
                 *upperchild_ret = upper;  
                 return 0;  
         }  
         if (VTOI(lower)->i_number == ULFS_ROOTINO) {  
                 *found_ret = 0;  
                 *upperchild_ret = NULL;  
                 return 0;  
         }  
   
         upper_ino = VTOI(upper)->i_number;  
   
         current = lower;  
         vref(current);  
         vn_lock(current, LK_EXCLUSIVE | LK_RETRY);  
   
         for (;;) {  
                 error = ulfs_readdotdot(current, needswap, cred, &found_ino);  
                 if (error) {  
                         vput(current);  
                         return error;  
                 }  
                 if (found_ino == upper_ino) {  
                         VOP_UNLOCK(current);  
                         *found_ret = 1;  
                         *upperchild_ret = current;  
                         return 0;  
                 }  
                 if (found_ino == ULFS_ROOTINO) {  
                         vput(current);  
                         *found_ret = 0;  
                         *upperchild_ret = NULL;  
                         return 0;  
                 }  
                 VOP_UNLOCK(current);  
                 error = VFS_VGET(current->v_mount, found_ino, &next);  
                 if (error) {  
                         vrele(current);  
                         return error;  
                 }  
                 KASSERT(VOP_ISLOCKED(next));  
                 if (next->v_type != VDIR) {  
                         printf("ulfs_parentcheck: inode %llu reached via .. of "  
                                "inode %llu is not a directory\n",  
                             (unsigned long long)VTOI(next)->i_number,  
                             (unsigned long long)VTOI(current)->i_number);  
                         vput(next);  
                         vrele(current);  
                         return ENOTDIR;  
                 }  
                 vrele(current);  
                 current = next;  
         }  
   
         return 0;  
 }  
   
 #define ULFS_DIRRABLKS 0  #define ULFS_DIRRABLKS 0
 int ulfs_dirrablks = ULFS_DIRRABLKS;  int ulfs_dirrablks = ULFS_DIRRABLKS;
   
Line 1472  int
Line 1276  int
 ulfs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp,  ulfs_blkatoff(struct vnode *vp, off_t offset, char **res, struct buf **bpp,
     bool modify)      bool modify)
 {  {
         struct inode *ip;          struct inode *ip __diagused;
         struct buf *bp;          struct buf *bp;
         daddr_t lbn;          daddr_t lbn;
         const int dirrablks = ulfs_dirrablks;          const int dirrablks = ulfs_dirrablks;

Legend:
Removed from v.1.12.2.2  
changed lines
  Added in v.1.12.2.3

CVSweb <webmaster@jp.NetBSD.org>