Diff for /xfs-linux/xfs_inode.c between versions 1.453 and 1.454

version 1.453, 2006/11/07 14:39:38 version 1.454, 2006/11/07 14:40:26
Line 2741  xfs_iunpin( Line 2741  xfs_iunpin(
 {  {
         ASSERT(atomic_read(&ip->i_pincount) > 0);          ASSERT(atomic_read(&ip->i_pincount) > 0);
   
         if (atomic_dec_and_test(&ip->i_pincount)) {          if (atomic_dec_and_lock(&ip->i_pincount, &ip->i_flags_lock)) {
   
                 /*                  /*
                  * If the inode is currently being reclaimed, the                   * If the inode is currently being reclaimed, the link between
                  * linux inode _and_ the xfs vnode may have been                   * the bhv_vnode and the xfs_inode will be broken after the
                  * freed so we cannot reference either of them safely.                   * XFS_IRECLAIM* flag is set. Hence, if these flags are not
                  * Hence we should not try to do anything to them                   * set, then we can move forward and mark the linux inode dirty
                  * if the xfs inode is currently in the reclaim                   * knowing that it is still valid as it won't freed until after
                  * path.                   * the bhv_vnode<->xfs_inode link is broken in xfs_reclaim. The
                    * i_flags_lock is used to synchronise the setting of the
                    * XFS_IRECLAIM* flags and the breaking of the link, and so we
                    * can execute atomically w.r.t to reclaim by holding this lock
                    * here.
                  *                   *
                  * However, we still need to issue the unpin wakeup                   * However, we still need to issue the unpin wakeup call as the
                  * call as the inode reclaim may be blocked waiting for                   * inode reclaim may be blocked waiting for the inode to become
                  * the inode to become unpinned.                   * unpinned.
                  */                   */
                 struct inode *inode = NULL;  
   
                 spin_lock(&ip->i_flags_lock);  
                 if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) {                  if (!__xfs_iflags_test(ip, XFS_IRECLAIM|XFS_IRECLAIMABLE)) {
                         bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);                          bhv_vnode_t     *vp = XFS_ITOV_NULL(ip);
                           struct inode *inode = NULL;
   
                         /* make sync come back and flush this inode */                          BUG_ON(vp == NULL);
                         if (vp) {                          inode = vn_to_inode(vp);
                                 inode = vn_to_inode(vp);                          BUG_ON(inode->i_state & I_CLEAR);
   
                                 if (!(inode->i_state &                          /* make sync come back and flush this inode */
                                                 (I_NEW|I_FREEING|I_CLEAR))) {                          if (!(inode->i_state & (I_NEW|I_FREEING)))
                                         inode = igrab(inode);                                  mark_inode_dirty_sync(inode);
                                         if (inode)  
                                                 mark_inode_dirty_sync(inode);  
                                 } else  
                                         inode = NULL;  
                         }  
                 }                  }
                 spin_unlock(&ip->i_flags_lock);                  spin_unlock(&ip->i_flags_lock);
                 wake_up(&ip->i_ipin_wait);                  wake_up(&ip->i_ipin_wait);
                 if (inode)  
                         iput(inode);  
         }          }
 }  }
   

Removed from v.1.453  
changed lines
  Added in v.1.454


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