Browse Source

[XFS] Avoid using inodes that haven't been completely initialised

The radix tree walks in xfs_sync_inodes_ag and xfs_qm_dqrele_all_inodes()
can find inodes that are still undergoing initialisation. Avoid
them by checking for the the XFS_INEW() flag once we have a reference
on the inode. This flag is cleared once the inode is properly initialised.

SGI-PV: 987246

Signed-off-by: Dave Chinner <david@fromorbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Dave Chinner 17 years ago
parent
commit
6307091fe6
3 changed files with 9 additions and 3 deletions
  1. 0 1
      fs/xfs/linux-2.6/xfs_iops.c
  2. 3 2
      fs/xfs/linux-2.6/xfs_sync.c
  3. 6 0
      fs/xfs/quota/xfs_qm_syscalls.c

+ 0 - 1
fs/xfs/linux-2.6/xfs_iops.c

@@ -780,7 +780,6 @@ xfs_setup_inode(
 	inode->i_ino = ip->i_ino;
 	inode->i_state = I_NEW|I_LOCK;
 	inode_add_to_lists(ip->i_mount->m_super, inode);
-	ASSERT(atomic_read(&inode->i_count) == 1);
 
 	inode->i_mode	= ip->i_d.di_mode;
 	inode->i_nlink	= ip->i_d.di_nlink;

+ 3 - 2
fs/xfs/linux-2.6/xfs_sync.c

@@ -117,8 +117,9 @@ xfs_sync_inodes_ag(
 		}
 		read_unlock(&pag->pag_ici_lock);
 
-		/* bad inodes are dealt with elsewhere */
-		if (is_bad_inode(inode)) {
+		/* avoid new or bad inodes */
+		if (is_bad_inode(inode) ||
+		    xfs_iflags_test(ip, XFS_INEW)) {
 			IRELE(ip);
 			continue;
 		}

+ 6 - 0
fs/xfs/quota/xfs_qm_syscalls.c

@@ -1080,6 +1080,12 @@ xfs_qm_dqrele_inodes_ag(
 		}
 		read_unlock(&pag->pag_ici_lock);
 
+		/* avoid new inodes though we shouldn't find any here */
+		if (xfs_iflags_test(ip, XFS_INEW)) {
+			IRELE(ip);
+			continue;
+		}
+
 		xfs_ilock(ip, XFS_ILOCK_EXCL);
 		if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
 			xfs_qm_dqrele(ip->i_udquot);