aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/quota/xfs_qm_syscalls.c
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 02:08:03 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 02:08:03 -0400
commit5b4d89ae0f5ae45c7fa1dfc616fd2bb8634bb7b7 (patch)
tree3dd6c2d0fc0072a822692fc3ea2a9e6cc8a6f5f5 /fs/xfs/quota/xfs_qm_syscalls.c
parent683a897080a053733778b36398186cb1b22c377f (diff)
[XFS] Traverse inode trees when releasing dquots
Make releasing all inode dquots traverse the per-ag inode radix trees rather than the mount inode list. This removes another user of the mount inode list. Version 3 o fix comment relating to avoiding trying to release the quota inodes and those in reclaim. Version 2 o add comment explaining use of gang lookups for a single inode o use IRELE, not VN_RELE o move check for ag initialisation to caller. SGI-PV: 988139 SGI-Modid: xfs-linux-melb:xfs-kern:32291a Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs/quota/xfs_qm_syscalls.c')
-rw-r--r--fs/xfs/quota/xfs_qm_syscalls.c127
1 files changed, 59 insertions, 68 deletions
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c
index 1a3b803dfa55..26152b9ccc6f 100644
--- a/fs/xfs/quota/xfs_qm_syscalls.c
+++ b/fs/xfs/quota/xfs_qm_syscalls.c
@@ -1022,101 +1022,92 @@ xfs_qm_export_flags(
1022 1022
1023 1023
1024/* 1024/*
1025 * Go thru all the inodes in the file system, releasing their dquots. 1025 * Release all the dquots on the inodes in an AG.
1026 * Note that the mount structure gets modified to indicate that quotas are off
1027 * AFTER this, in the case of quotaoff. This also gets called from
1028 * xfs_rootumount.
1029 */ 1026 */
1030void 1027STATIC void
1031xfs_qm_dqrele_all_inodes( 1028xfs_qm_dqrele_inodes_ag(
1032 struct xfs_mount *mp, 1029 xfs_mount_t *mp,
1033 uint flags) 1030 int ag,
1031 uint flags)
1034{ 1032{
1035 xfs_inode_t *ip, *topino; 1033 xfs_inode_t *ip = NULL;
1036 uint ireclaims; 1034 struct inode *vp = NULL;
1037 struct inode *vp; 1035 xfs_perag_t *pag = &mp->m_perag[ag];
1038 boolean_t vnode_refd; 1036 int first_index = 0;
1037 int nr_found;
1039 1038
1040 ASSERT(mp->m_quotainfo);
1041
1042 XFS_MOUNT_ILOCK(mp);
1043again:
1044 ip = mp->m_inodes;
1045 if (ip == NULL) {
1046 XFS_MOUNT_IUNLOCK(mp);
1047 return;
1048 }
1049 do { 1039 do {
1050 /* Skip markers inserted by xfs_sync */ 1040 boolean_t vnode_refd = B_FALSE;
1051 if (ip->i_mount == NULL) { 1041
1052 ip = ip->i_mnext; 1042 /*
1053 continue; 1043 * use a gang lookup to find the next inode in the tree
1054 } 1044 * as the tree is sparse and a gang lookup walks to find
1055 /* Root inode, rbmip and rsumip have associated blocks */ 1045 * the number of objects requested.
1056 if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { 1046 */
1057 ASSERT(ip->i_udquot == NULL); 1047 read_lock(&pag->pag_ici_lock);
1058 ASSERT(ip->i_gdquot == NULL); 1048 nr_found = radix_tree_gang_lookup(&pag->pag_ici_root,
1059 ip = ip->i_mnext; 1049 (void**)&ip, first_index, 1);
1060 continue; 1050
1051 if (!nr_found) {
1052 read_unlock(&pag->pag_ici_lock);
1053 break;
1061 } 1054 }
1055
1056 /* update the index for the next lookup */
1057 first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1);
1058
1059 /* skip quota inodes and those in reclaim */
1062 vp = VFS_I(ip); 1060 vp = VFS_I(ip);
1063 if (!vp) { 1061 if (!vp || ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) {
1064 ASSERT(ip->i_udquot == NULL); 1062 ASSERT(ip->i_udquot == NULL);
1065 ASSERT(ip->i_gdquot == NULL); 1063 ASSERT(ip->i_gdquot == NULL);
1066 ip = ip->i_mnext; 1064 read_unlock(&pag->pag_ici_lock);
1067 continue; 1065 continue;
1068 } 1066 }
1069 vnode_refd = B_FALSE;
1070 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) { 1067 if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) {
1071 ireclaims = mp->m_ireclaims;
1072 topino = mp->m_inodes;
1073 vp = vn_grab(vp); 1068 vp = vn_grab(vp);
1069 read_unlock(&pag->pag_ici_lock);
1074 if (!vp) 1070 if (!vp)
1075 goto again; 1071 continue;
1076
1077 XFS_MOUNT_IUNLOCK(mp);
1078 /* XXX restart limit ? */
1079 xfs_ilock(ip, XFS_ILOCK_EXCL);
1080 vnode_refd = B_TRUE; 1072 vnode_refd = B_TRUE;
1073 xfs_ilock(ip, XFS_ILOCK_EXCL);
1081 } else { 1074 } else {
1082 ireclaims = mp->m_ireclaims; 1075 read_unlock(&pag->pag_ici_lock);
1083 topino = mp->m_inodes;
1084 XFS_MOUNT_IUNLOCK(mp);
1085 } 1076 }
1086
1087 /*
1088 * We don't keep the mountlock across the dqrele() call,
1089 * since it can take a while..
1090 */
1091 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { 1077 if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) {
1092 xfs_qm_dqrele(ip->i_udquot); 1078 xfs_qm_dqrele(ip->i_udquot);
1093 ip->i_udquot = NULL; 1079 ip->i_udquot = NULL;
1094 } 1080 }
1095 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { 1081 if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) &&
1082 ip->i_gdquot) {
1096 xfs_qm_dqrele(ip->i_gdquot); 1083 xfs_qm_dqrele(ip->i_gdquot);
1097 ip->i_gdquot = NULL; 1084 ip->i_gdquot = NULL;
1098 } 1085 }
1099 xfs_iunlock(ip, XFS_ILOCK_EXCL); 1086 xfs_iunlock(ip, XFS_ILOCK_EXCL);
1100 /*
1101 * Wait until we've dropped the ilock and mountlock to
1102 * do the vn_rele. Or be condemned to an eternity in the
1103 * inactive code in hell.
1104 */
1105 if (vnode_refd) 1087 if (vnode_refd)
1106 IRELE(ip); 1088 IRELE(ip);
1107 XFS_MOUNT_ILOCK(mp); 1089 } while (nr_found);
1108 /* 1090}
1109 * If an inode was inserted or removed, we gotta
1110 * start over again.
1111 */
1112 if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) {
1113 /* XXX use a sentinel */
1114 goto again;
1115 }
1116 ip = ip->i_mnext;
1117 } while (ip != mp->m_inodes);
1118 1091
1119 XFS_MOUNT_IUNLOCK(mp); 1092/*
1093 * Go thru all the inodes in the file system, releasing their dquots.
1094 * Note that the mount structure gets modified to indicate that quotas are off
1095 * AFTER this, in the case of quotaoff. This also gets called from
1096 * xfs_rootumount.
1097 */
1098void
1099xfs_qm_dqrele_all_inodes(
1100 struct xfs_mount *mp,
1101 uint flags)
1102{
1103 int i;
1104
1105 ASSERT(mp->m_quotainfo);
1106 for (i = 0; i < mp->m_sb.sb_agcount; i++) {
1107 if (!mp->m_perag[i].pag_ici_init)
1108 continue;
1109 xfs_qm_dqrele_inodes_ag(mp, i, flags);
1110 }
1120} 1111}
1121 1112
1122/*------------------------------------------------------------------------*/ 1113/*------------------------------------------------------------------------*/