diff options
Diffstat (limited to 'fs/xfs/quota/xfs_qm_syscalls.c')
-rw-r--r-- | fs/xfs/quota/xfs_qm_syscalls.c | 151 |
1 files changed, 77 insertions, 74 deletions
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 1a3b803dfa55..68139b38aede 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -127,7 +127,7 @@ xfs_qm_quotactl( | |||
127 | break; | 127 | break; |
128 | 128 | ||
129 | case Q_XQUOTASYNC: | 129 | case Q_XQUOTASYNC: |
130 | return (xfs_sync_inodes(mp, SYNC_DELWRI, NULL)); | 130 | return xfs_sync_inodes(mp, SYNC_DELWRI); |
131 | 131 | ||
132 | default: | 132 | default: |
133 | break; | 133 | break; |
@@ -1022,101 +1022,104 @@ 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 | */ |
1030 | void | 1027 | STATIC void |
1031 | xfs_qm_dqrele_all_inodes( | 1028 | xfs_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 | xfs_perag_t *pag = &mp->m_perag[ag]; |
1037 | struct inode *vp; | 1035 | int first_index = 0; |
1038 | boolean_t vnode_refd; | 1036 | int nr_found; |
1039 | 1037 | ||
1040 | ASSERT(mp->m_quotainfo); | ||
1041 | |||
1042 | XFS_MOUNT_ILOCK(mp); | ||
1043 | again: | ||
1044 | ip = mp->m_inodes; | ||
1045 | if (ip == NULL) { | ||
1046 | XFS_MOUNT_IUNLOCK(mp); | ||
1047 | return; | ||
1048 | } | ||
1049 | do { | 1038 | do { |
1050 | /* Skip markers inserted by xfs_sync */ | 1039 | /* |
1051 | if (ip->i_mount == NULL) { | 1040 | * use a gang lookup to find the next inode in the tree |
1052 | ip = ip->i_mnext; | 1041 | * as the tree is sparse and a gang lookup walks to find |
1053 | continue; | 1042 | * the number of objects requested. |
1043 | */ | ||
1044 | read_lock(&pag->pag_ici_lock); | ||
1045 | nr_found = radix_tree_gang_lookup(&pag->pag_ici_root, | ||
1046 | (void**)&ip, first_index, 1); | ||
1047 | |||
1048 | if (!nr_found) { | ||
1049 | read_unlock(&pag->pag_ici_lock); | ||
1050 | break; | ||
1054 | } | 1051 | } |
1055 | /* Root inode, rbmip and rsumip have associated blocks */ | 1052 | |
1053 | /* | ||
1054 | * Update the index for the next lookup. Catch overflows | ||
1055 | * into the next AG range which can occur if we have inodes | ||
1056 | * in the last block of the AG and we are currently | ||
1057 | * pointing to the last inode. | ||
1058 | */ | ||
1059 | first_index = XFS_INO_TO_AGINO(mp, ip->i_ino + 1); | ||
1060 | if (first_index < XFS_INO_TO_AGINO(mp, ip->i_ino)) { | ||
1061 | read_unlock(&pag->pag_ici_lock); | ||
1062 | break; | ||
1063 | } | ||
1064 | |||
1065 | /* skip quota inodes */ | ||
1056 | if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { | 1066 | if (ip == XFS_QI_UQIP(mp) || ip == XFS_QI_GQIP(mp)) { |
1057 | ASSERT(ip->i_udquot == NULL); | 1067 | ASSERT(ip->i_udquot == NULL); |
1058 | ASSERT(ip->i_gdquot == NULL); | 1068 | ASSERT(ip->i_gdquot == NULL); |
1059 | ip = ip->i_mnext; | 1069 | read_unlock(&pag->pag_ici_lock); |
1060 | continue; | 1070 | continue; |
1061 | } | 1071 | } |
1062 | vp = VFS_I(ip); | 1072 | |
1063 | if (!vp) { | 1073 | /* |
1064 | ASSERT(ip->i_udquot == NULL); | 1074 | * If we can't get a reference on the inode, it must be |
1065 | ASSERT(ip->i_gdquot == NULL); | 1075 | * in reclaim. Leave it for the reclaim code to flush. |
1066 | ip = ip->i_mnext; | 1076 | */ |
1077 | if (!igrab(VFS_I(ip))) { | ||
1078 | read_unlock(&pag->pag_ici_lock); | ||
1067 | continue; | 1079 | continue; |
1068 | } | 1080 | } |
1069 | vnode_refd = B_FALSE; | 1081 | read_unlock(&pag->pag_ici_lock); |
1070 | if (xfs_ilock_nowait(ip, XFS_ILOCK_EXCL) == 0) { | 1082 | |
1071 | ireclaims = mp->m_ireclaims; | 1083 | /* avoid new inodes though we shouldn't find any here */ |
1072 | topino = mp->m_inodes; | 1084 | if (xfs_iflags_test(ip, XFS_INEW)) { |
1073 | vp = vn_grab(vp); | 1085 | IRELE(ip); |
1074 | if (!vp) | 1086 | continue; |
1075 | goto again; | ||
1076 | |||
1077 | XFS_MOUNT_IUNLOCK(mp); | ||
1078 | /* XXX restart limit ? */ | ||
1079 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
1080 | vnode_refd = B_TRUE; | ||
1081 | } else { | ||
1082 | ireclaims = mp->m_ireclaims; | ||
1083 | topino = mp->m_inodes; | ||
1084 | XFS_MOUNT_IUNLOCK(mp); | ||
1085 | } | 1087 | } |
1086 | 1088 | ||
1087 | /* | 1089 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
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) { | 1090 | if ((flags & XFS_UQUOTA_ACCT) && ip->i_udquot) { |
1092 | xfs_qm_dqrele(ip->i_udquot); | 1091 | xfs_qm_dqrele(ip->i_udquot); |
1093 | ip->i_udquot = NULL; | 1092 | ip->i_udquot = NULL; |
1094 | } | 1093 | } |
1095 | if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && ip->i_gdquot) { | 1094 | if (flags & (XFS_PQUOTA_ACCT|XFS_GQUOTA_ACCT) && |
1095 | ip->i_gdquot) { | ||
1096 | xfs_qm_dqrele(ip->i_gdquot); | 1096 | xfs_qm_dqrele(ip->i_gdquot); |
1097 | ip->i_gdquot = NULL; | 1097 | ip->i_gdquot = NULL; |
1098 | } | 1098 | } |
1099 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 1099 | xfs_iput(ip, XFS_ILOCK_EXCL); |
1100 | /* | 1100 | |
1101 | * Wait until we've dropped the ilock and mountlock to | 1101 | } while (nr_found); |
1102 | * do the vn_rele. Or be condemned to an eternity in the | 1102 | } |
1103 | * inactive code in hell. | 1103 | |
1104 | */ | 1104 | /* |
1105 | if (vnode_refd) | 1105 | * Go thru all the inodes in the file system, releasing their dquots. |
1106 | IRELE(ip); | 1106 | * Note that the mount structure gets modified to indicate that quotas are off |
1107 | XFS_MOUNT_ILOCK(mp); | 1107 | * AFTER this, in the case of quotaoff. This also gets called from |
1108 | /* | 1108 | * xfs_rootumount. |
1109 | * If an inode was inserted or removed, we gotta | 1109 | */ |
1110 | * start over again. | 1110 | void |
1111 | */ | 1111 | xfs_qm_dqrele_all_inodes( |
1112 | if (topino != mp->m_inodes || mp->m_ireclaims != ireclaims) { | 1112 | struct xfs_mount *mp, |
1113 | /* XXX use a sentinel */ | 1113 | uint flags) |
1114 | goto again; | 1114 | { |
1115 | } | 1115 | int i; |
1116 | ip = ip->i_mnext; | ||
1117 | } while (ip != mp->m_inodes); | ||
1118 | 1116 | ||
1119 | XFS_MOUNT_IUNLOCK(mp); | 1117 | ASSERT(mp->m_quotainfo); |
1118 | for (i = 0; i < mp->m_sb.sb_agcount; i++) { | ||
1119 | if (!mp->m_perag[i].pag_ici_init) | ||
1120 | continue; | ||
1121 | xfs_qm_dqrele_inodes_ag(mp, i, flags); | ||
1122 | } | ||
1120 | } | 1123 | } |
1121 | 1124 | ||
1122 | /*------------------------------------------------------------------------*/ | 1125 | /*------------------------------------------------------------------------*/ |