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

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

Diff for /src/sys/ufs/ffs/ffs_snapshot.c between version 1.75 and 1.76

version 1.75, 2008/08/22 10:48:22 version 1.76, 2008/08/24 09:51:47
Line 89  __KERNEL_RCSID(0, "$NetBSD$");
Line 89  __KERNEL_RCSID(0, "$NetBSD$");
 #define MNT_IUNLOCK(v)  mutex_exit(&mntvnode_lock)  #define MNT_IUNLOCK(v)  mutex_exit(&mntvnode_lock)
   
 #if !defined(FFS_NO_SNAPSHOT)  #if !defined(FFS_NO_SNAPSHOT)
   typedef int (*acctfunc_t)
       (struct vnode *, void *, int, int, struct fs *, daddr_t, int);
   
 static int cgaccount(int, struct vnode *, void *, int);  static int cgaccount(int, struct vnode *, void *, int);
 static int expunge_ufs1(struct vnode *, struct inode *, struct fs *,  static int expunge(struct vnode *, struct inode *, struct fs *,
     int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,      acctfunc_t, int);
     ufs_lbn_t, int), int);  static int indiracct(struct vnode *, struct vnode *, int, daddr_t,
 static int indiracct_ufs1(struct vnode *, struct vnode *, int,      daddr_t, daddr_t, daddr_t, daddr_t, struct fs *, acctfunc_t, int);
     ufs1_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,  static int fullacct(struct vnode *, void *, int, int, struct fs *,
     int (*)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *, struct fs *,      daddr_t, int);
     ufs_lbn_t, int), int);  static int snapacct(struct vnode *, void *, int, int, struct fs *,
 static int fullacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,      daddr_t, int);
     struct fs *, ufs_lbn_t, int);  static int mapacct(struct vnode *, void *, int, int, struct fs *,
 static int snapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,      daddr_t, int);
     struct fs *, ufs_lbn_t, int);  
 static int mapacct_ufs1(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,  
     struct fs *, ufs_lbn_t, int);  
 static int expunge_ufs2(struct vnode *, struct inode *, struct fs *,  
     int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,  
     ufs_lbn_t, int), int);  
 static int indiracct_ufs2(struct vnode *, struct vnode *, int,  
     ufs2_daddr_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, ufs_lbn_t, struct fs *,  
     int (*)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *, struct fs *,  
     ufs_lbn_t, int), int);  
 static int fullacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,  
     struct fs *, ufs_lbn_t, int);  
 static int snapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,  
     struct fs *, ufs_lbn_t, int);  
 static int mapacct_ufs2(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,  
     struct fs *, ufs_lbn_t, int);  
 #endif /* !defined(FFS_NO_SNAPSHOT) */  #endif /* !defined(FFS_NO_SNAPSHOT) */
   
 static int ffs_copyonwrite(void *, struct buf *, bool);  static int ffs_copyonwrite(void *, struct buf *, bool);
Line 123  static int snapblkaddr(struct vnode *, d
Line 110  static int snapblkaddr(struct vnode *, d
 static int rwfsblk(struct vnode *, int, void *, ufs2_daddr_t);  static int rwfsblk(struct vnode *, int, void *, ufs2_daddr_t);
 static int syncsnap(struct vnode *);  static int syncsnap(struct vnode *);
 static int wrsnapblk(struct vnode *, void *, ufs2_daddr_t);  static int wrsnapblk(struct vnode *, void *, ufs2_daddr_t);
   
 static inline ufs2_daddr_t db_get(struct inode *, int);  static inline ufs2_daddr_t db_get(struct inode *, int);
 static inline void db_assign(struct inode *, int, ufs2_daddr_t);  static inline void db_assign(struct inode *, int, ufs2_daddr_t);
   static inline ufs2_daddr_t ib_get(struct inode *, int);
   static inline void ib_assign(struct inode *, int, ufs2_daddr_t);
 static inline ufs2_daddr_t idb_get(struct inode *, void *, int);  static inline ufs2_daddr_t idb_get(struct inode *, void *, int);
 static inline void idb_assign(struct inode *, void *, int, ufs2_daddr_t);  static inline void idb_assign(struct inode *, void *, int, ufs2_daddr_t);
   
Line 510  ffs_snapshot(struct mount *mp, struct vn
Line 500  ffs_snapshot(struct mount *mp, struct vn
                         }                          }
                 }                  }
                 snaplistsize += 1;                  snaplistsize += 1;
                 if (xp->i_ump->um_fstype == UFS1)                  error = expunge(vp, xp, copy_fs, fullacct, BLK_NOCOPY);
                         error = expunge_ufs1(vp, xp, copy_fs,  
                             fullacct_ufs1, BLK_NOCOPY);  
                 else  
                         error = expunge_ufs2(vp, xp, copy_fs,  
                             fullacct_ufs2, BLK_NOCOPY);  
                 if (blkno)                  if (blkno)
                         db_assign(xp, loc, blkno);                          db_assign(xp, loc, blkno);
                 if (!error)                  if (!error)
