[BACK]Return to ffs_vnops.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_vnops.c between version 1.113.4.5 and 1.114

version 1.113.4.5, 2011/05/31 03:05:13 version 1.114, 2010/03/29 13:11:33
Line 175  const struct vnodeopv_entry_desc ffs_spe
Line 175  const struct vnodeopv_entry_desc ffs_spe
         { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */          { &vop_kqfilter_desc, spec_kqfilter },          /* kqfilter */
         { &vop_revoke_desc, spec_revoke },              /* revoke */          { &vop_revoke_desc, spec_revoke },              /* revoke */
         { &vop_mmap_desc, spec_mmap },                  /* mmap */          { &vop_mmap_desc, spec_mmap },                  /* mmap */
         { &vop_fsync_desc, ffs_spec_fsync },            /* fsync */          { &vop_fsync_desc, ffs_fsync },                 /* fsync */
         { &vop_seek_desc, spec_seek },                  /* seek */          { &vop_seek_desc, spec_seek },                  /* seek */
         { &vop_remove_desc, spec_remove },              /* remove */          { &vop_remove_desc, spec_remove },              /* remove */
         { &vop_link_desc, spec_link },                  /* link */          { &vop_link_desc, spec_link },                  /* link */
Line 266  const struct vnodeopv_desc ffs_fifoop_op
Line 266  const struct vnodeopv_desc ffs_fifoop_op
 #include <ufs/ufs/ufs_readwrite.c>  #include <ufs/ufs/ufs_readwrite.c>
   
 int  int
 ffs_spec_fsync(void *v)  
 {  
         struct vop_fsync_args /* {  
                 struct vnode *a_vp;  
                 kauth_cred_t a_cred;  
                 int a_flags;  
                 off_t a_offlo;  
                 off_t a_offhi;  
                 struct lwp *a_l;  
         } */ *ap = v;  
         int error, flags, uflags;  
         struct vnode *vp;  
         struct mount *mp;  
   
         flags = ap->a_flags;  
         uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);  
         vp = ap->a_vp;  
         mp = vp->v_mount;  
   
         fstrans_start(mp, FSTRANS_LAZY);  
   
         error = spec_fsync(v);  
         if (error)  
                 goto out;  
   
 #ifdef WAPBL  
         if (mp && mp->mnt_wapbl) {  
                 /*  
                  * Don't bother writing out metadata if the syncer is  
                  * making the request.  We will let the sync vnode  
                  * write it out in a single burst through a call to  
                  * VFS_SYNC().  
                  */  
                 if ((flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0)  
                         goto out;  
                 if ((VTOI(vp)->i_flag & (IN_ACCESS | IN_CHANGE | IN_UPDATE  
                     | IN_MODIFY | IN_MODIFIED | IN_ACCESSED)) != 0) {  
                         error = UFS_WAPBL_BEGIN(mp);  
                         if (error != 0)  
                                 goto out;  
                         error = ffs_update(vp, NULL, NULL, uflags);  
                         UFS_WAPBL_END(mp);  
                 }  
                 goto out;  
         }  
 #endif /* WAPBL */  
   
         error = ffs_update(vp, NULL, NULL, uflags);  
   
 out:  
         fstrans_done(mp);  
         return error;  
 }  
   
 int  
 ffs_fsync(void *v)  ffs_fsync(void *v)
 {  {
         struct vop_fsync_args /* {          struct vop_fsync_args /* {
Line 337  ffs_fsync(void *v)
Line 282  ffs_fsync(void *v)
         int bsize;          int bsize;
         daddr_t blk_high;          daddr_t blk_high;
         struct vnode *vp;          struct vnode *vp;
   #ifdef WAPBL
         struct mount *mp;          struct mount *mp;
   #endif
   
         vp = ap->a_vp;          vp = ap->a_vp;
         mp = vp->v_mount;  
   
         fstrans_start(mp, FSTRANS_LAZY);          fstrans_start(vp->v_mount, FSTRANS_LAZY);
         if ((ap->a_offlo == 0 && ap->a_offhi == 0) || (vp->v_type != VREG)) {          if ((ap->a_offlo == 0 && ap->a_offhi == 0) || (vp->v_type != VREG)) {
                 error = ffs_full_fsync(vp, ap->a_flags);                  error = ffs_full_fsync(vp, ap->a_flags);
                 goto out;                  goto out;
         }          }
   
         bsize = mp->mnt_stat.f_iosize;          bsize = vp->v_mount->mnt_stat.f_iosize;
         blk_high = ap->a_offhi / bsize;          blk_high = ap->a_offhi / bsize;
         if (ap->a_offhi % bsize != 0)          if (ap->a_offhi % bsize != 0)
                 blk_high++;                  blk_high++;
Line 357  ffs_fsync(void *v)
Line 303  ffs_fsync(void *v)
          * First, flush all pages in range.           * First, flush all pages in range.
          */           */
   
         mutex_enter(vp->v_interlock);          mutex_enter(&vp->v_interlock);
         error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),          error = VOP_PUTPAGES(vp, trunc_page(ap->a_offlo),
             round_page(ap->a_offhi), PGO_CLEANIT |              round_page(ap->a_offhi), PGO_CLEANIT |
             ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0));              ((ap->a_flags & FSYNC_WAIT) ? PGO_SYNCIO : 0));
