[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.17.2.6 and 1.17.2.7

version 1.17.2.6, 2007/12/07 17:35:19 version 1.17.2.7, 2008/01/21 09:48:07
Line 78  __KERNEL_RCSID(0, "$NetBSD$");
Line 78  __KERNEL_RCSID(0, "$NetBSD$");
 #define ufs2_daddr_t    int64_t  #define ufs2_daddr_t    int64_t
 #define ufs_lbn_t       daddr_t  #define ufs_lbn_t       daddr_t
 #define VI_MTX(v)       (&(v)->v_interlock)  #define VI_MTX(v)       (&(v)->v_interlock)
 #define VI_LOCK(v)      simple_lock(&(v)->v_interlock)  #define VI_LOCK(v)      mutex_enter(&(v)->v_interlock)
 #define VI_UNLOCK(v)    simple_unlock(&(v)->v_interlock)  #define VI_UNLOCK(v)    mutex_exit(&(v)->v_interlock)
 #define MNT_ILOCK(v)    simple_lock(&mntvnode_slock)  #define MNT_ILOCK(v)    mutex_enter(&mntvnode_lock)
 #define MNT_IUNLOCK(v)  simple_unlock(&mntvnode_slock)  #define MNT_IUNLOCK(v)  mutex_exit(&mntvnode_lock)
   
 #if !defined(FFS_NO_SNAPSHOT)  #if !defined(FFS_NO_SNAPSHOT)
 static int cgaccount(int, struct vnode *, void *, int);  static int cgaccount(int, struct vnode *, void *, int);
Line 204  ffs_snapshot(struct mount *mp, struct vn
Line 204  ffs_snapshot(struct mount *mp, struct vn
 #else /* defined(FFS_NO_SNAPSHOT) */  #else /* defined(FFS_NO_SNAPSHOT) */
         ufs2_daddr_t numblks, blkno, *blkp, snaplistsize = 0, *snapblklist;          ufs2_daddr_t numblks, blkno, *blkp, snaplistsize = 0, *snapblklist;
         int error, ns, cg, snaploc;          int error, ns, cg, snaploc;
         int i, s, size, len, loc;          int i, size, len, loc;
         int flag = mp->mnt_flag;          int flag = mp->mnt_flag;
         struct timeval starttime;          struct timeval starttime;
 #ifdef DEBUG  #ifdef DEBUG
Line 220  ffs_snapshot(struct mount *mp, struct vn
Line 220  ffs_snapshot(struct mount *mp, struct vn
         struct inode *ip, *xp;          struct inode *ip, *xp;
         struct buf *bp, *ibp, *nbp;          struct buf *bp, *ibp, *nbp;
         struct vattr vat;          struct vattr vat;
         struct vnode *xvp, *nvp, *devvp;          struct vnode *xvp, *mvp, *devvp;
         struct snap_info *si;          struct snap_info *si;
   
         ns = UFS_FSNEEDSWAP(fs);          ns = UFS_FSNEEDSWAP(fs);
Line 252  ffs_snapshot(struct mount *mp, struct vn
Line 252  ffs_snapshot(struct mount *mp, struct vn
                 return EACCES;                  return EACCES;
   
         if (vp->v_size != 0) {          if (vp->v_size != 0) {
                 error = ffs_truncate(vp, 0, 0, NOCRED, l);                  error = ffs_truncate(vp, 0, 0, NOCRED);
                 if (error)                  if (error)
                         return error;                          return error;
         }          }
Line 426  ffs_snapshot(struct mount *mp, struct vn
Line 426  ffs_snapshot(struct mount *mp, struct vn
          */           */
         snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) +          snaplistsize = fs->fs_ncg + howmany(fs->fs_cssize, fs->fs_bsize) +
             FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */;              FSMAXSNAP + 1 /* superblock */ + 1 /* last block */ + 1 /* size */;
           /* Allocate a marker vnode */
           if ((mvp = vnalloc(mp)) == NULL) {
                   error = ENOMEM;
                   goto out1;
           }
         MNT_ILOCK(mp);          MNT_ILOCK(mp);
 loop:  
         /*          /*
          * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()           * NOTE: not using the TAILQ_FOREACH here since in this loop vgone()
          * and vclean() can be called indirectly           * and vclean() can be called indirectly
          */           */
         for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = nvp) {          for (xvp = TAILQ_FIRST(&mp->mnt_vnodelist); xvp; xvp = vunmark(mvp)) {
                   vmark(mvp, vp);
                 /*                  /*
                  * Make sure this vnode wasn't reclaimed in getnewvnode().                   * Make sure this vnode wasn't reclaimed in getnewvnode().
                  * Start over if it has (it won't be on the list anymore).                   * Start over if it has (it won't be on the list anymore).
                  */                   */
                 if (xvp->v_mount != mp)                  if (xvp->v_mount != mp || vismarker(xvp))
                         goto loop;                          continue;
                 VI_LOCK(xvp);                  VI_LOCK(xvp);
                 nvp = TAILQ_NEXT(xvp, v_mntvnodes);  
                 MNT_IUNLOCK(mp);  
                 if ((xvp->v_iflag & VI_XLOCK) ||                  if ((xvp->v_iflag & VI_XLOCK) ||
                     xvp->v_usecount == 0 || xvp->v_type == VNON ||                      xvp->v_usecount == 0 || xvp->v_type == VNON ||
                     (VTOI(xvp)->i_flags & SF_SNAPSHOT)) {                      (VTOI(xvp)->i_flags & SF_SNAPSHOT)) {
                         VI_UNLOCK(xvp);                          VI_UNLOCK(xvp);
                         MNT_ILOCK(mp);  
                         continue;                          continue;
                 }                  }
                   MNT_IUNLOCK(mp);
                   /*
                    * XXXAD should increase vnode ref count to prevent it
                    * disappearing or being recycled.
                    */
                 VI_UNLOCK(xvp);                  VI_UNLOCK(xvp);
 #ifdef DEBUG  #ifdef DEBUG
                 if (snapdebug)                  if (snapdebug)
Line 492  loop:
Line 499  loop:
                             xp->i_mode);                              xp->i_mode);
                 if (error) {                  if (error) {
                         free(copy_fs->fs_csp, M_UFSMNT);                          free(copy_fs->fs_csp, M_UFSMNT);
                           (void)vunmark(mvp);
                         goto out1;                          goto out1;
                 }                  }
                 MNT_ILOCK(mp);                  MNT_ILOCK(mp);
         }          }
         MNT_IUNLOCK(mp);          MNT_IUNLOCK(mp);
           vnfree(mvp);
         /*          /*
          * If there already exist snapshots on this filesystem, grab a           * If there already exist snapshots on this filesystem, grab a
          * reference to their shared lock. If this is the first snapshot           * reference to their shared lock. If this is the first snapshot
Line 702  out:
Line 711  out:
          * Clean all dirty buffers now to avoid UBC inconsistencies.           * Clean all dirty buffers now to avoid UBC inconsistencies.
          */           */
         if (!error) {          if (!error) {
                 simple_lock(&vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 error = VOP_PUTPAGES(vp, 0, 0,                  error = VOP_PUTPAGES(vp, 0, 0,
                     PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);                      PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);
         }          }
         if (!error) {          if (!error) {
                 s = splbio();                  mutex_enter(&bufcache_lock);
                 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {                  for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
                         nbp = LIST_NEXT(bp, b_vnbufs);                          nbp = LIST_NEXT(bp, b_vnbufs);
                         simple_lock(&bp->b_interlock);                          bp->b_cflags |= BC_BUSY|BC_VFLUSH;
                         splx(s);  
                         if ((bp->b_flags & (B_DELWRI|B_BUSY)) != B_DELWRI)  
                                 panic("ffs_snapshot: not dirty or busy, bp %p",  
                                     bp);  
                         bp->b_flags |= B_BUSY|B_VFLUSH;  
                         if (LIST_FIRST(&bp->b_dep) == NULL)                          if (LIST_FIRST(&bp->b_dep) == NULL)
                                 bp->b_flags |= B_NOCACHE;                                  bp->b_cflags |= BC_NOCACHE;
                         simple_unlock(&bp->b_interlock);                          mutex_exit(&bufcache_lock);
                         bwrite(bp);                          bwrite(bp);
                         s = splbio();                          mutex_enter(&bufcache_lock);
                 }                  }
                 simple_lock(&global_v_numoutput_slock);                  mutex_exit(&bufcache_lock);
                 while (vp->v_numoutput) {  
                         vp->v_iflag |= VI_BWAIT;                  mutex_enter(&vp->v_interlock);
                         ltsleep((void *)&vp->v_numoutput, PRIBIO+1,                  while (vp->v_numoutput > 0)
                             "snapflushbuf", 0, &global_v_numoutput_slock);                          cv_wait(&vp->v_cv, &vp->v_interlock);
                 }                  mutex_exit(&vp->v_interlock);
                 simple_unlock(&global_v_numoutput_slock);  
                 splx(s);  
         }          }
         if (sbbuf)          if (sbbuf)
                 free(sbbuf, M_UFSMNT);                  free(sbbuf, M_UFSMNT);
Line 739  out:
Line 741  out:
         }          }
         mp->mnt_flag = flag;          mp->mnt_flag = flag;
         if (error)          if (error)
                 (void) ffs_truncate(vp, (off_t)0, 0, NOCRED, l);                  (void) ffs_truncate(vp, (off_t)0, 0, NOCRED);
         else          else
                 vref(vp);                  vref(vp);
         return (error);          return (error);
Line 958  indiracct_ufs1(struct vnode *snapvp, str
Line 960  indiracct_ufs1(struct vnode *snapvp, str
          */           */
         bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);          bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);
         bp->b_blkno = fsbtodb(fs, blkno);          bp->b_blkno = fsbtodb(fs, blkno);
         if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&          if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 &&
             (error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) {              (error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) {
                 brelse(bp, 0);                  brelse(bp, 0);
                 return (error);                  return (error);
Line 1226  indiracct_ufs2(struct vnode *snapvp, str
Line 1228  indiracct_ufs2(struct vnode *snapvp, str
          */           */
         bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);          bp = getblk(cancelvp, lbn, fs->fs_bsize, 0, 0);
         bp->b_blkno = fsbtodb(fs, blkno);          bp->b_blkno = fsbtodb(fs, blkno);
         if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0 &&          if ((bp->b_oflags & (BO_DONE | BO_DELWRI)) == 0 &&
             (error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) {              (error = readfsblk(bp->b_vp, bp->b_data, fragstoblks(fs, blkno)))) {
                 brelse(bp, 0);                  brelse(bp, 0);
                 return (error);                  return (error);
Line 2063  readfsblk(struct vnode *vp, void *data, 
Line 2065  readfsblk(struct vnode *vp, void *data, 
         struct fs *fs = ip->i_fs;          struct fs *fs = ip->i_fs;
         struct buf *nbp;          struct buf *nbp;
   
         nbp = getiobuf();          nbp = getiobuf(NULL, true);
         nbp->b_flags = B_READ;          nbp->b_flags = B_READ;
         nbp->b_bcount = nbp->b_bufsize = fs->fs_bsize;          nbp->b_bcount = nbp->b_bufsize = fs->fs_bsize;
         nbp->b_error = 0;          nbp->b_error = 0;
Line 2071  readfsblk(struct vnode *vp, void *data, 
Line 2073  readfsblk(struct vnode *vp, void *data, 
         nbp->b_blkno = nbp->b_rawblkno = fsbtodb(fs, blkstofrags(fs, lbn));          nbp->b_blkno = nbp->b_rawblkno = fsbtodb(fs, blkstofrags(fs, lbn));
         nbp->b_proc = NULL;          nbp->b_proc = NULL;
         nbp->b_dev = ip->i_devvp->v_rdev;          nbp->b_dev = ip->i_devvp->v_rdev;
         nbp->b_vp = NULLVP;  
   
         bdev_strategy(nbp);          bdev_strategy(nbp);
   
Line 2101  readvnblk(struct vnode *vp, void *data, 
Line 2102  readvnblk(struct vnode *vp, void *data, 
   
         if (bn != (daddr_t)-1) {          if (bn != (daddr_t)-1) {
                 offset = dbtob(bn);                  offset = dbtob(bn);
                 simple_lock(&vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 error = VOP_PUTPAGES(vp, trunc_page(offset),                  error = VOP_PUTPAGES(vp, trunc_page(offset),
                     round_page(offset+fs->fs_bsize),                      round_page(offset+fs->fs_bsize),
                     PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);                      PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);
Line 2131  writevnblk(struct vnode *vp, void *data,
Line 2132  writevnblk(struct vnode *vp, void *data,
   
         offset = lblktosize(fs, (off_t)lbn);          offset = lblktosize(fs, (off_t)lbn);
         s = cow_enter();          s = cow_enter();
         simple_lock(&vp->v_interlock);          mutex_enter(&vp->v_interlock);
         error = VOP_PUTPAGES(vp, trunc_page(offset),          error = VOP_PUTPAGES(vp, trunc_page(offset),
             round_page(offset+fs->fs_bsize), PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);              round_page(offset+fs->fs_bsize), PGO_CLEANIT|PGO_SYNCIO|PGO_FREE);
         if (error == 0)          if (error == 0)
Line 2142  writevnblk(struct vnode *vp, void *data,
Line 2143  writevnblk(struct vnode *vp, void *data,
                 return error;                  return error;
   
         bcopy(data, bp->b_data, fs->fs_bsize);          bcopy(data, bp->b_data, fs->fs_bsize);
         bp->b_flags |= B_NOCACHE;          mutex_enter(&bufcache_lock);
           /* XXX Shouldn't need to lock for this, NOCACHE is only read later. */
           bp->b_cflags |= BC_NOCACHE;
           mutex_exit(&bufcache_lock);
   
         return bwrite(bp);          return bwrite(bp);
 }  }

Legend:
Removed from v.1.17.2.6  
changed lines
  Added in v.1.17.2.7

CVSweb <webmaster@jp.NetBSD.org>