Diff for /xfs-linux/xfs_vfsops.c between versions 1.536 and 1.537

version 1.536, 2007/08/24 16:18:10 version 1.537, 2007/09/10 15:51:42
Line 981  xfs_sync_inodes( Line 981  xfs_sync_inodes(
         int             *bypassed)          int             *bypassed)
 {  {
         xfs_inode_t     *ip = NULL;          xfs_inode_t     *ip = NULL;
         xfs_inode_t     *ip_next;  
         xfs_buf_t       *bp;  
         bhv_vnode_t     *vp = NULL;          bhv_vnode_t     *vp = NULL;
         int             error;          int             error;
         int             last_error;          int             last_error;
Line 992  xfs_sync_inodes( Line 990  xfs_sync_inodes(
         boolean_t       mount_locked;          boolean_t       mount_locked;
         boolean_t       vnode_refed;          boolean_t       vnode_refed;
         int             preempt;          int             preempt;
         xfs_dinode_t    *dip;  
         xfs_iptr_t      *ipointer;          xfs_iptr_t      *ipointer;
 #ifdef DEBUG  #ifdef DEBUG
         boolean_t       ipointer_in = B_FALSE;          boolean_t       ipointer_in = B_FALSE;
Line 1045  xfs_sync_inodes( Line 1042  xfs_sync_inodes(
   
 #define XFS_PREEMPT_MASK        0x7f  #define XFS_PREEMPT_MASK        0x7f
   
           ASSERT(!(flags & SYNC_BDFLUSH));
   
         if (bypassed)          if (bypassed)
                 *bypassed = 0;                  *bypassed = 0;
         if (mp->m_flags & XFS_MOUNT_RDONLY)          if (mp->m_flags & XFS_MOUNT_RDONLY)
Line 1057  xfs_sync_inodes( Line 1056  xfs_sync_inodes(
         ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);          ipointer = (xfs_iptr_t *)kmem_zalloc(sizeof(xfs_iptr_t), KM_SLEEP);
   
         fflag = XFS_B_ASYNC;            /* default is don't wait */          fflag = XFS_B_ASYNC;            /* default is don't wait */
         if (flags & (SYNC_BDFLUSH | SYNC_DELWRI))          if (flags & SYNC_DELWRI)
                 fflag = XFS_B_DELWRI;                  fflag = XFS_B_DELWRI;
         if (flags & SYNC_WAIT)          if (flags & SYNC_WAIT)
                 fflag = 0;              /* synchronous overrides all */                  fflag = 0;              /* synchronous overrides all */
Line 1147  xfs_sync_inodes( Line 1146  xfs_sync_inodes(
                 }                  }
   
                 /*                  /*
                  * If this is just vfs_sync() or pflushd() calling  
                  * then we can skip inodes for which it looks like  
                  * there is nothing to do.  Since we don't have the  
                  * inode locked this is racy, but these are periodic  
                  * calls so it doesn't matter.  For the others we want  
                  * to know for sure, so we at least try to lock them.  
                  */  
                 if (flags & SYNC_BDFLUSH) {  
                         if (((ip->i_itemp == NULL) ||  
                              !(ip->i_itemp->ili_format.ilf_fields &  
                                XFS_ILOG_ALL)) &&  
                             (ip->i_update_core == 0)) {  
                                 ip = ip->i_mnext;  
                                 continue;  
                         }  
                 }  
   
                 /*  
                  * Try to lock without sleeping.  We're out of order with                   * Try to lock without sleeping.  We're out of order with
                  * the inode list lock here, so if we fail we need to drop                   * the inode list lock here, so if we fail we need to drop
                  * the mount lock and try again.  If we're called from                   * the mount lock and try again.  If we're called from
Line 1181  xfs_sync_inodes( Line 1162  xfs_sync_inodes(
                  * it.                   * it.
                  */                   */
                 if (xfs_ilock_nowait(ip, lock_flags) == 0) {                  if (xfs_ilock_nowait(ip, lock_flags) == 0) {
                         if ((flags & SYNC_BDFLUSH) || (vp == NULL)) {                          if (vp == NULL) {
                                 ip = ip->i_mnext;                                  ip = ip->i_mnext;
                                 continue;                                  continue;
                         }                          }
Line 1242  xfs_sync_inodes( Line 1223  xfs_sync_inodes(
                         xfs_ilock(ip, XFS_ILOCK_SHARED);                          xfs_ilock(ip, XFS_ILOCK_SHARED);
                 }                  }
   
                 if (flags & SYNC_BDFLUSH) {                  if ((flags & SYNC_ATTR) &&
                         if ((flags & SYNC_ATTR) &&                      (ip->i_update_core ||
                             ((ip->i_update_core) ||                       (ip->i_itemp && ip->i_itemp->ili_format.ilf_fields))) {
                              ((ip->i_itemp != NULL) &&                          if (mount_locked)
                               (ip->i_itemp->ili_format.ilf_fields != 0)))) {                                  IPOINTER_INSERT(ip, mp);
   
                                 /* Insert marker and drop lock if not already  
                                  * done.  
                                  */  
                                 if (mount_locked) {  
                                         IPOINTER_INSERT(ip, mp);  
                                 }  
   
                                 /*  
                                  * We don't want the periodic flushing of the  
                                  * inodes by vfs_sync() to interfere with  
                                  * I/O to the file, especially read I/O  
                                  * where it is only the access time stamp  
                                  * that is being flushed out.  To prevent  
                                  * long periods where we have both inode  
                                  * locks held shared here while reading the  
                                  * inode's buffer in from disk, we drop the  
                                  * inode lock while reading in the inode  
                                  * buffer.  We have to release the buffer  
                                  * and reacquire the inode lock so that they  
                                  * are acquired in the proper order (inode  
                                  * locks first).  The buffer will go at the  
                                  * end of the lru chain, though, so we can  
                                  * expect it to still be there when we go  
                                  * for it again in xfs_iflush().  
                                  */  
                                 if ((xfs_ipincount(ip) == 0) &&  
                                     xfs_iflock_nowait(ip)) {  
   
                                         xfs_ifunlock(ip);  
                                         xfs_iunlock(ip, XFS_ILOCK_SHARED);  
   
                                         error = xfs_itobp(mp, NULL, ip,  
                                                           &dip, &bp, 0, 0);  
                                         if (!error) {  
                                                 xfs_buf_relse(bp);  
                                         } else {  
                                                 /* Bailing out, remove the  
                                                  * marker and free it.  
                                                  */  
                                                 XFS_MOUNT_ILOCK(mp);  
                                                 IPOINTER_REMOVE(ip, mp);  
                                                 XFS_MOUNT_IUNLOCK(mp);  
   
                                                 ASSERT(!(lock_flags &  
                                                         XFS_IOLOCK_SHARED));  
   
                                                 kmem_free(ipointer,  
                                                         sizeof(xfs_iptr_t));  
                                                 return (0);  
                                         }  
   
                                         /*  
                                          * Since we dropped the inode lock,  
                                          * the inode may have been reclaimed.  
                                          * Therefore, we reacquire the mount  
                                          * lock and check to see if we were the  
                                          * inode reclaimed. If this happened  
                                          * then the ipointer marker will no  
                                          * longer point back at us. In this  
                                          * case, move ip along to the inode  
                                          * after the marker, remove the marker  
                                          * and continue.  
                                          */  
                                         XFS_MOUNT_ILOCK(mp);  
                                         mount_locked = B_TRUE;  
   
                                         if (ip != ipointer->ip_mprev) {  
                                                 IPOINTER_REMOVE(ip, mp);  
   
                                                 ASSERT(!vnode_refed);  
                                                 ASSERT(!(lock_flags &  
                                                         XFS_IOLOCK_SHARED));  
                                                 continue;  
                                         }  
   
                                         ASSERT(ip->i_mount == mp);  
   
                                         if (xfs_ilock_nowait(ip,  
                                                     XFS_ILOCK_SHARED) == 0) {  
                                                 ASSERT(ip->i_mount == mp);  
                                                 /*  
                                                  * We failed to reacquire  
                                                  * the inode lock without  
                                                  * sleeping, so just skip  
                                                  * the inode for now.  We  
                                                  * clear the ILOCK bit from  
                                                  * the lock_flags so that we  
                                                  * won't try to drop a lock  
                                                  * we don't hold below.  
                                                  */  
                                                 lock_flags &= ~XFS_ILOCK_SHARED;  
                                                 IPOINTER_REMOVE(ip_next, mp);  
                                         } else if ((xfs_ipincount(ip) == 0) &&  
                                                    xfs_iflock_nowait(ip)) {  
                                                 ASSERT(ip->i_mount == mp);  
                                                 /*  
                                                  * Since this is vfs_sync()  
                                                  * calling we only flush the  
                                                  * inode out if we can lock  
                                                  * it without sleeping and  
                                                  * it is not pinned.  Drop  
                                                  * the mount lock here so  
                                                  * that we don't hold it for  
                                                  * too long. We already have  
                                                  * a marker in the list here.  
                                                  */  
                                                 XFS_MOUNT_IUNLOCK(mp);  
                                                 mount_locked = B_FALSE;  
                                                 error = xfs_iflush(ip,  
                                                            XFS_IFLUSH_DELWRI);  
                                         } else {  
                                                 ASSERT(ip->i_mount == mp);  
                                                 IPOINTER_REMOVE(ip_next, mp);  
                                         }  
                                 }  
   
                         }  
   
                 } else {                          if (flags & SYNC_WAIT) {
                         if ((flags & SYNC_ATTR) &&                                  xfs_iflock(ip);
                             ((ip->i_update_core) ||                                  error = xfs_iflush(ip, XFS_IFLUSH_SYNC);
                              ((ip->i_itemp != NULL) &&  
                               (ip->i_itemp->ili_format.ilf_fields != 0)))) {  
                                 if (mount_locked) {  
                                         IPOINTER_INSERT(ip, mp);  
                                 }  
   
                                 if (flags & SYNC_WAIT) {                          /*
                                         xfs_iflock(ip);                           * If we can't acquire the flush lock, then the inode
                                         error = xfs_iflush(ip,                           * is already being flushed so don't bother waiting.
                                                            XFS_IFLUSH_SYNC);                           *
                                 } else {                           * If we can lock it then do a delwri flush so we can
                                         /*                           * combine multiple inode flushes in each disk write.
                                          * If we can't acquire the flush                           */
                                          * lock, then the inode is already                          } else if (xfs_iflock_nowait(ip)) {
                                          * being flushed so don't bother                                  error = xfs_iflush(ip, XFS_IFLUSH_DELWRI);
                                          * waiting.  If we can lock it then                          } else if (bypassed) {
                                          * do a delwri flush so we can                                  (*bypassed)++;
                                          * combine multiple inode flushes  
                                          * in each disk write.  
                                          */  
                                         if (xfs_iflock_nowait(ip)) {  
                                                 error = xfs_iflush(ip,  
                                                            XFS_IFLUSH_DELWRI);  
                                         }  
                                         else if (bypassed)  
                                                 (*bypassed)++;  
                                 }  
                         }                          }
                 }                  }
   

Removed from v.1.536  
changed lines
  Added in v.1.537


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>