Line 366  ffs_fsync(void *v)
Line 312  ffs_fsync(void *v)
         }          }
   
 #ifdef WAPBL  #ifdef WAPBL
         KASSERT(vp->v_type == VREG);          mp = wapbl_vptomp(vp);
         if (mp->mnt_wapbl) {          if (mp->mnt_wapbl) {
                 /*                  /*
                  * Don't bother writing out metadata if the syncer is                   * Don't bother writing out metadata if the syncer is
Line 375  ffs_fsync(void *v)
Line 321  ffs_fsync(void *v)
                  * VFS_SYNC().                   * VFS_SYNC().
                  */                   */
                 if ((ap->a_flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) {                  if ((ap->a_flags & (FSYNC_DATAONLY | FSYNC_LAZY)) != 0) {
                         fstrans_done(mp);                          fstrans_done(vp->v_mount);
                         return 0;                          return 0;
                 }                  }
                 error = 0;                  error = 0;
Line 384  ffs_fsync(void *v)
Line 330  ffs_fsync(void *v)
                                  IN_MODIFIED | IN_ACCESSED)) {                                   IN_MODIFIED | IN_ACCESSED)) {
                         error = UFS_WAPBL_BEGIN(mp);                          error = UFS_WAPBL_BEGIN(mp);
                         if (error) {                          if (error) {
                                 fstrans_done(mp);                                  fstrans_done(vp->v_mount);
                                 return error;                                  return error;
                         }                          }
                         error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |                          error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
Line 392  ffs_fsync(void *v)
Line 338  ffs_fsync(void *v)
                         UFS_WAPBL_END(mp);                          UFS_WAPBL_END(mp);
                 }                  }
                 if (error || (ap->a_flags & FSYNC_NOLOG) != 0) {                  if (error || (ap->a_flags & FSYNC_NOLOG) != 0) {
                         fstrans_done(mp);                          fstrans_done(vp->v_mount);
                         return error;                          return error;
                 }                  }
                 error = wapbl_flush(mp->mnt_wapbl, 0);                  error = wapbl_flush(mp->mnt_wapbl, 0);
                 fstrans_done(mp);                  fstrans_done(vp->v_mount);
                 return error;                  return error;
         }          }
 #endif /* WAPBL */  #endif /* WAPBL */
Line 426  ffs_fsync(void *v)
Line 372  ffs_fsync(void *v)
         }          }
   
         if (ap->a_flags & FSYNC_WAIT) {          if (ap->a_flags & FSYNC_WAIT) {
                 mutex_enter(vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 while (vp->v_numoutput > 0)                  while (vp->v_numoutput > 0)
                         cv_wait(&vp->v_cv, vp->v_interlock);                          cv_wait(&vp->v_cv, &vp->v_interlock);
                 mutex_exit(vp->v_interlock);                  mutex_exit(&vp->v_interlock);
         }          }
   
         error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |          error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
Line 443  ffs_fsync(void *v)
Line 389  ffs_fsync(void *v)
         }          }
   
 out:  out:
         fstrans_done(mp);          fstrans_done(vp->v_mount);
         return error;          return error;
 }  }
   
