Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[XFS] fix uninitialised variable bug in dquot release

gcc on ARM warns about an using an uninitialised variable
in xfs_qm_dqrele_all_inodes(). This is a real bug, but gcc
on x86_64 is not reporting this warning so it went unnoticed.

Fix the bug by bring the inode radix tree walk code up to
date with xfs_sync_inodes_ag().

SGI-PV: 987246

Signed-off-by: Dave Chinner <david@fromorbit.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>

authored by

Dave Chinner and committed by
Lachlan McIlroy
cb4f0d1d d44dab8d

+24 -18
+24 -18
fs/xfs/quota/xfs_qm_syscalls.c
··· 1036 1036 int nr_found; 1037 1037 1038 1038 do { 1039 - boolean_t inode_refed; 1040 - struct inode *inode; 1041 - 1042 1039 /* 1043 1040 * use a gang lookup to find the next inode in the tree 1044 1041 * as the tree is sparse and a gang lookup walks to find ··· 1050 1053 break; 1051 1054 } 1052 1055 1053 - /* update the index for the next lookup */ 1056 + /* 1057 + * Update the index for the next lookup. Catch overflows 1058 + * into the next AG range which can occur if we have inodes 1059 + * in the last block of the AG and we are currently 1060 + * pointing to the last inode. 1061 + */ 1054 1062 first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); 1063 + if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) { 1064 + read_unlock(&pag->pag_ici_lock); 1065 + break; 1066 + } 1055 1067 1056 - /* skip quota inodes and those in reclaim */ 1057 - inode = VFS_I(ip); 1058 - if (!inode || ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { 1068 + /* skip quota inodes */ 1069 + if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { 1059 1070 ASSERT(ip->i_udquot == NULL); 1060 1071 ASSERT(ip->i_gdquot == NULL); 1061 1072 read_unlock(&pag->pag_ici_lock); 1062 1073 continue; 1063 1074 } 1064 - if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) { 1065 - inode = igrab(inode); 1075 + 1076 + /* 1077 + * If we can't get a reference on the inode, it must be 1078 + * in reclaim. Leave it for the reclaim code to flush. 1079 + */ 1080 + if (!igrab(VFS_I(ip))) { 1066 1081 read_unlock(&pag->pag_ici_lock); 1067 - if (!inode) 1068 - continue; 1069 - inode_refed = B_TRUE; 1070 - xfs_ilock(ip, XFS_ILOCK_EXCL); 1071 - } else { 1072 - read_unlock(&pag->pag_ici_lock); 1082 + continue; 1073 1083 } 1084 + read_unlock(&pag->pag_ici_lock); 1085 + 1086 + xfs_ilock(ip, XFS_ILOCK_EXCL); 1074 1087 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { 1075 1088 xfs_qm_dqrele(ip->i_udquot); 1076 1089 ip->i_udquot = NULL; ··· 1090 1083 xfs_qm_dqrele(ip->i_gdquot); 1091 1084 ip->i_gdquot = NULL; 1092 1085 } 1093 - xfs_iunlock(ip, XFS_ILOCK_EXCL); 1094 - if (inode_refed) 1095 - IRELE(ip); 1086 + xfs_iput(ip, XFS_ILOCK_EXCL); 1087 + 1096 1088 } while (nr_found); 1097 1089 } 1098 1090