| .. | .. |
|---|
| 187 | 187 | |
|---|
| 188 | 188 | /** |
|---|
| 189 | 189 | * __rsv_window_dump() -- Dump the filesystem block allocation reservation map |
|---|
| 190 | | - * @rb_root: root of per-filesystem reservation rb tree |
|---|
| 190 | + * @root: root of per-filesystem reservation rb tree |
|---|
| 191 | 191 | * @verbose: verbose mode |
|---|
| 192 | 192 | * @fn: function which wishes to dump the reservation map |
|---|
| 193 | 193 | * |
|---|
| .. | .. |
|---|
| 267 | 267 | ext2_fsblk_t group_first_block, group_last_block; |
|---|
| 268 | 268 | |
|---|
| 269 | 269 | group_first_block = ext2_group_first_block_no(sb, group); |
|---|
| 270 | | - group_last_block = group_first_block + EXT2_BLOCKS_PER_GROUP(sb) - 1; |
|---|
| 270 | + group_last_block = ext2_group_last_block_no(sb, group); |
|---|
| 271 | 271 | |
|---|
| 272 | 272 | if ((rsv->_rsv_start > group_last_block) || |
|---|
| 273 | 273 | (rsv->_rsv_end < group_first_block)) |
|---|
| .. | .. |
|---|
| 280 | 280 | |
|---|
| 281 | 281 | /** |
|---|
| 282 | 282 | * search_reserve_window() |
|---|
| 283 | | - * @rb_root: root of reservation tree |
|---|
| 283 | + * @root: root of reservation tree |
|---|
| 284 | 284 | * @goal: target allocation block |
|---|
| 285 | 285 | * |
|---|
| 286 | 286 | * Find the reserved window which includes the goal, or the previous one |
|---|
| .. | .. |
|---|
| 488 | 488 | struct ext2_super_block * es = sbi->s_es; |
|---|
| 489 | 489 | unsigned freed = 0, group_freed; |
|---|
| 490 | 490 | |
|---|
| 491 | | - if (block < le32_to_cpu(es->s_first_data_block) || |
|---|
| 492 | | - block + count < block || |
|---|
| 493 | | - block + count > le32_to_cpu(es->s_blocks_count)) { |
|---|
| 491 | + if (!ext2_data_block_valid(sbi, block, count)) { |
|---|
| 494 | 492 | ext2_error (sb, "ext2_free_blocks", |
|---|
| 495 | 493 | "Freeing blocks not in datazone - " |
|---|
| 496 | 494 | "block = %lu, count = %lu", block, count); |
|---|
| .. | .. |
|---|
| 666 | 664 | unsigned long *count, |
|---|
| 667 | 665 | struct ext2_reserve_window *my_rsv) |
|---|
| 668 | 666 | { |
|---|
| 669 | | - ext2_fsblk_t group_first_block; |
|---|
| 667 | + ext2_fsblk_t group_first_block = ext2_group_first_block_no(sb, group); |
|---|
| 668 | + ext2_fsblk_t group_last_block = ext2_group_last_block_no(sb, group); |
|---|
| 670 | 669 | ext2_grpblk_t start, end; |
|---|
| 671 | 670 | unsigned long num = 0; |
|---|
| 672 | 671 | |
|---|
| 672 | + start = 0; |
|---|
| 673 | + end = group_last_block - group_first_block + 1; |
|---|
| 673 | 674 | /* we do allocation within the reservation window if we have a window */ |
|---|
| 674 | 675 | if (my_rsv) { |
|---|
| 675 | | - group_first_block = ext2_group_first_block_no(sb, group); |
|---|
| 676 | 676 | if (my_rsv->_rsv_start >= group_first_block) |
|---|
| 677 | 677 | start = my_rsv->_rsv_start - group_first_block; |
|---|
| 678 | | - else |
|---|
| 679 | | - /* reservation window cross group boundary */ |
|---|
| 680 | | - start = 0; |
|---|
| 681 | | - end = my_rsv->_rsv_end - group_first_block + 1; |
|---|
| 682 | | - if (end > EXT2_BLOCKS_PER_GROUP(sb)) |
|---|
| 683 | | - /* reservation window crosses group boundary */ |
|---|
| 684 | | - end = EXT2_BLOCKS_PER_GROUP(sb); |
|---|
| 685 | | - if ((start <= grp_goal) && (grp_goal < end)) |
|---|
| 686 | | - start = grp_goal; |
|---|
| 687 | | - else |
|---|
| 678 | + if (my_rsv->_rsv_end < group_last_block) |
|---|
| 679 | + end = my_rsv->_rsv_end - group_first_block + 1; |
|---|
| 680 | + if (grp_goal < start || grp_goal >= end) |
|---|
| 688 | 681 | grp_goal = -1; |
|---|
| 689 | | - } else { |
|---|
| 690 | | - if (grp_goal > 0) |
|---|
| 691 | | - start = grp_goal; |
|---|
| 692 | | - else |
|---|
| 693 | | - start = 0; |
|---|
| 694 | | - end = EXT2_BLOCKS_PER_GROUP(sb); |
|---|
| 695 | 682 | } |
|---|
| 696 | | - |
|---|
| 697 | 683 | BUG_ON(start > EXT2_BLOCKS_PER_GROUP(sb)); |
|---|
| 698 | 684 | |
|---|
| 699 | | -repeat: |
|---|
| 700 | 685 | if (grp_goal < 0) { |
|---|
| 701 | 686 | grp_goal = find_next_usable_block(start, bitmap_bh, end); |
|---|
| 702 | 687 | if (grp_goal < 0) |
|---|
| .. | .. |
|---|
| 711 | 696 | ; |
|---|
| 712 | 697 | } |
|---|
| 713 | 698 | } |
|---|
| 714 | | - start = grp_goal; |
|---|
| 715 | 699 | |
|---|
| 716 | | - if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group), grp_goal, |
|---|
| 717 | | - bitmap_bh->b_data)) { |
|---|
| 718 | | - /* |
|---|
| 719 | | - * The block was allocated by another thread, or it was |
|---|
| 720 | | - * allocated and then freed by another thread |
|---|
| 721 | | - */ |
|---|
| 722 | | - start++; |
|---|
| 723 | | - grp_goal++; |
|---|
| 724 | | - if (start >= end) |
|---|
| 725 | | - goto fail_access; |
|---|
| 726 | | - goto repeat; |
|---|
| 727 | | - } |
|---|
| 728 | | - num++; |
|---|
| 729 | | - grp_goal++; |
|---|
| 730 | | - while (num < *count && grp_goal < end |
|---|
| 731 | | - && !ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group), |
|---|
| 700 | + for (; num < *count && grp_goal < end; grp_goal++) { |
|---|
| 701 | + if (ext2_set_bit_atomic(sb_bgl_lock(EXT2_SB(sb), group), |
|---|
| 732 | 702 | grp_goal, bitmap_bh->b_data)) { |
|---|
| 703 | + if (num == 0) |
|---|
| 704 | + continue; |
|---|
| 705 | + break; |
|---|
| 706 | + } |
|---|
| 733 | 707 | num++; |
|---|
| 734 | | - grp_goal++; |
|---|
| 735 | 708 | } |
|---|
| 709 | + |
|---|
| 710 | + if (num == 0) |
|---|
| 711 | + goto fail_access; |
|---|
| 712 | + |
|---|
| 736 | 713 | *count = num; |
|---|
| 737 | 714 | return grp_goal - num; |
|---|
| 738 | 715 | fail_access: |
|---|
| 739 | | - *count = num; |
|---|
| 740 | 716 | return -1; |
|---|
| 741 | 717 | } |
|---|
| 742 | 718 | |
|---|
| .. | .. |
|---|
| 754 | 730 | * but we will shift to the place where start_block is, |
|---|
| 755 | 731 | * then start from there, when looking for a reservable space. |
|---|
| 756 | 732 | * |
|---|
| 757 | | - * @size: the target new reservation window size |
|---|
| 733 | + * @sb: the super block. |
|---|
| 758 | 734 | * |
|---|
| 759 | | - * @group_first_block: the first block we consider to start |
|---|
| 760 | | - * the real search from |
|---|
| 735 | + * @start_block: the first block we consider to start the real search from |
|---|
| 761 | 736 | * |
|---|
| 762 | 737 | * @last_block: |
|---|
| 763 | 738 | * the maximum block number that our goal reservable space |
|---|
| .. | .. |
|---|
| 882 | 857 | * |
|---|
| 883 | 858 | * failed: we failed to find a reservation window in this group |
|---|
| 884 | 859 | * |
|---|
| 885 | | - * @rsv: the reservation |
|---|
| 860 | + * @my_rsv: the reservation |
|---|
| 886 | 861 | * |
|---|
| 887 | 862 | * @grp_goal: The goal (group-relative). It is where the search for a |
|---|
| 888 | 863 | * free reservable space should start from. |
|---|
| .. | .. |
|---|
| 908 | 883 | spinlock_t *rsv_lock = &EXT2_SB(sb)->s_rsv_window_lock; |
|---|
| 909 | 884 | |
|---|
| 910 | 885 | group_first_block = ext2_group_first_block_no(sb, group); |
|---|
| 911 | | - group_end_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1); |
|---|
| 886 | + group_end_block = ext2_group_last_block_no(sb, group); |
|---|
| 912 | 887 | |
|---|
| 913 | 888 | if (grp_goal < 0) |
|---|
| 914 | 889 | start_block = group_first_block; |
|---|
| .. | .. |
|---|
| 1115 | 1090 | * first block is the block number of the first block in this group |
|---|
| 1116 | 1091 | */ |
|---|
| 1117 | 1092 | group_first_block = ext2_group_first_block_no(sb, group); |
|---|
| 1118 | | - group_last_block = group_first_block + (EXT2_BLOCKS_PER_GROUP(sb) - 1); |
|---|
| 1093 | + group_last_block = ext2_group_last_block_no(sb, group); |
|---|
| 1119 | 1094 | |
|---|
| 1120 | 1095 | /* |
|---|
| 1121 | 1096 | * Basically we will allocate a new block from inode's reservation |
|---|
| .. | .. |
|---|
| 1195 | 1170 | |
|---|
| 1196 | 1171 | /* |
|---|
| 1197 | 1172 | * Returns 1 if the passed-in block region is valid; 0 if some part overlaps |
|---|
| 1198 | | - * with filesystem metadata blocksi. |
|---|
| 1173 | + * with filesystem metadata blocks. |
|---|
| 1199 | 1174 | */ |
|---|
| 1200 | 1175 | int ext2_data_block_valid(struct ext2_sb_info *sbi, ext2_fsblk_t start_blk, |
|---|
| 1201 | 1176 | unsigned int count) |
|---|
| 1202 | 1177 | { |
|---|
| 1203 | 1178 | if ((start_blk <= le32_to_cpu(sbi->s_es->s_first_data_block)) || |
|---|
| 1204 | | - (start_blk + count < start_blk) || |
|---|
| 1205 | | - (start_blk > le32_to_cpu(sbi->s_es->s_blocks_count))) |
|---|
| 1179 | + (start_blk + count - 1 < start_blk) || |
|---|
| 1180 | + (start_blk + count - 1 >= le32_to_cpu(sbi->s_es->s_blocks_count))) |
|---|
| 1206 | 1181 | return 0; |
|---|
| 1207 | 1182 | |
|---|
| 1208 | 1183 | /* Ensure we do not step over superblock */ |
|---|
| 1209 | 1184 | if ((start_blk <= sbi->s_sb_block) && |
|---|
| 1210 | | - (start_blk + count >= sbi->s_sb_block)) |
|---|
| 1185 | + (start_blk + count - 1 >= sbi->s_sb_block)) |
|---|
| 1211 | 1186 | return 0; |
|---|
| 1212 | | - |
|---|
| 1213 | 1187 | |
|---|
| 1214 | 1188 | return 1; |
|---|
| 1215 | 1189 | } |
|---|
| .. | .. |
|---|
| 1314 | 1288 | if (free_blocks > 0) { |
|---|
| 1315 | 1289 | grp_target_blk = ((goal - le32_to_cpu(es->s_first_data_block)) % |
|---|
| 1316 | 1290 | EXT2_BLOCKS_PER_GROUP(sb)); |
|---|
| 1291 | + /* |
|---|
| 1292 | + * In case we retry allocation (due to fs reservation not |
|---|
| 1293 | + * working out or fs corruption), the bitmap_bh is non-null |
|---|
| 1294 | + * pointer and we have to release it before calling |
|---|
| 1295 | + * read_block_bitmap(). |
|---|
| 1296 | + */ |
|---|
| 1297 | + brelse(bitmap_bh); |
|---|
| 1317 | 1298 | bitmap_bh = read_block_bitmap(sb, group_no); |
|---|
| 1318 | 1299 | if (!bitmap_bh) |
|---|
| 1319 | 1300 | goto io_error; |
|---|
| .. | .. |
|---|
| 1405 | 1386 | * use. So we may want to selectively mark some of the blocks |
|---|
| 1406 | 1387 | * as free |
|---|
| 1407 | 1388 | */ |
|---|
| 1389 | + num = *count; |
|---|
| 1408 | 1390 | goto retry_alloc; |
|---|
| 1409 | 1391 | } |
|---|
| 1410 | 1392 | |
|---|