Line 454  out:
Line 400  out:
 int  int
 ffs_full_fsync(struct vnode *vp, int flags)  ffs_full_fsync(struct vnode *vp, int flags)
 {  {
         int error, i, uflags;          struct buf *bp, *nbp;
           int error, passes, skipmeta, waitfor, i;
         struct mount *mp;          struct mount *mp;
   
         KASSERT(vp->v_tag == VT_UFS);  
         KASSERT(VTOI(vp) != NULL);          KASSERT(VTOI(vp) != NULL);
         KASSERT(vp->v_type != VCHR && vp->v_type != VBLK);          KASSERT(vp->v_tag == VT_UFS);
   
         error = 0;          error = 0;
         uflags = UPDATE_CLOSE | ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0);  
   
         mp = vp->v_mount;          mp = vp->v_mount;
           if (vp->v_type == VBLK && vp->v_specmountpoint != NULL) {
                   mp = vp->v_specmountpoint;
           } else {
                   mp = vp->v_mount;
           }
   
         /*          /*
          * Flush all dirty data associated with the vnode.           * Flush all dirty data associated with the vnode.
          */           */
         if (vp->v_type == VREG) {          if (vp->v_type == VREG || vp->v_type == VBLK) {
                 int pflags = PGO_ALLPAGES | PGO_CLEANIT;                  int pflags = PGO_ALLPAGES | PGO_CLEANIT;
   
                 if ((flags & FSYNC_WAIT))                  if ((flags & FSYNC_WAIT))
                         pflags |= PGO_SYNCIO;                          pflags |= PGO_SYNCIO;
                 if (fstrans_getstate(mp) == FSTRANS_SUSPENDING)                  if (vp->v_type == VREG &&
                       fstrans_getstate(mp) == FSTRANS_SUSPENDING)
                         pflags |= PGO_FREE;                          pflags |= PGO_FREE;
                 mutex_enter(vp->v_interlock);                  mutex_enter(&vp->v_interlock);
                 error = VOP_PUTPAGES(vp, 0, 0, pflags);                  error = VOP_PUTPAGES(vp, 0, 0, pflags);
                 if (error)                  if (error)
                         return error;                          return error;
         }          }
   
 #ifdef WAPBL  #ifdef WAPBL
           mp = wapbl_vptomp(vp);
         if (mp && mp->mnt_wapbl) {          if (mp && mp->mnt_wapbl) {
                 /*                  /*
                  * Don't bother writing out metadata if the syncer is                   * Don't bother writing out metadata if the syncer is
Line 498  ffs_full_fsync(struct vnode *vp, int fla
Line 450  ffs_full_fsync(struct vnode *vp, int fla
                         error = UFS_WAPBL_BEGIN(mp);                          error = UFS_WAPBL_BEGIN(mp);
                         if (error)                          if (error)
                                 return error;                                  return error;
                         error = ffs_update(vp, NULL, NULL, uflags);                          error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE |
                               ((flags & FSYNC_WAIT) ? UPDATE_WAIT : 0));
                         UFS_WAPBL_END(mp);                          UFS_WAPBL_END(mp);
                 }                  }
                 if (error || (flags & FSYNC_NOLOG) != 0)                  if (error || (flags & FSYNC_NOLOG) != 0)
Line 515  ffs_full_fsync(struct vnode *vp, int fla
Line 468  ffs_full_fsync(struct vnode *vp, int fla
                 }                  }
   
                 if ((flags & FSYNC_WAIT) != 0) {                  if ((flags & FSYNC_WAIT) != 0) {
                         mutex_enter(vp->v_interlock);                          mutex_enter(&vp->v_interlock);
                         while (vp->v_numoutput != 0)                          while (vp->v_numoutput != 0)
                                 cv_wait(&vp->v_cv, vp->v_interlock);                                  cv_wait(&vp->v_cv, &vp->v_interlock);
                         mutex_exit(vp->v_interlock);                          mutex_exit(&vp->v_interlock);
                 }                  }
   
                 return error;                  return error;
         }          }
 #endif /* WAPBL */  #endif /* WAPBL */
   
         error = vflushbuf(vp, (flags & FSYNC_WAIT) != 0);          /*
         if (error == 0)           * Write out metadata for non-logging file systems. XXX This block
                 error = ffs_update(vp, NULL, NULL, uflags);           * should be simplified now that softdep is gone.
            */
           passes = NIADDR + 1;
           skipmeta = 0;
           if (flags & FSYNC_WAIT)
                   skipmeta = 1;
   
   loop:
           mutex_enter(&bufcache_lock);
           LIST_FOREACH(bp, &vp->v_dirtyblkhd, b_vnbufs) {
                   bp->b_cflags &= ~BC_SCANNED;
           }
           for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp; bp = nbp) {
                   nbp = LIST_NEXT(bp, b_vnbufs);
                   if (bp->b_cflags & (BC_BUSY | BC_SCANNED))
                           continue;
                   if ((bp->b_oflags & BO_DELWRI) == 0)
                           panic("ffs_fsync: not dirty");
                   if (skipmeta && bp->b_lblkno < 0)
                           continue;
                   bp->b_cflags |= BC_BUSY | BC_VFLUSH | BC_SCANNED;
                   mutex_exit(&bufcache_lock);
                   /*
                    * On our final pass through, do all I/O synchronously
                    * so that we can find out if our flush is failing
                    * because of write errors.
                    */
                   if (passes > 0 || !(flags & FSYNC_WAIT))
                           (void) bawrite(bp);
                   else if ((error = bwrite(bp)) != 0)
                           return (error);
                   /*
                    * Since we unlocked during the I/O, we need
                    * to start from a known point.
                    */
                   mutex_enter(&bufcache_lock);
                   nbp = LIST_FIRST(&vp->v_dirtyblkhd);
           }
           mutex_exit(&bufcache_lock);
           if (skipmeta) {
                   skipmeta = 0;
                   goto loop;
           }
   
           if ((flags & FSYNC_WAIT) != 0) {
                   mutex_enter(&vp->v_interlock);
                   while (vp->v_numoutput) {
                           cv_wait(&vp->v_cv, &vp->v_interlock);
                   }
                   mutex_exit(&vp->v_interlock);
   
                   /*
                    * Ensure that any filesystem metadata associated
                    * with the vnode has been written.
                    */
                   if (!LIST_EMPTY(&vp->v_dirtyblkhd)) {
                           /*
                           * Block devices associated with filesystems may
                           * have new I/O requests posted for them even if
                           * the vnode is locked, so no amount of trying will
                           * get them clean. Thus we give block devices a
                           * good effort, then just give up. For all other file
                           * types, go around and try again until it is clean.
                           */
                           if (passes > 0) {
                                   passes--;
                                   goto loop;
                           }
   #ifdef DIAGNOSTIC
                           if (vp->v_type != VBLK)
                                   vprint("ffs_fsync: dirty", vp);
   #endif
                   }
           }
   
           waitfor = (flags & FSYNC_WAIT) ? UPDATE_WAIT : 0;
           error = ffs_update(vp, NULL, NULL, UPDATE_CLOSE | waitfor);
   
         if (error == 0 && (flags & FSYNC_CACHE) != 0) {          if (error == 0 && (flags & FSYNC_CACHE) != 0) {
                 i = 1;  
                 (void)VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE,                  (void)VOP_IOCTL(VTOI(vp)->i_devvp, DIOCCACHESYNC, &i, FWRITE,
                     kauth_cred_get());                      kauth_cred_get());
         }          }
Line 555  ffs_reclaim(void *v)
Line 584  ffs_reclaim(void *v)
         int error;          int error;
   
         fstrans_start(mp, FSTRANS_LAZY);          fstrans_start(mp, FSTRANS_LAZY);
         /*  
          * The inode must be freed and updated before being removed  
          * from its hash chain.  Other threads trying to gain a hold  
          * on the inode will be stalled because it is locked (VI_XLOCK).  
          */  
         error = UFS_WAPBL_BEGIN(mp);  
         if (error) {  
                 fstrans_done(mp);  
                 return error;  
         }  
         if (ip->i_nlink <= 0 && ip->i_omode != 0 &&  
             (vp->v_mount->mnt_flag & MNT_RDONLY) == 0)  
                 ffs_vfree(vp, ip->i_number, ip->i_omode);  
         UFS_WAPBL_END(mp);  
         if ((error = ufs_reclaim(vp)) != 0) {          if ((error = ufs_reclaim(vp)) != 0) {
                 fstrans_done(mp);                  fstrans_done(mp);
                 return (error);                  return (error);
Line 583  ffs_reclaim(void *v)
Line 598  ffs_reclaim(void *v)
          * To interlock with ffs_sync().           * To interlock with ffs_sync().
          */           */
         genfs_node_destroy(vp);          genfs_node_destroy(vp);
         mutex_enter(vp->v_interlock);          mutex_enter(&vp->v_interlock);
         data = vp->v_data;          data = vp->v_data;
         vp->v_data = NULL;          vp->v_data = NULL;
         mutex_exit(vp->v_interlock);          mutex_exit(&vp->v_interlock);
   
         /*          /*
          * XXX MFS ends up here, too, to free an inode.  Should we create           * XXX MFS ends up here, too, to free an inode.  Should we create

Legend:
Removed from v.1.113.4.5  
changed lines
  Added in v.1.114

CVSweb <webmaster@jp.NetBSD.org>