diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 32 | ||||
-rw-r--r-- | fs/xfs/libxfs/xfs_sb.c | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_fsops.c | 9 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 192 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_super.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.c | 16 |
8 files changed, 134 insertions, 131 deletions
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 61ec015dca16..e39c9e83670e 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c | |||
@@ -2212,9 +2212,8 @@ xfs_bmap_add_extent_delay_real( | |||
2212 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - | 2212 | diff = (int)(temp + temp2 - startblockval(PREV.br_startblock) - |
2213 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); | 2213 | (bma->cur ? bma->cur->bc_private.b.allocated : 0)); |
2214 | if (diff > 0) { | 2214 | if (diff > 0) { |
2215 | error = xfs_icsb_modify_counters(bma->ip->i_mount, | 2215 | error = xfs_mod_fdblocks(bma->ip->i_mount, |
2216 | XFS_SBS_FDBLOCKS, | 2216 | -((int64_t)diff), false); |
2217 | -((int64_t)diff), 0); | ||
2218 | ASSERT(!error); | 2217 | ASSERT(!error); |
2219 | if (error) | 2218 | if (error) |
2220 | goto done; | 2219 | goto done; |
@@ -2265,9 +2264,8 @@ xfs_bmap_add_extent_delay_real( | |||
2265 | temp += bma->cur->bc_private.b.allocated; | 2264 | temp += bma->cur->bc_private.b.allocated; |
2266 | ASSERT(temp <= da_old); | 2265 | ASSERT(temp <= da_old); |
2267 | if (temp < da_old) | 2266 | if (temp < da_old) |
2268 | xfs_icsb_modify_counters(bma->ip->i_mount, | 2267 | xfs_mod_fdblocks(bma->ip->i_mount, |
2269 | XFS_SBS_FDBLOCKS, | 2268 | (int64_t)(da_old - temp), false); |
2270 | (int64_t)(da_old - temp), 0); | ||
2271 | } | 2269 | } |
2272 | 2270 | ||
2273 | /* clear out the allocated field, done with it now in any case. */ | 2271 | /* clear out the allocated field, done with it now in any case. */ |
@@ -2944,8 +2942,8 @@ xfs_bmap_add_extent_hole_delay( | |||
2944 | } | 2942 | } |
2945 | if (oldlen != newlen) { | 2943 | if (oldlen != newlen) { |
2946 | ASSERT(oldlen > newlen); | 2944 | ASSERT(oldlen > newlen); |
2947 | xfs_icsb_modify_counters(ip->i_mount, XFS_SBS_FDBLOCKS, | 2945 | xfs_mod_fdblocks(ip->i_mount, (int64_t)(oldlen - newlen), |
2948 | (int64_t)(oldlen - newlen), 0); | 2946 | false); |
2949 | /* | 2947 | /* |
2950 | * Nothing to do for disk quota accounting here. | 2948 | * Nothing to do for disk quota accounting here. |
2951 | */ | 2949 | */ |
@@ -4163,15 +4161,13 @@ xfs_bmapi_reserve_delalloc( | |||
4163 | error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, | 4161 | error = xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, |
4164 | -((int64_t)extsz), 0); | 4162 | -((int64_t)extsz), 0); |
4165 | } else { | 4163 | } else { |
4166 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 4164 | error = xfs_mod_fdblocks(mp, -((int64_t)alen), false); |
4167 | -((int64_t)alen), 0); | ||
4168 | } | 4165 | } |
4169 | 4166 | ||
4170 | if (error) | 4167 | if (error) |
4171 | goto out_unreserve_quota; | 4168 | goto out_unreserve_quota; |
4172 | 4169 | ||
4173 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 4170 | error = xfs_mod_fdblocks(mp, -((int64_t)indlen), false); |
4174 | -((int64_t)indlen), 0); | ||
4175 | if (error) | 4171 | if (error) |
4176 | goto out_unreserve_blocks; | 4172 | goto out_unreserve_blocks; |
4177 | 4173 | ||
@@ -4200,7 +4196,7 @@ out_unreserve_blocks: | |||
4200 | if (rt) | 4196 | if (rt) |
4201 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); | 4197 | xfs_mod_incore_sb(mp, XFS_SBS_FREXTENTS, extsz, 0); |
4202 | else | 4198 | else |
4203 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, alen, 0); | 4199 | xfs_mod_fdblocks(mp, alen, false); |
4204 | out_unreserve_quota: | 4200 | out_unreserve_quota: |
4205 | if (XFS_IS_QUOTA_ON(mp)) | 4201 | if (XFS_IS_QUOTA_ON(mp)) |
4206 | xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? | 4202 | xfs_trans_unreserve_quota_nblks(NULL, ip, (long)alen, 0, rt ? |
@@ -5012,10 +5008,8 @@ xfs_bmap_del_extent( | |||
5012 | * Nothing to do for disk quota accounting here. | 5008 | * Nothing to do for disk quota accounting here. |
5013 | */ | 5009 | */ |
5014 | ASSERT(da_old >= da_new); | 5010 | ASSERT(da_old >= da_new); |
5015 | if (da_old > da_new) { | 5011 | if (da_old > da_new) |
5016 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 5012 | xfs_mod_fdblocks(mp, (int64_t)(da_old - da_new), false); |
5017 | (int64_t)(da_old - da_new), 0); | ||
5018 | } | ||
5019 | done: | 5013 | done: |
5020 | *logflagsp = flags; | 5014 | *logflagsp = flags; |
5021 | return error; | 5015 | return error; |
@@ -5290,8 +5284,8 @@ xfs_bunmapi( | |||
5290 | ip, -((long)del.br_blockcount), 0, | 5284 | ip, -((long)del.br_blockcount), 0, |
5291 | XFS_QMOPT_RES_RTBLKS); | 5285 | XFS_QMOPT_RES_RTBLKS); |
5292 | } else { | 5286 | } else { |
5293 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 5287 | xfs_mod_fdblocks(mp, (int64_t)del.br_blockcount, |
5294 | (int64_t)del.br_blockcount, 0); | 5288 | false); |
5295 | (void)xfs_trans_reserve_quota_nblks(NULL, | 5289 | (void)xfs_trans_reserve_quota_nblks(NULL, |
5296 | ip, -((long)del.br_blockcount), 0, | 5290 | ip, -((long)del.br_blockcount), 0, |
5297 | XFS_QMOPT_RES_REGBLKS); | 5291 | XFS_QMOPT_RES_REGBLKS); |
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c index b66aeab99cfb..31a3e972f86f 100644 --- a/fs/xfs/libxfs/xfs_sb.c +++ b/fs/xfs/libxfs/xfs_sb.c | |||
@@ -773,6 +773,7 @@ xfs_log_sb( | |||
773 | 773 | ||
774 | mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount); | 774 | mp->m_sb.sb_icount = percpu_counter_sum(&mp->m_icount); |
775 | mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree); | 775 | mp->m_sb.sb_ifree = percpu_counter_sum(&mp->m_ifree); |
776 | mp->m_sb.sb_fdblocks = percpu_counter_sum(&mp->m_fdblocks); | ||
776 | 777 | ||
777 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); | 778 | xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb); |
778 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); | 779 | xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF); |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index a1ca9c2b8c00..7ef25588062f 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -640,9 +640,10 @@ xfs_fs_counts( | |||
640 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); | 640 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); |
641 | cnt->allocino = percpu_counter_read_positive(&mp->m_icount); | 641 | cnt->allocino = percpu_counter_read_positive(&mp->m_icount); |
642 | cnt->freeino = percpu_counter_read_positive(&mp->m_ifree); | 642 | cnt->freeino = percpu_counter_read_positive(&mp->m_ifree); |
643 | cnt->freedata = percpu_counter_read_positive(&mp->m_fdblocks) - | ||
644 | XFS_ALLOC_SET_ASIDE(mp); | ||
643 | 645 | ||
644 | spin_lock(&mp->m_sb_lock); | 646 | spin_lock(&mp->m_sb_lock); |
645 | cnt->freedata = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | ||
646 | cnt->freertx = mp->m_sb.sb_frextents; | 647 | cnt->freertx = mp->m_sb.sb_frextents; |
647 | spin_unlock(&mp->m_sb_lock); | 648 | spin_unlock(&mp->m_sb_lock); |
648 | return 0; | 649 | return 0; |
@@ -717,7 +718,8 @@ retry: | |||
717 | } else { | 718 | } else { |
718 | __int64_t free; | 719 | __int64_t free; |
719 | 720 | ||
720 | free = mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 721 | free = percpu_counter_sum(&mp->m_fdblocks) - |
722 | XFS_ALLOC_SET_ASIDE(mp); | ||
721 | if (!free) | 723 | if (!free) |
722 | goto out; /* ENOSPC and fdblks_delta = 0 */ | 724 | goto out; /* ENOSPC and fdblks_delta = 0 */ |
723 | 725 | ||
@@ -756,8 +758,7 @@ out: | |||
756 | * the extra reserve blocks from the reserve..... | 758 | * the extra reserve blocks from the reserve..... |
757 | */ | 759 | */ |
758 | int error; | 760 | int error; |
759 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 761 | error = xfs_mod_fdblocks(mp, fdblks_delta, 0); |
760 | fdblks_delta, 0); | ||
761 | if (error == -ENOSPC) | 762 | if (error == -ENOSPC) |
762 | goto retry; | 763 | goto retry; |
763 | } | 764 | } |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index ccb1dd0d509e..205b948c9d20 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -461,7 +461,7 @@ xfs_iomap_prealloc_size( | |||
461 | alloc_blocks); | 461 | alloc_blocks); |
462 | 462 | ||
463 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); | 463 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); |
464 | freesp = mp->m_sb.sb_fdblocks; | 464 | freesp = percpu_counter_read_positive(&mp->m_fdblocks); |
465 | if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) { | 465 | if (freesp < mp->m_low_space[XFS_LOWSP_5_PCNT]) { |
466 | shift = 2; | 466 | shift = 2; |
467 | if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT]) | 467 | if (freesp < mp->m_low_space[XFS_LOWSP_4_PCNT]) |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 650e8f18cd2a..767c09a5d3ff 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1114,7 +1114,6 @@ xfs_mod_icount( | |||
1114 | return 0; | 1114 | return 0; |
1115 | } | 1115 | } |
1116 | 1116 | ||
1117 | |||
1118 | int | 1117 | int |
1119 | xfs_mod_ifree( | 1118 | xfs_mod_ifree( |
1120 | struct xfs_mount *mp, | 1119 | struct xfs_mount *mp, |
@@ -1128,6 +1127,92 @@ xfs_mod_ifree( | |||
1128 | } | 1127 | } |
1129 | return 0; | 1128 | return 0; |
1130 | } | 1129 | } |
1130 | |||
1131 | int | ||
1132 | xfs_mod_fdblocks( | ||
1133 | struct xfs_mount *mp, | ||
1134 | int64_t delta, | ||
1135 | bool rsvd) | ||
1136 | { | ||
1137 | int64_t lcounter; | ||
1138 | long long res_used; | ||
1139 | s32 batch; | ||
1140 | |||
1141 | if (delta > 0) { | ||
1142 | /* | ||
1143 | * If the reserve pool is depleted, put blocks back into it | ||
1144 | * first. Most of the time the pool is full. | ||
1145 | */ | ||
1146 | if (likely(mp->m_resblks == mp->m_resblks_avail)) { | ||
1147 | percpu_counter_add(&mp->m_fdblocks, delta); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | spin_lock(&mp->m_sb_lock); | ||
1152 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); | ||
1153 | |||
1154 | if (res_used > delta) { | ||
1155 | mp->m_resblks_avail += delta; | ||
1156 | } else { | ||
1157 | delta -= res_used; | ||
1158 | mp->m_resblks_avail = mp->m_resblks; | ||
1159 | percpu_counter_add(&mp->m_fdblocks, delta); | ||
1160 | } | ||
1161 | spin_unlock(&mp->m_sb_lock); | ||
1162 | return 0; | ||
1163 | } | ||
1164 | |||
1165 | /* | ||
1166 | * Taking blocks away, need to be more accurate the closer we | ||
1167 | * are to zero. | ||
1168 | * | ||
1169 | * batch size is set to a maximum of 1024 blocks - if we are | ||
1170 | * allocating of freeing extents larger than this then we aren't | ||
1171 | * going to be hammering the counter lock so a lock per update | ||
1172 | * is not a problem. | ||
1173 | * | ||
1174 | * If the counter has a value of less than 2 * max batch size, | ||
1175 | * then make everything serialise as we are real close to | ||
1176 | * ENOSPC. | ||
1177 | */ | ||
1178 | #define __BATCH 1024 | ||
1179 | if (percpu_counter_compare(&mp->m_fdblocks, 2 * __BATCH) < 0) | ||
1180 | batch = 1; | ||
1181 | else | ||
1182 | batch = __BATCH; | ||
1183 | #undef __BATCH | ||
1184 | |||
1185 | __percpu_counter_add(&mp->m_fdblocks, delta, batch); | ||
1186 | if (percpu_counter_compare(&mp->m_fdblocks, | ||
1187 | XFS_ALLOC_SET_ASIDE(mp)) >= 0) { | ||
1188 | /* we had space! */ | ||
1189 | return 0; | ||
1190 | } | ||
1191 | |||
1192 | /* | ||
1193 | * lock up the sb for dipping into reserves before releasing the space | ||
1194 | * that took us to ENOSPC. | ||
1195 | */ | ||
1196 | spin_lock(&mp->m_sb_lock); | ||
1197 | percpu_counter_add(&mp->m_fdblocks, -delta); | ||
1198 | if (!rsvd) | ||
1199 | goto fdblocks_enospc; | ||
1200 | |||
1201 | lcounter = (long long)mp->m_resblks_avail + delta; | ||
1202 | if (lcounter >= 0) { | ||
1203 | mp->m_resblks_avail = lcounter; | ||
1204 | spin_unlock(&mp->m_sb_lock); | ||
1205 | return 0; | ||
1206 | } | ||
1207 | printk_once(KERN_WARNING | ||
1208 | "Filesystem \"%s\": reserve blocks depleted! " | ||
1209 | "Consider increasing reserve pool size.", | ||
1210 | mp->m_fsname); | ||
1211 | fdblocks_enospc: | ||
1212 | spin_unlock(&mp->m_sb_lock); | ||
1213 | return -ENOSPC; | ||
1214 | } | ||
1215 | |||
1131 | /* | 1216 | /* |
1132 | * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply | 1217 | * xfs_mod_incore_sb_unlocked() is a utility routine commonly used to apply |
1133 | * a delta to a specified field in the in-core superblock. Simply | 1218 | * a delta to a specified field in the in-core superblock. Simply |
@@ -1146,7 +1231,6 @@ xfs_mod_incore_sb_unlocked( | |||
1146 | { | 1231 | { |
1147 | int scounter; /* short counter for 32 bit fields */ | 1232 | int scounter; /* short counter for 32 bit fields */ |
1148 | long long lcounter; /* long counter for 64 bit fields */ | 1233 | long long lcounter; /* long counter for 64 bit fields */ |
1149 | long long res_used, rem; | ||
1150 | 1234 | ||
1151 | /* | 1235 | /* |
1152 | * With the in-core superblock spin lock held, switch | 1236 | * With the in-core superblock spin lock held, switch |
@@ -1157,50 +1241,9 @@ xfs_mod_incore_sb_unlocked( | |||
1157 | switch (field) { | 1241 | switch (field) { |
1158 | case XFS_SBS_ICOUNT: | 1242 | case XFS_SBS_ICOUNT: |
1159 | case XFS_SBS_IFREE: | 1243 | case XFS_SBS_IFREE: |
1244 | case XFS_SBS_FDBLOCKS: | ||
1160 | ASSERT(0); | 1245 | ASSERT(0); |
1161 | return -EINVAL; | 1246 | return -EINVAL; |
1162 | case XFS_SBS_FDBLOCKS: | ||
1163 | lcounter = (long long) | ||
1164 | mp->m_sb.sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | ||
1165 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); | ||
1166 | |||
1167 | if (delta > 0) { /* Putting blocks back */ | ||
1168 | if (res_used > delta) { | ||
1169 | mp->m_resblks_avail += delta; | ||
1170 | } else { | ||
1171 | rem = delta - res_used; | ||
1172 | mp->m_resblks_avail = mp->m_resblks; | ||
1173 | lcounter += rem; | ||
1174 | } | ||
1175 | } else { /* Taking blocks away */ | ||
1176 | lcounter += delta; | ||
1177 | if (lcounter >= 0) { | ||
1178 | mp->m_sb.sb_fdblocks = lcounter + | ||
1179 | XFS_ALLOC_SET_ASIDE(mp); | ||
1180 | return 0; | ||
1181 | } | ||
1182 | |||
1183 | /* | ||
1184 | * We are out of blocks, use any available reserved | ||
1185 | * blocks if were allowed to. | ||
1186 | */ | ||
1187 | if (!rsvd) | ||
1188 | return -ENOSPC; | ||
1189 | |||
1190 | lcounter = (long long)mp->m_resblks_avail + delta; | ||
1191 | if (lcounter >= 0) { | ||
1192 | mp->m_resblks_avail = lcounter; | ||
1193 | return 0; | ||
1194 | } | ||
1195 | printk_once(KERN_WARNING | ||
1196 | "Filesystem \"%s\": reserve blocks depleted! " | ||
1197 | "Consider increasing reserve pool size.", | ||
1198 | mp->m_fsname); | ||
1199 | return -ENOSPC; | ||
1200 | } | ||
1201 | |||
1202 | mp->m_sb.sb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); | ||
1203 | return 0; | ||
1204 | case XFS_SBS_FREXTENTS: | 1247 | case XFS_SBS_FREXTENTS: |
1205 | lcounter = (long long)mp->m_sb.sb_frextents; | 1248 | lcounter = (long long)mp->m_sb.sb_frextents; |
1206 | lcounter += delta; | 1249 | lcounter += delta; |
@@ -1323,7 +1366,7 @@ xfs_mod_incore_sb( | |||
1323 | * | 1366 | * |
1324 | * Note that this function may not be used for the superblock values that | 1367 | * Note that this function may not be used for the superblock values that |
1325 | * are tracked with the in-memory per-cpu counters - a direct call to | 1368 | * are tracked with the in-memory per-cpu counters - a direct call to |
1326 | * xfs_icsb_modify_counters is required for these. | 1369 | * xfs_mod_incore_sb is required for these. |
1327 | */ | 1370 | */ |
1328 | int | 1371 | int |
1329 | xfs_mod_incore_sb_batch( | 1372 | xfs_mod_incore_sb_batch( |
@@ -1508,7 +1551,6 @@ xfs_icsb_cpu_notify( | |||
1508 | case CPU_ONLINE: | 1551 | case CPU_ONLINE: |
1509 | case CPU_ONLINE_FROZEN: | 1552 | case CPU_ONLINE_FROZEN: |
1510 | xfs_icsb_lock(mp); | 1553 | xfs_icsb_lock(mp); |
1511 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); | ||
1512 | xfs_icsb_unlock(mp); | 1554 | xfs_icsb_unlock(mp); |
1513 | break; | 1555 | break; |
1514 | case CPU_DEAD: | 1556 | case CPU_DEAD: |
@@ -1518,13 +1560,9 @@ xfs_icsb_cpu_notify( | |||
1518 | * re-enable the counters. */ | 1560 | * re-enable the counters. */ |
1519 | xfs_icsb_lock(mp); | 1561 | xfs_icsb_lock(mp); |
1520 | spin_lock(&mp->m_sb_lock); | 1562 | spin_lock(&mp->m_sb_lock); |
1521 | xfs_icsb_disable_counter(mp, XFS_SBS_FDBLOCKS); | ||
1522 | |||
1523 | mp->m_sb.sb_fdblocks += cntp->icsb_fdblocks; | ||
1524 | 1563 | ||
1525 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); | 1564 | memset(cntp, 0, sizeof(xfs_icsb_cnts_t)); |
1526 | 1565 | ||
1527 | xfs_icsb_balance_counter_locked(mp, XFS_SBS_FDBLOCKS, 0); | ||
1528 | spin_unlock(&mp->m_sb_lock); | 1566 | spin_unlock(&mp->m_sb_lock); |
1529 | xfs_icsb_unlock(mp); | 1567 | xfs_icsb_unlock(mp); |
1530 | break; | 1568 | break; |
@@ -1550,10 +1588,14 @@ xfs_icsb_init_counters( | |||
1550 | if (error) | 1588 | if (error) |
1551 | goto free_icount; | 1589 | goto free_icount; |
1552 | 1590 | ||
1591 | error = percpu_counter_init(&mp->m_fdblocks, 0, GFP_KERNEL); | ||
1592 | if (error) | ||
1593 | goto free_ifree; | ||
1594 | |||
1553 | mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t); | 1595 | mp->m_sb_cnts = alloc_percpu(xfs_icsb_cnts_t); |
1554 | if (!mp->m_sb_cnts) { | 1596 | if (!mp->m_sb_cnts) { |
1555 | error = -ENOMEM; | 1597 | error = -ENOMEM; |
1556 | goto free_ifree; | 1598 | goto free_fdblocks; |
1557 | } | 1599 | } |
1558 | 1600 | ||
1559 | for_each_online_cpu(i) { | 1601 | for_each_online_cpu(i) { |
@@ -1577,6 +1619,8 @@ xfs_icsb_init_counters( | |||
1577 | 1619 | ||
1578 | return 0; | 1620 | return 0; |
1579 | 1621 | ||
1622 | free_fdblocks: | ||
1623 | percpu_counter_destroy(&mp->m_fdblocks); | ||
1580 | free_ifree: | 1624 | free_ifree: |
1581 | percpu_counter_destroy(&mp->m_ifree); | 1625 | percpu_counter_destroy(&mp->m_ifree); |
1582 | free_icount: | 1626 | free_icount: |
@@ -1590,6 +1634,7 @@ xfs_icsb_reinit_counters( | |||
1590 | { | 1634 | { |
1591 | percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount); | 1635 | percpu_counter_set(&mp->m_icount, mp->m_sb.sb_icount); |
1592 | percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree); | 1636 | percpu_counter_set(&mp->m_ifree, mp->m_sb.sb_ifree); |
1637 | percpu_counter_set(&mp->m_fdblocks, mp->m_sb.sb_fdblocks); | ||
1593 | 1638 | ||
1594 | xfs_icsb_lock(mp); | 1639 | xfs_icsb_lock(mp); |
1595 | /* | 1640 | /* |
@@ -1597,7 +1642,6 @@ xfs_icsb_reinit_counters( | |||
1597 | * initial balance kicks us off correctly | 1642 | * initial balance kicks us off correctly |
1598 | */ | 1643 | */ |
1599 | mp->m_icsb_counters = -1; | 1644 | mp->m_icsb_counters = -1; |
1600 | xfs_icsb_balance_counter(mp, XFS_SBS_FDBLOCKS, 0); | ||
1601 | xfs_icsb_unlock(mp); | 1645 | xfs_icsb_unlock(mp); |
1602 | } | 1646 | } |
1603 | 1647 | ||
@@ -1612,6 +1656,7 @@ xfs_icsb_destroy_counters( | |||
1612 | 1656 | ||
1613 | percpu_counter_destroy(&mp->m_icount); | 1657 | percpu_counter_destroy(&mp->m_icount); |
1614 | percpu_counter_destroy(&mp->m_ifree); | 1658 | percpu_counter_destroy(&mp->m_ifree); |
1659 | percpu_counter_destroy(&mp->m_fdblocks); | ||
1615 | 1660 | ||
1616 | mutex_destroy(&mp->m_icsb_mutex); | 1661 | mutex_destroy(&mp->m_icsb_mutex); |
1617 | } | 1662 | } |
@@ -1665,18 +1710,11 @@ xfs_icsb_count( | |||
1665 | xfs_icsb_cnts_t *cnt, | 1710 | xfs_icsb_cnts_t *cnt, |
1666 | int flags) | 1711 | int flags) |
1667 | { | 1712 | { |
1668 | xfs_icsb_cnts_t *cntp; | ||
1669 | int i; | ||
1670 | |||
1671 | memset(cnt, 0, sizeof(xfs_icsb_cnts_t)); | 1713 | memset(cnt, 0, sizeof(xfs_icsb_cnts_t)); |
1672 | 1714 | ||
1673 | if (!(flags & XFS_ICSB_LAZY_COUNT)) | 1715 | if (!(flags & XFS_ICSB_LAZY_COUNT)) |
1674 | xfs_icsb_lock_all_counters(mp); | 1716 | xfs_icsb_lock_all_counters(mp); |
1675 | 1717 | ||
1676 | for_each_online_cpu(i) { | ||
1677 | cntp = (xfs_icsb_cnts_t *)per_cpu_ptr(mp->m_sb_cnts, i); | ||
1678 | cnt->icsb_fdblocks += cntp->icsb_fdblocks; | ||
1679 | } | ||
1680 | 1718 | ||
1681 | if (!(flags & XFS_ICSB_LAZY_COUNT)) | 1719 | if (!(flags & XFS_ICSB_LAZY_COUNT)) |
1682 | xfs_icsb_unlock_all_counters(mp); | 1720 | xfs_icsb_unlock_all_counters(mp); |
@@ -1687,7 +1725,6 @@ xfs_icsb_counter_disabled( | |||
1687 | xfs_mount_t *mp, | 1725 | xfs_mount_t *mp, |
1688 | xfs_sb_field_t field) | 1726 | xfs_sb_field_t field) |
1689 | { | 1727 | { |
1690 | ASSERT(field == XFS_SBS_FDBLOCKS); | ||
1691 | return test_bit(field, &mp->m_icsb_counters); | 1728 | return test_bit(field, &mp->m_icsb_counters); |
1692 | } | 1729 | } |
1693 | 1730 | ||
@@ -1698,8 +1735,6 @@ xfs_icsb_disable_counter( | |||
1698 | { | 1735 | { |
1699 | xfs_icsb_cnts_t cnt; | 1736 | xfs_icsb_cnts_t cnt; |
1700 | 1737 | ||
1701 | ASSERT(field == XFS_SBS_FDBLOCKS); | ||
1702 | |||
1703 | /* | 1738 | /* |
1704 | * If we are already disabled, then there is nothing to do | 1739 | * If we are already disabled, then there is nothing to do |
1705 | * here. We check before locking all the counters to avoid | 1740 | * here. We check before locking all the counters to avoid |
@@ -1717,9 +1752,6 @@ xfs_icsb_disable_counter( | |||
1717 | 1752 | ||
1718 | xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT); | 1753 | xfs_icsb_count(mp, &cnt, XFS_ICSB_LAZY_COUNT); |
1719 | switch(field) { | 1754 | switch(field) { |
1720 | case XFS_SBS_FDBLOCKS: | ||
1721 | mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; | ||
1722 | break; | ||
1723 | default: | 1755 | default: |
1724 | BUG(); | 1756 | BUG(); |
1725 | } | 1757 | } |
@@ -1735,18 +1767,11 @@ xfs_icsb_enable_counter( | |||
1735 | uint64_t count, | 1767 | uint64_t count, |
1736 | uint64_t resid) | 1768 | uint64_t resid) |
1737 | { | 1769 | { |
1738 | xfs_icsb_cnts_t *cntp; | ||
1739 | int i; | 1770 | int i; |
1740 | 1771 | ||
1741 | ASSERT(field == XFS_SBS_FDBLOCKS); | ||
1742 | |||
1743 | xfs_icsb_lock_all_counters(mp); | 1772 | xfs_icsb_lock_all_counters(mp); |
1744 | for_each_online_cpu(i) { | 1773 | for_each_online_cpu(i) { |
1745 | cntp = per_cpu_ptr(mp->m_sb_cnts, i); | ||
1746 | switch (field) { | 1774 | switch (field) { |
1747 | case XFS_SBS_FDBLOCKS: | ||
1748 | cntp->icsb_fdblocks = count + resid; | ||
1749 | break; | ||
1750 | default: | 1775 | default: |
1751 | BUG(); | 1776 | BUG(); |
1752 | break; | 1777 | break; |
@@ -1765,9 +1790,6 @@ xfs_icsb_sync_counters_locked( | |||
1765 | xfs_icsb_cnts_t cnt; | 1790 | xfs_icsb_cnts_t cnt; |
1766 | 1791 | ||
1767 | xfs_icsb_count(mp, &cnt, flags); | 1792 | xfs_icsb_count(mp, &cnt, flags); |
1768 | |||
1769 | if (!xfs_icsb_counter_disabled(mp, XFS_SBS_FDBLOCKS)) | ||
1770 | mp->m_sb.sb_fdblocks = cnt.icsb_fdblocks; | ||
1771 | } | 1793 | } |
1772 | 1794 | ||
1773 | /* | 1795 | /* |
@@ -1809,20 +1831,12 @@ xfs_icsb_balance_counter_locked( | |||
1809 | int min_per_cpu) | 1831 | int min_per_cpu) |
1810 | { | 1832 | { |
1811 | uint64_t count, resid; | 1833 | uint64_t count, resid; |
1812 | int weight = num_online_cpus(); | ||
1813 | uint64_t min = (uint64_t)min_per_cpu; | ||
1814 | 1834 | ||
1815 | /* disable counter and sync counter */ | 1835 | /* disable counter and sync counter */ |
1816 | xfs_icsb_disable_counter(mp, field); | 1836 | xfs_icsb_disable_counter(mp, field); |
1817 | 1837 | ||
1818 | /* update counters - first CPU gets residual*/ | 1838 | /* update counters - first CPU gets residual*/ |
1819 | switch (field) { | 1839 | switch (field) { |
1820 | case XFS_SBS_FDBLOCKS: | ||
1821 | count = mp->m_sb.sb_fdblocks; | ||
1822 | resid = do_div(count, weight); | ||
1823 | if (count < max(min, XFS_ICSB_FDBLK_CNTR_REENABLE(mp))) | ||
1824 | return; | ||
1825 | break; | ||
1826 | default: | 1840 | default: |
1827 | BUG(); | 1841 | BUG(); |
1828 | count = resid = 0; /* quiet, gcc */ | 1842 | count = resid = 0; /* quiet, gcc */ |
@@ -1851,7 +1865,6 @@ xfs_icsb_modify_counters( | |||
1851 | int rsvd) | 1865 | int rsvd) |
1852 | { | 1866 | { |
1853 | xfs_icsb_cnts_t *icsbp; | 1867 | xfs_icsb_cnts_t *icsbp; |
1854 | long long lcounter; /* long counter for 64 bit fields */ | ||
1855 | int ret = 0; | 1868 | int ret = 0; |
1856 | 1869 | ||
1857 | might_sleep(); | 1870 | might_sleep(); |
@@ -1871,18 +1884,9 @@ again: | |||
1871 | } | 1884 | } |
1872 | 1885 | ||
1873 | switch (field) { | 1886 | switch (field) { |
1874 | case XFS_SBS_FDBLOCKS: | ||
1875 | BUG_ON((mp->m_resblks - mp->m_resblks_avail) != 0); | ||
1876 | |||
1877 | lcounter = icsbp->icsb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | ||
1878 | lcounter += delta; | ||
1879 | if (unlikely(lcounter < 0)) | ||
1880 | goto balance_counter; | ||
1881 | icsbp->icsb_fdblocks = lcounter + XFS_ALLOC_SET_ASIDE(mp); | ||
1882 | break; | ||
1883 | default: | 1887 | default: |
1884 | BUG(); | 1888 | BUG(); |
1885 | break; | 1889 | goto balance_counter; /* be still, gcc */ |
1886 | } | 1890 | } |
1887 | xfs_icsb_unlock_cntr(icsbp); | 1891 | xfs_icsb_unlock_cntr(icsbp); |
1888 | preempt_enable(); | 1892 | preempt_enable(); |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 7ce997d43d81..84b745fbc787 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -85,6 +85,7 @@ typedef struct xfs_mount { | |||
85 | spinlock_t m_sb_lock; /* sb counter lock */ | 85 | spinlock_t m_sb_lock; /* sb counter lock */ |
86 | struct percpu_counter m_icount; /* allocated inodes counter */ | 86 | struct percpu_counter m_icount; /* allocated inodes counter */ |
87 | struct percpu_counter m_ifree; /* free inodes counter */ | 87 | struct percpu_counter m_ifree; /* free inodes counter */ |
88 | struct percpu_counter m_fdblocks; /* free block counter */ | ||
88 | 89 | ||
89 | struct xfs_buf *m_sb_bp; /* buffer for superblock */ | 90 | struct xfs_buf *m_sb_bp; /* buffer for superblock */ |
90 | char *m_fsname; /* filesystem name */ | 91 | char *m_fsname; /* filesystem name */ |
@@ -393,6 +394,8 @@ extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *, | |||
393 | uint, int); | 394 | uint, int); |
394 | extern int xfs_mod_icount(struct xfs_mount *mp, int64_t delta); | 395 | extern int xfs_mod_icount(struct xfs_mount *mp, int64_t delta); |
395 | extern int xfs_mod_ifree(struct xfs_mount *mp, int64_t delta); | 396 | extern int xfs_mod_ifree(struct xfs_mount *mp, int64_t delta); |
397 | extern int xfs_mod_fdblocks(struct xfs_mount *mp, int64_t delta, | ||
398 | bool reserved); | ||
396 | extern int xfs_mount_log_sb(xfs_mount_t *); | 399 | extern int xfs_mount_log_sb(xfs_mount_t *); |
397 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); | 400 | extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int); |
398 | extern int xfs_readsb(xfs_mount_t *, int); | 401 | extern int xfs_readsb(xfs_mount_t *, int); |
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c index 049147776ee1..9ec75074026d 100644 --- a/fs/xfs/xfs_super.c +++ b/fs/xfs/xfs_super.c | |||
@@ -1087,6 +1087,7 @@ xfs_fs_statfs( | |||
1087 | __uint64_t fakeinos, id; | 1087 | __uint64_t fakeinos, id; |
1088 | __uint64_t icount; | 1088 | __uint64_t icount; |
1089 | __uint64_t ifree; | 1089 | __uint64_t ifree; |
1090 | __uint64_t fdblocks; | ||
1090 | xfs_extlen_t lsize; | 1091 | xfs_extlen_t lsize; |
1091 | __int64_t ffree; | 1092 | __int64_t ffree; |
1092 | 1093 | ||
@@ -1100,13 +1101,17 @@ xfs_fs_statfs( | |||
1100 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); | 1101 | xfs_icsb_sync_counters(mp, XFS_ICSB_LAZY_COUNT); |
1101 | icount = percpu_counter_sum(&mp->m_icount); | 1102 | icount = percpu_counter_sum(&mp->m_icount); |
1102 | ifree = percpu_counter_sum(&mp->m_ifree); | 1103 | ifree = percpu_counter_sum(&mp->m_ifree); |
1104 | fdblocks = percpu_counter_sum(&mp->m_fdblocks); | ||
1103 | 1105 | ||
1104 | spin_lock(&mp->m_sb_lock); | 1106 | spin_lock(&mp->m_sb_lock); |
1105 | statp->f_bsize = sbp->sb_blocksize; | 1107 | statp->f_bsize = sbp->sb_blocksize; |
1106 | lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; | 1108 | lsize = sbp->sb_logstart ? sbp->sb_logblocks : 0; |
1107 | statp->f_blocks = sbp->sb_dblocks - lsize; | 1109 | statp->f_blocks = sbp->sb_dblocks - lsize; |
1108 | statp->f_bfree = statp->f_bavail = | 1110 | spin_unlock(&mp->m_sb_lock); |
1109 | sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 1111 | |
1112 | statp->f_bfree = fdblocks - XFS_ALLOC_SET_ASIDE(mp); | ||
1113 | statp->f_bavail = statp->f_bfree; | ||
1114 | |||
1110 | fakeinos = statp->f_bfree << sbp->sb_inopblog; | 1115 | fakeinos = statp->f_bfree << sbp->sb_inopblog; |
1111 | statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); | 1116 | statp->f_files = MIN(icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); |
1112 | if (mp->m_maxicount) | 1117 | if (mp->m_maxicount) |
@@ -1123,7 +1128,6 @@ xfs_fs_statfs( | |||
1123 | ffree = statp->f_files - (icount - ifree); | 1128 | ffree = statp->f_files - (icount - ifree); |
1124 | statp->f_ffree = max_t(__int64_t, ffree, 0); | 1129 | statp->f_ffree = max_t(__int64_t, ffree, 0); |
1125 | 1130 | ||
1126 | spin_unlock(&mp->m_sb_lock); | ||
1127 | 1131 | ||
1128 | if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) && | 1132 | if ((ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) && |
1129 | ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) == | 1133 | ((mp->m_qflags & (XFS_PQUOTA_ACCT|XFS_PQUOTA_ENFD))) == |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 68680ce67547..e99f5e552c64 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -173,7 +173,7 @@ xfs_trans_reserve( | |||
173 | uint rtextents) | 173 | uint rtextents) |
174 | { | 174 | { |
175 | int error = 0; | 175 | int error = 0; |
176 | int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; | 176 | bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; |
177 | 177 | ||
178 | /* Mark this thread as being in a transaction */ | 178 | /* Mark this thread as being in a transaction */ |
179 | current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); | 179 | current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); |
@@ -184,8 +184,7 @@ xfs_trans_reserve( | |||
184 | * fail if the count would go below zero. | 184 | * fail if the count would go below zero. |
185 | */ | 185 | */ |
186 | if (blocks > 0) { | 186 | if (blocks > 0) { |
187 | error = xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, | 187 | error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd); |
188 | -((int64_t)blocks), rsvd); | ||
189 | if (error != 0) { | 188 | if (error != 0) { |
190 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); | 189 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
191 | return -ENOSPC; | 190 | return -ENOSPC; |
@@ -268,8 +267,7 @@ undo_log: | |||
268 | 267 | ||
269 | undo_blocks: | 268 | undo_blocks: |
270 | if (blocks > 0) { | 269 | if (blocks > 0) { |
271 | xfs_icsb_modify_counters(tp->t_mountp, XFS_SBS_FDBLOCKS, | 270 | xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd); |
272 | (int64_t)blocks, rsvd); | ||
273 | tp->t_blk_res = 0; | 271 | tp->t_blk_res = 0; |
274 | } | 272 | } |
275 | 273 | ||
@@ -516,14 +514,13 @@ xfs_trans_unreserve_and_mod_sb( | |||
516 | xfs_mount_t *mp = tp->t_mountp; | 514 | xfs_mount_t *mp = tp->t_mountp; |
517 | /* REFERENCED */ | 515 | /* REFERENCED */ |
518 | int error; | 516 | int error; |
519 | int rsvd; | 517 | bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; |
520 | int64_t blkdelta = 0; | 518 | int64_t blkdelta = 0; |
521 | int64_t rtxdelta = 0; | 519 | int64_t rtxdelta = 0; |
522 | int64_t idelta = 0; | 520 | int64_t idelta = 0; |
523 | int64_t ifreedelta = 0; | 521 | int64_t ifreedelta = 0; |
524 | 522 | ||
525 | msbp = msb; | 523 | msbp = msb; |
526 | rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; | ||
527 | 524 | ||
528 | /* calculate deltas */ | 525 | /* calculate deltas */ |
529 | if (tp->t_blk_res > 0) | 526 | if (tp->t_blk_res > 0) |
@@ -547,8 +544,7 @@ xfs_trans_unreserve_and_mod_sb( | |||
547 | 544 | ||
548 | /* apply the per-cpu counters */ | 545 | /* apply the per-cpu counters */ |
549 | if (blkdelta) { | 546 | if (blkdelta) { |
550 | error = xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, | 547 | error = xfs_mod_fdblocks(mp, blkdelta, rsvd); |
551 | blkdelta, rsvd); | ||
552 | if (error) | 548 | if (error) |
553 | goto out; | 549 | goto out; |
554 | } | 550 | } |
@@ -635,7 +631,7 @@ out_undo_icount: | |||
635 | xfs_mod_icount(mp, -idelta); | 631 | xfs_mod_icount(mp, -idelta); |
636 | out_undo_fdblocks: | 632 | out_undo_fdblocks: |
637 | if (blkdelta) | 633 | if (blkdelta) |
638 | xfs_icsb_modify_counters(mp, XFS_SBS_FDBLOCKS, -blkdelta, rsvd); | 634 | xfs_mod_fdblocks(mp, -blkdelta, rsvd); |
639 | out: | 635 | out: |
640 | ASSERT(error == 0); | 636 | ASSERT(error == 0); |
641 | return; | 637 | return; |