aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext3/balloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext3/balloc.c')
-rw-r--r--fs/ext3/balloc.c149
1 files changed, 119 insertions, 30 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c
index 6250fcdf14a1..77927d6938f6 100644
--- a/fs/ext3/balloc.c
+++ b/fs/ext3/balloc.c
@@ -653,9 +653,11 @@ claim_block(spinlock_t *lock, int block, struct buffer_head *bh)
653 */ 653 */
654static int 654static int
655ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group, 655ext3_try_to_allocate(struct super_block *sb, handle_t *handle, int group,
656 struct buffer_head *bitmap_bh, int goal, struct ext3_reserve_window *my_rsv) 656 struct buffer_head *bitmap_bh, int goal,
657 unsigned long *count, struct ext3_reserve_window *my_rsv)
657{ 658{
658 int group_first_block, start, end; 659 int group_first_block, start, end;
660 unsigned long num = 0;
659 661
660 /* we do allocation within the reservation window if we have a window */ 662 /* we do allocation within the reservation window if we have a window */
661 if (my_rsv) { 663 if (my_rsv) {
@@ -713,8 +715,18 @@ repeat:
713 goto fail_access; 715 goto fail_access;
714 goto repeat; 716 goto repeat;
715 } 717 }
716 return goal; 718 num++;
719 goal++;
720 while (num < *count && goal < end
721 && ext3_test_allocatable(goal, bitmap_bh)
722 && claim_block(sb_bgl_lock(EXT3_SB(sb), group), goal, bitmap_bh)) {
723 num++;
724 goal++;
725 }
726 *count = num;
727 return goal - num;
717fail_access: 728fail_access:
729 *count = num;
718 return -1; 730 return -1;
719} 731}
720 732
@@ -999,6 +1011,31 @@ retry:
999 goto retry; 1011 goto retry;
1000} 1012}
1001 1013
1014static void try_to_extend_reservation(struct ext3_reserve_window_node *my_rsv,
1015 struct super_block *sb, int size)
1016{
1017 struct ext3_reserve_window_node *next_rsv;
1018 struct rb_node *next;
1019 spinlock_t *rsv_lock = &EXT3_SB(sb)->s_rsv_window_lock;
1020
1021 if (!spin_trylock(rsv_lock))
1022 return;
1023
1024 next = rb_next(&my_rsv->rsv_node);
1025
1026 if (!next)
1027 my_rsv->rsv_end += size;
1028 else {
1029 next_rsv = list_entry(next, struct ext3_reserve_window_node, rsv_node);
1030
1031 if ((next_rsv->rsv_start - my_rsv->rsv_end - 1) >= size)
1032 my_rsv->rsv_end += size;
1033 else
1034 my_rsv->rsv_end = next_rsv->rsv_start - 1;
1035 }
1036 spin_unlock(rsv_lock);
1037}
1038
1002/* 1039/*
1003 * This is the main function used to allocate a new block and its reservation 1040 * This is the main function used to allocate a new block and its reservation
1004 * window. 1041 * window.
@@ -1024,11 +1061,12 @@ static int
1024ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle, 1061ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1025 unsigned int group, struct buffer_head *bitmap_bh, 1062 unsigned int group, struct buffer_head *bitmap_bh,
1026 int goal, struct ext3_reserve_window_node * my_rsv, 1063 int goal, struct ext3_reserve_window_node * my_rsv,
1027 int *errp) 1064 unsigned long *count, int *errp)
1028{ 1065{
1029 unsigned long group_first_block; 1066 unsigned long group_first_block;
1030 int ret = 0; 1067 int ret = 0;
1031 int fatal; 1068 int fatal;
1069 unsigned long num = *count;
1032 1070
1033 *errp = 0; 1071 *errp = 0;
1034 1072
@@ -1051,7 +1089,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1051 * or last attempt to allocate a block with reservation turned on failed 1089 * or last attempt to allocate a block with reservation turned on failed
1052 */ 1090 */
1053 if (my_rsv == NULL ) { 1091 if (my_rsv == NULL ) {
1054 ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, NULL); 1092 ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh,
1093 goal, count, NULL);
1055 goto out; 1094 goto out;
1056 } 1095 }
1057 /* 1096 /*
@@ -1081,6 +1120,8 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1081 while (1) { 1120 while (1) {
1082 if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) || 1121 if (rsv_is_empty(&my_rsv->rsv_window) || (ret < 0) ||
1083 !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) { 1122 !goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) {
1123 if (my_rsv->rsv_goal_size < *count)
1124 my_rsv->rsv_goal_size = *count;
1084 ret = alloc_new_reservation(my_rsv, goal, sb, 1125 ret = alloc_new_reservation(my_rsv, goal, sb,
1085 group, bitmap_bh); 1126 group, bitmap_bh);
1086 if (ret < 0) 1127 if (ret < 0)
@@ -1088,16 +1129,21 @@ ext3_try_to_allocate_with_rsv(struct super_block *sb, handle_t *handle,
1088 1129
1089 if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb)) 1130 if (!goal_in_my_reservation(&my_rsv->rsv_window, goal, group, sb))
1090 goal = -1; 1131 goal = -1;
1091 } 1132 } else if (goal > 0 && (my_rsv->rsv_end-goal+1) < *count)
1133 try_to_extend_reservation(my_rsv, sb,
1134 *count-my_rsv->rsv_end + goal - 1);
1135
1092 if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb)) 1136 if ((my_rsv->rsv_start >= group_first_block + EXT3_BLOCKS_PER_GROUP(sb))
1093 || (my_rsv->rsv_end < group_first_block)) 1137 || (my_rsv->rsv_end < group_first_block))
1094 BUG(); 1138 BUG();
1095 ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal, 1139 ret = ext3_try_to_allocate(sb, handle, group, bitmap_bh, goal,
1096 &my_rsv->rsv_window); 1140 &num, &my_rsv->rsv_window);
1097 if (ret >= 0) { 1141 if (ret >= 0) {
1098 my_rsv->rsv_alloc_hit++; 1142 my_rsv->rsv_alloc_hit += num;
1143 *count = num;
1099 break; /* succeed */ 1144 break; /* succeed */
1100 } 1145 }
1146 num = *count;
1101 } 1147 }
1102out: 1148out:
1103 if (ret >= 0) { 1149 if (ret >= 0) {
@@ -1154,8 +1200,8 @@ int ext3_should_retry_alloc(struct super_block *sb, int *retries)
1154 * bitmap, and then for any free bit if that fails. 1200 * bitmap, and then for any free bit if that fails.
1155 * This function also updates quota and i_blocks field. 1201 * This function also updates quota and i_blocks field.
1156 */ 1202 */
1157int ext3_new_block(handle_t *handle, struct inode *inode, 1203int ext3_new_blocks(handle_t *handle, struct inode *inode,
1158 unsigned long goal, int *errp) 1204 unsigned long goal, unsigned long *count, int *errp)
1159{ 1205{
1160 struct buffer_head *bitmap_bh = NULL; 1206 struct buffer_head *bitmap_bh = NULL;
1161 struct buffer_head *gdp_bh; 1207 struct buffer_head *gdp_bh;
@@ -1178,6 +1224,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode,
1178 static int goal_hits, goal_attempts; 1224 static int goal_hits, goal_attempts;
1179#endif 1225#endif
1180 unsigned long ngroups; 1226 unsigned long ngroups;
1227 unsigned long num = *count;
1181 1228
1182 *errp = -ENOSPC; 1229 *errp = -ENOSPC;
1183 sb = inode->i_sb; 1230 sb = inode->i_sb;
@@ -1189,7 +1236,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode,
1189 /* 1236 /*
1190 * Check quota for allocation of this block. 1237 * Check quota for allocation of this block.
1191 */ 1238 */
1192 if (DQUOT_ALLOC_BLOCK(inode, 1)) { 1239 if (DQUOT_ALLOC_BLOCK(inode, num)) {
1193 *errp = -EDQUOT; 1240 *errp = -EDQUOT;
1194 return 0; 1241 return 0;
1195 } 1242 }
@@ -1244,7 +1291,7 @@ retry:
1244 if (!bitmap_bh) 1291 if (!bitmap_bh)
1245 goto io_error; 1292 goto io_error;
1246 ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, 1293 ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
1247 bitmap_bh, ret_block, my_rsv, &fatal); 1294 bitmap_bh, ret_block, my_rsv, &num, &fatal);
1248 if (fatal) 1295 if (fatal)
1249 goto out; 1296 goto out;
1250 if (ret_block >= 0) 1297 if (ret_block >= 0)
@@ -1281,7 +1328,7 @@ retry:
1281 if (!bitmap_bh) 1328 if (!bitmap_bh)
1282 goto io_error; 1329 goto io_error;
1283 ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no, 1330 ret_block = ext3_try_to_allocate_with_rsv(sb, handle, group_no,
1284 bitmap_bh, -1, my_rsv, &fatal); 1331 bitmap_bh, -1, my_rsv, &num, &fatal);
1285 if (fatal) 1332 if (fatal)
1286 goto out; 1333 goto out;
1287 if (ret_block >= 0) 1334 if (ret_block >= 0)
@@ -1316,13 +1363,15 @@ allocated:
1316 target_block = ret_block + group_no * EXT3_BLOCKS_PER_GROUP(sb) 1363 target_block = ret_block + group_no * EXT3_BLOCKS_PER_GROUP(sb)
1317 + le32_to_cpu(es->s_first_data_block); 1364 + le32_to_cpu(es->s_first_data_block);
1318 1365
1319 if (target_block == le32_to_cpu(gdp->bg_block_bitmap) || 1366 if (in_range(le32_to_cpu(gdp->bg_block_bitmap), target_block, num) ||
1320 target_block == le32_to_cpu(gdp->bg_inode_bitmap) || 1367 in_range(le32_to_cpu(gdp->bg_inode_bitmap), target_block, num) ||
1321 in_range(target_block, le32_to_cpu(gdp->bg_inode_table), 1368 in_range(target_block, le32_to_cpu(gdp->bg_inode_table),
1369 EXT3_SB(sb)->s_itb_per_group) ||
1370 in_range(target_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
1322 EXT3_SB(sb)->s_itb_per_group)) 1371 EXT3_SB(sb)->s_itb_per_group))
1323 ext3_error(sb, "ext3_new_block", 1372 ext3_error(sb, "ext3_new_block",
1324 "Allocating block in system zone - " 1373 "Allocating block in system zone - "
1325 "block = %u", target_block); 1374 "blocks from %u, length %lu", target_block, num);
1326 1375
1327 performed_allocation = 1; 1376 performed_allocation = 1;
1328 1377
@@ -1341,10 +1390,14 @@ allocated:
1341 jbd_lock_bh_state(bitmap_bh); 1390 jbd_lock_bh_state(bitmap_bh);
1342 spin_lock(sb_bgl_lock(sbi, group_no)); 1391 spin_lock(sb_bgl_lock(sbi, group_no));
1343 if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) { 1392 if (buffer_jbd(bitmap_bh) && bh2jh(bitmap_bh)->b_committed_data) {
1344 if (ext3_test_bit(ret_block, 1393 int i;
1345 bh2jh(bitmap_bh)->b_committed_data)) { 1394
1346 printk("%s: block was unexpectedly set in " 1395 for (i = 0; i < num; i++) {
1347 "b_committed_data\n", __FUNCTION__); 1396 if (ext3_test_bit(ret_block,
1397 bh2jh(bitmap_bh)->b_committed_data)) {
1398 printk("%s: block was unexpectedly set in "
1399 "b_committed_data\n", __FUNCTION__);
1400 }
1348 } 1401 }
1349 } 1402 }
1350 ext3_debug("found bit %d\n", ret_block); 1403 ext3_debug("found bit %d\n", ret_block);
@@ -1355,7 +1408,7 @@ allocated:
1355 /* ret_block was blockgroup-relative. Now it becomes fs-relative */ 1408 /* ret_block was blockgroup-relative. Now it becomes fs-relative */
1356 ret_block = target_block; 1409 ret_block = target_block;
1357 1410
1358 if (ret_block >= le32_to_cpu(es->s_blocks_count)) { 1411 if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
1359 ext3_error(sb, "ext3_new_block", 1412 ext3_error(sb, "ext3_new_block",
1360 "block(%d) >= blocks count(%d) - " 1413 "block(%d) >= blocks count(%d) - "
1361 "block_group = %d, es == %p ", ret_block, 1414 "block_group = %d, es == %p ", ret_block,
@@ -1373,9 +1426,9 @@ allocated:
1373 1426
1374 spin_lock(sb_bgl_lock(sbi, group_no)); 1427 spin_lock(sb_bgl_lock(sbi, group_no));
1375 gdp->bg_free_blocks_count = 1428 gdp->bg_free_blocks_count =
1376 cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - 1); 1429 cpu_to_le16(le16_to_cpu(gdp->bg_free_blocks_count) - num);
1377 spin_unlock(sb_bgl_lock(sbi, group_no)); 1430 spin_unlock(sb_bgl_lock(sbi, group_no));
1378 percpu_counter_mod(&sbi->s_freeblocks_counter, -1); 1431 percpu_counter_mod(&sbi->s_freeblocks_counter, -num);
1379 1432
1380 BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor"); 1433 BUFFER_TRACE(gdp_bh, "journal_dirty_metadata for group descriptor");
1381 err = ext3_journal_dirty_metadata(handle, gdp_bh); 1434 err = ext3_journal_dirty_metadata(handle, gdp_bh);
@@ -1388,6 +1441,8 @@ allocated:
1388 1441
1389 *errp = 0; 1442 *errp = 0;
1390 brelse(bitmap_bh); 1443 brelse(bitmap_bh);
1444 DQUOT_FREE_BLOCK(inode, *count-num);
1445 *count = num;
1391 return ret_block; 1446 return ret_block;
1392 1447
1393io_error: 1448io_error:
@@ -1401,11 +1456,19 @@ out:
1401 * Undo the block allocation 1456 * Undo the block allocation
1402 */ 1457 */
1403 if (!performed_allocation) 1458 if (!performed_allocation)
1404 DQUOT_FREE_BLOCK(inode, 1); 1459 DQUOT_FREE_BLOCK(inode, *count);
1405 brelse(bitmap_bh); 1460 brelse(bitmap_bh);
1406 return 0; 1461 return 0;
1407} 1462}
1408 1463
1464int ext3_new_block(handle_t *handle, struct inode *inode,
1465 unsigned long goal, int *errp)
1466{
1467 unsigned long count = 1;
1468
1469 return ext3_new_blocks(handle, inode, goal, &count, errp);
1470}
1471
1409unsigned long ext3_count_free_blocks(struct super_block *sb) 1472unsigned long ext3_count_free_blocks(struct super_block *sb)
1410{ 1473{
1411 unsigned long desc_count; 1474 unsigned long desc_count;
@@ -1493,12 +1556,33 @@ static int ext3_group_sparse(int group)
1493 */ 1556 */
1494int ext3_bg_has_super(struct super_block *sb, int group) 1557int ext3_bg_has_super(struct super_block *sb, int group)
1495{ 1558{
1496 if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&& 1559 if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
1497 !ext3_group_sparse(group)) 1560 EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
1561 !ext3_group_sparse(group))
1498 return 0; 1562 return 0;
1499 return 1; 1563 return 1;
1500} 1564}
1501 1565
1566static unsigned long ext3_bg_num_gdb_meta(struct super_block *sb, int group)
1567{
1568 unsigned long metagroup = group / EXT3_DESC_PER_BLOCK(sb);
1569 unsigned long first = metagroup * EXT3_DESC_PER_BLOCK(sb);
1570 unsigned long last = first + EXT3_DESC_PER_BLOCK(sb) - 1;
1571
1572 if (group == first || group == first + 1 || group == last)
1573 return 1;
1574 return 0;
1575}
1576
1577static unsigned long ext3_bg_num_gdb_nometa(struct super_block *sb, int group)
1578{
1579 if (EXT3_HAS_RO_COMPAT_FEATURE(sb,
1580 EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER) &&
1581 !ext3_group_sparse(group))
1582 return 0;
1583 return EXT3_SB(sb)->s_gdb_count;
1584}
1585
1502/** 1586/**
1503 * ext3_bg_num_gdb - number of blocks used by the group table in group 1587 * ext3_bg_num_gdb - number of blocks used by the group table in group
1504 * @sb: superblock for filesystem 1588 * @sb: superblock for filesystem
@@ -1510,9 +1594,14 @@ int ext3_bg_has_super(struct super_block *sb, int group)
1510 */ 1594 */
1511unsigned long ext3_bg_num_gdb(struct super_block *sb, int group) 1595unsigned long ext3_bg_num_gdb(struct super_block *sb, int group)
1512{ 1596{
1513 if (EXT3_HAS_RO_COMPAT_FEATURE(sb,EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)&& 1597 unsigned long first_meta_bg =
1514 !ext3_group_sparse(group)) 1598 le32_to_cpu(EXT3_SB(sb)->s_es->s_first_meta_bg);
1515 return 0; 1599 unsigned long metagroup = group / EXT3_DESC_PER_BLOCK(sb);
1516 return EXT3_SB(sb)->s_gdb_count; 1600
1517} 1601 if (!EXT3_HAS_INCOMPAT_FEATURE(sb,EXT3_FEATURE_INCOMPAT_META_BG) ||
1602 metagroup < first_meta_bg)
1603 return ext3_bg_num_gdb_nometa(sb,group);
1518 1604
1605 return ext3_bg_num_gdb_meta(sb,group);
1606
1607}