Line 597  ffs_snapshot(struct mount *mp, struct vn
Line 582  ffs_snapshot(struct mount *mp, struct vn
                 if (xp == ip)                  if (xp == ip)
                         break;                          break;
                 if ((error = UFS_WAPBL_BEGIN(mp)) == 0) {                  if ((error = UFS_WAPBL_BEGIN(mp)) == 0) {
                         if (xp->i_ump->um_fstype == UFS1)                          error = expunge(vp, xp, fs, snapacct, BLK_SNAP);
                                 error = expunge_ufs1(vp, xp, fs, snapacct_ufs1,  
                                     BLK_SNAP);  
                         else  
                                 error = expunge_ufs2(vp, xp, fs, snapacct_ufs2,  
                                     BLK_SNAP);  
                         if (error == 0 && xp->i_ffs_effnlink == 0)                          if (error == 0 && xp->i_ffs_effnlink == 0)
                                 error = ffs_freefile(copy_fs, vp,                                  error = ffs_freefile(copy_fs, vp,
                                     xp->i_number, xp->i_mode);                                      xp->i_number, xp->i_mode);
Line 625  ffs_snapshot(struct mount *mp, struct vn
Line 605  ffs_snapshot(struct mount *mp, struct vn
          * the list of allocated blocks in i_snapblklist.           * the list of allocated blocks in i_snapblklist.
          */           */
         if ((error = UFS_WAPBL_BEGIN(mp)) == 0) {          if ((error = UFS_WAPBL_BEGIN(mp)) == 0) {
                 if (ip->i_ump->um_fstype == UFS1)                  expunge(vp, ip, copy_fs, mapacct, BLK_SNAP);
                         error = expunge_ufs1(vp, ip, copy_fs, mapacct_ufs1,  
                             BLK_SNAP);  
                 else  
                         error = expunge_ufs2(vp, ip, copy_fs, mapacct_ufs2,  
                             BLK_SNAP);  
                 UFS_WAPBL_END(mp);                  UFS_WAPBL_END(mp);
         }          }
         if (error) {          if (error) {
Line 877  cgaccount(int cg, struct vnode *vp, void
Line 852  cgaccount(int cg, struct vnode *vp, void
  * blocks that it claims with BLK_SNAP so that fsck will   * blocks that it claims with BLK_SNAP so that fsck will
  * be able to account for those blocks properly and so   * be able to account for those blocks properly and so
  * that this snapshot knows that it need not copy them   * that this snapshot knows that it need not copy them
  * if the other snapshot holding them is freed. This code   * if the other snapshot holding them is freed.
  * is reproduced once each for UFS1 and UFS2.  
  */   */
 static int  static int
 expunge_ufs1(struct vnode *snapvp, struct inode *cancelip, struct fs *fs,  expunge(struct vnode *snapvp, struct inode *cancelip, struct fs *fs,
     int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,      acctfunc_t acctfunc, int expungetype)
                     struct fs *, ufs_lbn_t, int),  
     int expungetype)  
 {  {
         int i, error, ns;          int i, error, ns;
         ufs_lbn_t lbn, rlbn;          daddr_t lbn, rlbn;
         ufs2_daddr_t len, blkno, numblks, blksperindir;          daddr_t len, blkno, numblks, blksperindir;
         struct ufs1_dinode *dip;          struct ufs1_dinode *dip1;
           struct ufs2_dinode *dip2;
           void *bap;
         struct buf *bp;          struct buf *bp;
   
         ns = UFS_FSNEEDSWAP(fs);          ns = UFS_FSNEEDSWAP(fs);
Line 916  expunge_ufs1(struct vnode *snapvp, struc
Line 890  expunge_ufs1(struct vnode *snapvp, struc
          * Set a snapshot inode to be a zero length file, regular files           * Set a snapshot inode to be a zero length file, regular files
          * or unlinked snapshots to be completely unallocated.           * or unlinked snapshots to be completely unallocated.
          */           */
         dip = (struct ufs1_dinode *)bp->b_data +          if (fs->fs_magic == FS_UFS1_MAGIC) {
             ino_to_fsbo(fs, cancelip->i_number);                  dip1 = (struct ufs1_dinode *)bp->b_data +
         if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)                      ino_to_fsbo(fs, cancelip->i_number);
                 dip->di_mode = 0;                  if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)
         dip->di_size = 0;                          dip1->di_mode = 0;
         dip->di_blocks = 0;                  dip1->di_size = 0;
         dip->di_flags =                  dip1->di_blocks = 0;
             ufs_rw32(ufs_rw32(dip->di_flags, ns) & ~SF_SNAPSHOT, ns);                  dip1->di_flags =
         bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs1_daddr_t));                      ufs_rw32(ufs_rw32(dip1->di_flags, ns) & ~SF_SNAPSHOT, ns);
         bdwrite(bp);                  bzero(&dip1->di_db[0], (NDADDR + NIADDR) * sizeof(int32_t));
         /*  
          * Now go through and expunge all the blocks in the file  
          * using the function requested.  
          */  
         numblks = howmany(cancelip->i_size, fs->fs_bsize);  
         if ((error = (*acctfunc)(snapvp, &cancelip->i_ffs1_db[0],  
             &cancelip->i_ffs1_db[NDADDR], fs, 0, expungetype)))  
                 return (error);  
         if ((error = (*acctfunc)(snapvp, &cancelip->i_ffs1_ib[0],  
             &cancelip->i_ffs1_ib[NIADDR], fs, -1, expungetype)))  
                 return (error);  
         blksperindir = 1;  
         lbn = -NDADDR;  
         len = numblks - NDADDR;  
         rlbn = NDADDR;  
         for (i = 0; len > 0 && i < NIADDR; i++) {  
                 error = indiracct_ufs1(snapvp, ITOV(cancelip), i,  
                     ufs_rw32(cancelip->i_ffs1_ib[i], ns), lbn, rlbn, len,  
                     blksperindir, fs, acctfunc, expungetype);  
                 if (error)  
                         return (error);  
                 blksperindir *= NINDIR(fs);  
                 lbn -= blksperindir + 1;  
                 len -= blksperindir;  
                 rlbn += blksperindir;  
         }  
         return (0);  
 }  
   
 /*  
  * Descend an indirect block chain for vnode cancelvp accounting for all  
  * its indirect blocks in snapvp.  
  */  
 static int  
 indiracct_ufs1(struct vnode *snapvp, struct vnode *cancelvp, int level,  
     ufs1_daddr_t blkno, ufs_lbn_t lbn, ufs_lbn_t rlbn, ufs_lbn_t remblks,  
     ufs_lbn_t blksperindir, struct fs *fs,  
     int (*acctfunc)(struct vnode *, ufs1_daddr_t *, ufs1_daddr_t *,  
                     struct fs *, ufs_lbn_t, int),  
     int expungetype)  
 {  
         int error, ns, num, i;  
         ufs_lbn_t subblksperindir;  
         struct indir indirs[NIADDR + 2];  
         ufs1_daddr_t last, *bap;  
         struct buf *bp;  
   
         ns = UFS_FSNEEDSWAP(fs);  
   
         if (blkno == 0) {  
                 if (expungetype == BLK_NOCOPY)  
                         return (0);  
                 panic("indiracct_ufs1: missing indir");  
         }  
         if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)  
                 return (error);  
         if (lbn != indirs[num - 1 - level].in_lbn || num < 2)  
                 panic("indiracct_ufs1: botched params");  
         /*  
          * We have to expand bread here since it will deadlock looking  
          * up the block number for any blocks that are not in the cache.  
          */  
         error = ffs_getblk(cancelvp, lbn, fsbtodb(fs, blkno), fs->fs_bsize,  
             false, &bp);  
         if (error)  
                 return error;  
         if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 && (error =  
             rwfsblk(bp->b_vp, B_READ, bp->b_data, fragstoblks(fs, blkno)))) {  
                 brelse(bp, 0);  
                 return (error);  
         }  
         /*  
          * Account for the block pointers in this indirect block.  
          */  
         last = howmany(remblks, blksperindir);  
         if (last > NINDIR(fs))  
                 last = NINDIR(fs);  
         bap = malloc(fs->fs_bsize, M_DEVBUF, M_WAITOK);  
         bcopy(bp->b_data, (void *)bap, fs->fs_bsize);  
         brelse(bp, 0);  
         error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs,  
             level == 0 ? rlbn : -1, expungetype);  
         if (error || level == 0)  
                 goto out;  
         /*  
          * Account for the block pointers in each of the indirect blocks  
          * in the levels below us.  
          */  
         subblksperindir = blksperindir / NINDIR(fs);  
         for (lbn++, level--, i = 0; i < last; i++) {  
                 error = indiracct_ufs1(snapvp, cancelvp, level,  
                     ufs_rw32(bap[i], ns), lbn, rlbn, remblks, subblksperindir,  
                     fs, acctfunc, expungetype);  
                 if (error)  
                         goto out;  
                 rlbn += blksperindir;  
                 lbn -= blksperindir;  
                 remblks -= blksperindir;  
         }  
 out:  
         FREE(bap, M_DEVBUF);  
         return (error);  
 }  
   
 /*  
  * Do both snap accounting and map accounting.  
  */  
 static int  
 fullacct_ufs1(struct vnode *vp, ufs1_daddr_t *oldblkp, ufs1_daddr_t *lastblkp,  
     struct fs *fs, ufs_lbn_t lblkno,  
     int exptype /* BLK_SNAP or BLK_NOCOPY */)  
 {  
         int error;  
   
         if ((error = snapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype)))  
                 return (error);  
         return (mapacct_ufs1(vp, oldblkp, lastblkp, fs, lblkno, exptype));  
 }  
   
 /*  
  * Identify a set of blocks allocated in a snapshot inode.  
  */  
 static int  
 snapacct_ufs1(struct vnode *vp, ufs1_daddr_t *oldblkp, ufs1_daddr_t *lastblkp,  
     struct fs *fs, ufs_lbn_t lblkno,  
     int expungetype /* BLK_SNAP or BLK_NOCOPY */)  
 {  
         struct inode *ip = VTOI(vp);  
         ufs1_daddr_t blkno, *blkp;  
         ufs_lbn_t lbn;  
         struct buf *ibp;  
         int error, ns;  
   
         ns = UFS_FSNEEDSWAP(fs);  
   
         for ( ; oldblkp < lastblkp; oldblkp++) {  
                 blkno = ufs_rw32(*oldblkp, ns);  
                 if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)  
                         continue;  
                 lbn = fragstoblks(fs, blkno);  
                 if (lbn < NDADDR) {  
                         blkp = &ip->i_ffs1_db[lbn];  
                         ip->i_flag |= IN_CHANGE | IN_UPDATE;  
                 } else {  
                         error = ffs_balloc(vp, lblktosize(fs, (off_t)lbn),  
                             fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);  
                         if (error)  
                                 return (error);  
                         blkp = &((ufs1_daddr_t *)(ibp->b_data))  
                             [(lbn - NDADDR) % NINDIR(fs)];  
                 }  
                 /*  
                  * If we are expunging a snapshot vnode and we  
                  * find a block marked BLK_NOCOPY, then it is  
                  * one that has been allocated to this snapshot after  
                  * we took our current snapshot and can be ignored.  
                  */  
                 blkno = ufs_rw32(*blkp, ns);  
                 if (expungetype == BLK_SNAP && blkno == BLK_NOCOPY) {  
                         if (lbn >= NDADDR)  
                                 brelse(ibp, 0);  
                 } else {  
                         if (blkno != 0)  
                                 panic("snapacct_ufs1: bad block");  
                         *blkp = ufs_rw32(expungetype, ns);  
                         if (lbn >= NDADDR)  
                                 bdwrite(ibp);  
                 }  
         }  
         return (0);  
 }  
   
 /*  
  * Account for a set of blocks allocated in a snapshot inode.  
  */  
 static int  
 mapacct_ufs1(struct vnode *vp, ufs1_daddr_t *oldblkp, ufs1_daddr_t *lastblkp,  
     struct fs *fs, ufs_lbn_t lblkno, int expungetype)  
 {  
         ufs1_daddr_t blkno;  
         struct inode *ip;  
         ino_t inum;  
         int acctit, ns;  
   
         ns = UFS_FSNEEDSWAP(fs);  
         ip = VTOI(vp);  
         inum = ip->i_number;  
         if (lblkno == -1)  
                 acctit = 0;  
         else  
                 acctit = 1;  
         for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {  
                 blkno = ufs_rw32(*oldblkp, ns);  
                 if (blkno == 0 || blkno == BLK_NOCOPY)  
                         continue;  
                 if (acctit && expungetype == BLK_SNAP && blkno != BLK_SNAP)  
                         *ip->i_snapblklist++ = lblkno;  
                 if (blkno == BLK_SNAP)  
                         blkno = blkstofrags(fs, lblkno);  
                 ffs_blkfree(fs, vp, blkno, fs->fs_bsize, inum);  
         }  
         return (0);  
 }  
   
 /*  
  * Before expunging a snapshot inode, note all the  
  * blocks that it claims with BLK_SNAP so that fsck will  
  * be able to account for those blocks properly and so  
  * that this snapshot knows that it need not copy them  
  * if the other snapshot holding them is freed. This code  
  * is reproduced once each for UFS1 and UFS2.  
  */  
 static int  
 expunge_ufs2(struct vnode *snapvp, struct inode *cancelip, struct fs *fs,  
     int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,  
                     struct fs *, ufs_lbn_t, int),  
     int expungetype)  
 {  
         int i, error, ns;  
         ufs_lbn_t lbn, rlbn;  
         ufs2_daddr_t len, blkno, numblks, blksperindir;  
         struct ufs2_dinode *dip;  
         struct buf *bp;  
   
         ns = UFS_FSNEEDSWAP(fs);  
         /*  
          * Prepare to expunge the inode. If its inode block has not  
          * yet been copied, then allocate and fill the copy.  
          */  
         lbn = fragstoblks(fs, ino_to_fsba(fs, cancelip->i_number));  
         error = snapblkaddr(snapvp, lbn, &blkno);  
         if (error)  
                 return error;  
         if (blkno != 0) {  
                 error = bread(snapvp, lbn, fs->fs_bsize, KERNCRED,  
                     B_MODIFY, &bp);  
         } else {          } else {
                 error = ffs_balloc(snapvp, lblktosize(fs, (off_t)lbn),                  dip2 = (struct ufs2_dinode *)bp->b_data +
                     fs->fs_bsize, KERNCRED, 0, &bp);                      ino_to_fsbo(fs, cancelip->i_number);
                 if (! error)                  if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)
                         error = rwfsblk(snapvp, B_READ, bp->b_data, lbn);                          dip2->di_mode = 0;
                 }                  dip2->di_size = 0;
         if (error)                  dip2->di_blocks = 0;
                 return error;                  dip2->di_flags =
         /*                      ufs_rw32(ufs_rw32(dip2->di_flags, ns) & ~SF_SNAPSHOT, ns);
          * Set a snapshot inode to be a zero length file, regular files                  bzero(&dip2->di_db[0], (NDADDR + NIADDR) * sizeof(int64_t));
          * or unlinked snapshots to be completely unallocated.          }
          */  
         dip = (struct ufs2_dinode *)bp->b_data +  
             ino_to_fsbo(fs, cancelip->i_number);  
         if (expungetype == BLK_NOCOPY || cancelip->i_ffs_effnlink == 0)  
                 dip->di_mode = 0;  
         dip->di_size = 0;  
         dip->di_blocks = 0;  
         dip->di_flags =  
             ufs_rw32(ufs_rw32(dip->di_flags, ns) & ~SF_SNAPSHOT, ns);  
         bzero(&dip->di_db[0], (NDADDR + NIADDR) * sizeof(ufs2_daddr_t));  
         bdwrite(bp);          bdwrite(bp);
         /*          /*
          * Now go through and expunge all the blocks in the file           * Now go through and expunge all the blocks in the file
          * using the function requested.           * using the function requested.
          */           */
         numblks = howmany(cancelip->i_size, fs->fs_bsize);          numblks = howmany(cancelip->i_size, fs->fs_bsize);
         if ((error = (*acctfunc)(snapvp, &cancelip->i_ffs2_db[0],          if (fs->fs_magic == FS_UFS1_MAGIC)
             &cancelip->i_ffs2_db[NDADDR], fs, 0, expungetype)))                  bap = &cancelip->i_ffs1_db[0];
           else
                   bap = &cancelip->i_ffs2_db[0];
           if ((error = (*acctfunc)(snapvp, bap, 0, NDADDR, fs, 0, expungetype)))
                 return (error);                  return (error);
         if ((error = (*acctfunc)(snapvp, &cancelip->i_ffs2_ib[0],          if (fs->fs_magic == FS_UFS1_MAGIC)
             &cancelip->i_ffs2_ib[NIADDR], fs, -1, expungetype)))                  bap = &cancelip->i_ffs1_ib[0];
           else
                   bap = &cancelip->i_ffs2_ib[0];
           if ((error = (*acctfunc)(snapvp, bap, 0, NIADDR, fs, -1, expungetype)))
                 return (error);                  return (error);
         blksperindir = 1;          blksperindir = 1;
         lbn = -NDADDR;          lbn = -NDADDR;
         len = numblks - NDADDR;          len = numblks - NDADDR;
         rlbn = NDADDR;          rlbn = NDADDR;
         for (i = 0; len > 0 && i < NIADDR; i++) {          for (i = 0; len > 0 && i < NIADDR; i++) {
                 error = indiracct_ufs2(snapvp, ITOV(cancelip), i,                  error = indiracct(snapvp, ITOV(cancelip), i,
                     ufs_rw64(cancelip->i_ffs2_ib[i], ns), lbn, rlbn, len,                      ib_get(cancelip, i), lbn, rlbn, len,
                     blksperindir, fs, acctfunc, expungetype);                      blksperindir, fs, acctfunc, expungetype);
                 if (error)                  if (error)
                         return (error);                          return (error);
Line 1218  expunge_ufs2(struct vnode *snapvp, struc
Line 952  expunge_ufs2(struct vnode *snapvp, struc
  * its indirect blocks in snapvp.   * its indirect blocks in snapvp.
  */   */
 static int  static int
 indiracct_ufs2(struct vnode *snapvp, struct vnode *cancelvp, int level,  indiracct(struct vnode *snapvp, struct vnode *cancelvp, int level,
     ufs2_daddr_t blkno, ufs_lbn_t lbn, ufs_lbn_t rlbn, ufs_lbn_t remblks,      daddr_t blkno, daddr_t lbn, daddr_t rlbn, daddr_t remblks,
     ufs_lbn_t blksperindir, struct fs *fs,      daddr_t blksperindir, struct fs *fs, acctfunc_t acctfunc, int expungetype)
     int (*acctfunc)(struct vnode *, ufs2_daddr_t *, ufs2_daddr_t *,  
                     struct fs *, ufs_lbn_t, int),  
     int expungetype)  
 {  {
         int error, ns, num, i;          int error, num, i;
         ufs_lbn_t subblksperindir;          daddr_t subblksperindir;
         struct indir indirs[NIADDR + 2];          struct indir indirs[NIADDR + 2];
         ufs2_daddr_t last, *bap;          daddr_t last;
           void *bap;
         struct buf *bp;          struct buf *bp;
   
         ns = UFS_FSNEEDSWAP(fs);  
   
         if (blkno == 0) {          if (blkno == 0) {
                 if (expungetype == BLK_NOCOPY)                  if (expungetype == BLK_NOCOPY)
                         return (0);                          return (0);
                 panic("indiracct_ufs2: missing indir");                  panic("indiracct: missing indir");
         }          }
         if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)          if ((error = ufs_getlbns(cancelvp, rlbn, indirs, &num)) != 0)
                 return (error);                  return (error);
         if (lbn != indirs[num - 1 - level].in_lbn || num < 2)          if (lbn != indirs[num - 1 - level].in_lbn || num < 2)
                 panic("indiracct_ufs2: botched params");                  panic("indiracct: botched params");
         /*          /*
          * We have to expand bread here since it will deadlock looking           * We have to expand bread here since it will deadlock looking
          * up the block number for any blocks that are not in the cache.           * up the block number for any blocks that are not in the cache.
Line 1264  indiracct_ufs2(struct vnode *snapvp, str
Line 994  indiracct_ufs2(struct vnode *snapvp, str
         bap = malloc(fs->fs_bsize, M_DEVBUF, M_WAITOK);          bap = malloc(fs->fs_bsize, M_DEVBUF, M_WAITOK);
         bcopy(bp->b_data, (void *)bap, fs->fs_bsize);          bcopy(bp->b_data, (void *)bap, fs->fs_bsize);
         brelse(bp, 0);          brelse(bp, 0);
         error = (*acctfunc)(snapvp, &bap[0], &bap[last], fs,          error = (*acctfunc)(snapvp, bap, 0, last,
             level == 0 ? rlbn : -1, expungetype);              fs, level == 0 ? rlbn : -1, expungetype);
         if (error || level == 0)          if (error || level == 0)
                 goto out;                  goto out;
         /*          /*
Line 1274  indiracct_ufs2(struct vnode *snapvp, str
Line 1004  indiracct_ufs2(struct vnode *snapvp, str
          */           */
         subblksperindir = blksperindir / NINDIR(fs);          subblksperindir = blksperindir / NINDIR(fs);
         for (lbn++, level--, i = 0; i < last; i++) {          for (lbn++, level--, i = 0; i < last; i++) {
                 error = indiracct_ufs2(snapvp, cancelvp, level,                  error = indiracct(snapvp, cancelvp, level,
                     ufs_rw64(bap[i], ns), lbn, rlbn, remblks, subblksperindir,                      idb_get(VTOI(snapvp), bap, i), lbn, rlbn, remblks,
                     fs, acctfunc, expungetype);                      subblksperindir, fs, acctfunc, expungetype);
                 if (error)                  if (error)
                         goto out;                          goto out;
                 rlbn += blksperindir;                  rlbn += blksperindir;
Line 1292  out:
Line 1022  out:
  * Do both snap accounting and map accounting.   * Do both snap accounting and map accounting.
  */   */
 static int  static int
 fullacct_ufs2(struct vnode *vp, ufs2_daddr_t *oldblkp, ufs2_daddr_t *lastblkp,  fullacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp,
     struct fs *fs, ufs_lbn_t lblkno,      struct fs *fs, daddr_t lblkno,
     int exptype /* BLK_SNAP or BLK_NOCOPY */)      int exptype /* BLK_SNAP or BLK_NOCOPY */)
 {  {
         int error;          int error;
   
         if ((error = snapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype)))          if ((error = snapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype)))
                 return (error);                  return (error);
         return (mapacct_ufs2(vp, oldblkp, lastblkp, fs, lblkno, exptype));          return (mapacct(vp, bap, oldblkp, lastblkp, fs, lblkno, exptype));
 }  }
   
 /*  /*
  * Identify a set of blocks allocated in a snapshot inode.   * Identify a set of blocks allocated in a snapshot inode.
  */   */
 static int  static int
 snapacct_ufs2(struct vnode *vp, ufs2_daddr_t *oldblkp, ufs2_daddr_t *lastblkp,  snapacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp,
     struct fs *fs, ufs_lbn_t lblkno,      struct fs *fs, daddr_t lblkno,
     int expungetype /* BLK_SNAP or BLK_NOCOPY */)      int expungetype /* BLK_SNAP or BLK_NOCOPY */)
 {  {
         struct inode *ip = VTOI(vp);          struct inode *ip = VTOI(vp);
         ufs2_daddr_t blkno, *blkp;          daddr_t blkno;
         ufs_lbn_t lbn;          daddr_t lbn;
         struct buf *ibp;          struct buf *ibp;
         int error, ns;          int error;
   
         ns = UFS_FSNEEDSWAP(fs);  
   
         for ( ; oldblkp < lastblkp; oldblkp++) {          for ( ; oldblkp < lastblkp; oldblkp++) {
                 blkno = ufs_rw64(*oldblkp, ns);                  blkno = idb_get(ip, bap, oldblkp);
                 if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)                  if (blkno == 0 || blkno == BLK_NOCOPY || blkno == BLK_SNAP)
                         continue;                          continue;
                 lbn = fragstoblks(fs, blkno);                  lbn = fragstoblks(fs, blkno);
                 if (lbn < NDADDR) {                  if (lbn < NDADDR) {
                         blkp = &ip->i_ffs2_db[lbn];                          blkno = db_get(ip, lbn);
                         ip->i_flag |= IN_CHANGE | IN_UPDATE;                          ip->i_flag |= IN_CHANGE | IN_UPDATE;
                 } else {                  } else {
                         error = ffs_balloc(vp, lblktosize(fs, (off_t)lbn),                          error = ffs_balloc(vp, lblktosize(fs, (off_t)lbn),
                             fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);                              fs->fs_bsize, KERNCRED, B_METAONLY, &ibp);
                         if (error)                          if (error)
                                 return (error);                                  return (error);
                         blkp = &((ufs2_daddr_t *)(ibp->b_data))                          blkno = idb_get(ip, ibp->b_data,
                             [(lbn - NDADDR) % NINDIR(fs)];                              (lbn - NDADDR) % NINDIR(fs));
                 }                  }
                 /*                  /*
                  * If we are expunging a snapshot vnode and we                   * If we are expunging a snapshot vnode and we
Line 1341  snapacct_ufs2(struct vnode *vp, ufs2_dad
Line 1069  snapacct_ufs2(struct vnode *vp, ufs2_dad
                  * one that has been allocated to this snapshot after                   * one that has been allocated to this snapshot after
                  * we took our current snapshot and can be ignored.                   * we took our current snapshot and can be ignored.
                  */                   */
                 blkno = ufs_rw64(*blkp, ns);  
                 if (expungetype == BLK_SNAP && blkno == BLK_NOCOPY) {                  if (expungetype == BLK_SNAP && blkno == BLK_NOCOPY) {
                         if (lbn >= NDADDR)                          if (lbn >= NDADDR)
                                 brelse(ibp, 0);                                  brelse(ibp, 0);
                 } else {                  } else {
                         if (blkno != 0)                          if (blkno != 0)
                                 panic("snapacct_ufs2: bad block");                                  panic("snapacct: bad block");
                         *blkp = ufs_rw64(expungetype, ns);                          if (lbn < NDADDR)
                         if (lbn >= NDADDR)                                  db_assign(ip, lbn, expungetype);
                           else {
                                   idb_assign(ip, ibp->b_data,
                                       (lbn - NDADDR) % NINDIR(fs), expungetype);
                                 bdwrite(ibp);                                  bdwrite(ibp);
                           }
                 }                  }
         }          }
         return (0);          return (0);
Line 1360  snapacct_ufs2(struct vnode *vp, ufs2_dad
Line 1091  snapacct_ufs2(struct vnode *vp, ufs2_dad
  * Account for a set of blocks allocated in a snapshot inode.   * Account for a set of blocks allocated in a snapshot inode.
  */   */
 static int  static int
 mapacct_ufs2(struct vnode *vp, ufs2_daddr_t *oldblkp, ufs2_daddr_t *lastblkp,  mapacct(struct vnode *vp, void *bap, int oldblkp, int lastblkp,
     struct fs *fs, ufs_lbn_t lblkno, int expungetype)      struct fs *fs, daddr_t lblkno, int expungetype)
 {  {
         ufs2_daddr_t blkno;          daddr_t blkno;
         struct inode *ip;          struct inode *ip;
         ino_t inum;          ino_t inum;
         int acctit, ns;          int acctit;
   
         ns = UFS_FSNEEDSWAP(fs);  
         ip = VTOI(vp);          ip = VTOI(vp);
         inum = ip->i_number;          inum = ip->i_number;
         if (lblkno == -1)          if (lblkno == -1)
Line 1376  mapacct_ufs2(struct vnode *vp, ufs2_dadd
Line 1106  mapacct_ufs2(struct vnode *vp, ufs2_dadd
         else          else
                 acctit = 1;                  acctit = 1;
         for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {          for ( ; oldblkp < lastblkp; oldblkp++, lblkno++) {
                 blkno = ufs_rw64(*oldblkp, ns);                  blkno = idb_get(ip, bap, oldblkp);
                 if (blkno == 0 || blkno == BLK_NOCOPY)                  if (blkno == 0 || blkno == BLK_NOCOPY)
                         continue;                          continue;
                 if (acctit && expungetype == BLK_SNAP && blkno != BLK_SNAP)                  if (acctit && expungetype == BLK_SNAP && blkno != BLK_SNAP)
Line 1452  ffs_snapremove(struct vnode *vp)
Line 1182  ffs_snapremove(struct vnode *vp)
         struct buf *ibp;          struct buf *ibp;
         struct snap_info *si;          struct snap_info *si;
         ufs2_daddr_t numblks, blkno, dblk;          ufs2_daddr_t numblks, blkno, dblk;
         int error, ns, loc, last;          int error, loc, last;
   
         si = VFSTOUFS(mp)->um_snapinfo;          si = VFSTOUFS(mp)->um_snapinfo;
         ns = UFS_FSNEEDSWAP(fs);  
         mutex_enter(&si->si_snaplock);          mutex_enter(&si->si_snaplock);
         /*          /*
          * If active, delete from incore list (this snapshot may           * If active, delete from incore list (this snapshot may
Line 1940  ffs_copyonwrite(void *v, struct buf *bp,
Line 1669  ffs_copyonwrite(void *v, struct buf *bp,
         void *saved_data = NULL;          void *saved_data = NULL;
         ufs2_daddr_t lbn, blkno, *snapblklist;          ufs2_daddr_t lbn, blkno, *snapblklist;
         uint32_t gen;          uint32_t gen;
         int lower, upper, mid, ns, snapshot_locked = 0, error = 0;          int lower, upper, mid, snapshot_locked = 0, error = 0;
   
         /*          /*
          * Check for valid snapshots.           * Check for valid snapshots.
Line 1958  ffs_copyonwrite(void *v, struct buf *bp,
Line 1687  ffs_copyonwrite(void *v, struct buf *bp,
          * By doing this check we avoid several potential deadlocks.           * By doing this check we avoid several potential deadlocks.
          */           */
         fs = ip->i_fs;          fs = ip->i_fs;
         ns = UFS_FSNEEDSWAP(fs);  
         lbn = fragstoblks(fs, dbtofsb(fs, bp->b_blkno));          lbn = fragstoblks(fs, dbtofsb(fs, bp->b_blkno));
         if (bp->b_blkno >= fsbtodb(fs, fs->fs_size)) {          if (bp->b_blkno >= fsbtodb(fs, fs->fs_size)) {
                 mutex_exit(&si->si_lock);                  mutex_exit(&si->si_lock);
Line 2285  db_assign(struct inode *ip, int loc, ufs
Line 2013  db_assign(struct inode *ip, int loc, ufs
 }  }
   
 static inline ufs2_daddr_t  static inline ufs2_daddr_t
   ib_get(struct inode *ip, int loc)
   {
           if (ip->i_ump->um_fstype == UFS1)
                   return ufs_rw32(ip->i_ffs1_ib[loc], UFS_IPNEEDSWAP(ip));
           else
                   return ufs_rw64(ip->i_ffs2_ib[loc], UFS_IPNEEDSWAP(ip));
   }
   
   static inline void
   ib_assign(struct inode *ip, int loc, ufs2_daddr_t val)
   {
           if (ip->i_ump->um_fstype == UFS1)
                   ip->i_ffs1_ib[loc] = ufs_rw32(val, UFS_IPNEEDSWAP(ip));
           else
                   ip->i_ffs2_ib[loc] = ufs_rw64(val, UFS_IPNEEDSWAP(ip));
   }
   
   static inline ufs2_daddr_t
 idb_get(struct inode *ip, void *bf, int loc)  idb_get(struct inode *ip, void *bf, int loc)
 {  {
         if (ip->i_ump->um_fstype == UFS1)          if (ip->i_ump->um_fstype == UFS1)

Legend:
Removed from v.1.75  
changed lines
  Added in v.1.76

CVSweb <webmaster@jp.NetBSD.org>