124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * resize2fs.c --- ext2 main routine 324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 40cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1997, 1998 by Theodore Ts'o and 50cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * PowerQuest, Inc. 60cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * 70cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1999, 2000 by Theosore Ts'o 8efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %Begin-Header% 100cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 110cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * License. 1224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %End-Header% 1324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 1424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 1505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o/* 1605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Resizing a filesystem consists of the following phases: 1705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * 18a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1. Adjust superblock and write out new parts of the inode 1905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * table 20a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 2. Determine blocks which need to be relocated, and copy the 21a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * contents of blocks from their old locations to the new ones. 22a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 3. Scan the inode table, doing the following: 23a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * a. If blocks have been moved, update the block 24a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * pointers in the inodes and indirect blocks to 25a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * point at the new block locations. 26a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * b. If parts of the inode table need to be evacuated, 27a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * copy inodes from their old locations to their 28a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * new ones. 29a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * c. If (b) needs to be done, note which blocks contain 30a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * directory information, since we will need to 31a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the directory information. 32a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 4. Update the directory blocks with the new inode locations. 33a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 5. Move the inode tables, if necessary. 3405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 35a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 3624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o#include "resize2fs.h" 37b969b1b8a5c13992cadb026114731958644540d8Matthias Andree#include <time.h> 3824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 39546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o#ifdef __linux__ /* Kludge for debugging */ 40a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define RESIZE2FS_DEBUG 41a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 42a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 4386acdebd539864908127561034752082c86105e2Theodore Ts'ostatic void fix_uninit_block_bitmaps(ext2_filsys fs); 44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size); 45a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs); 46a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs); 47a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs); 48a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs); 49a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs); 509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs); 51a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs); 528a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeenstatic errcode_t fix_sb_journal_backup(ext2_filsys fs); 53e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t mark_table_blocks(ext2_filsys fs, 54e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap bmap); 55a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 56a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 57a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Some helper CPP macros 58a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 59e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_BLOCK_BM(fs, i, blk) ((blk) == ext2fs_block_bitmap_loc((fs),(i))) 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_INODE_BM(fs, i, blk) ((blk) == ext2fs_inode_bitmap_loc((fs),(i))) 61a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define IS_INODE_TB(fs, i, blk) (((blk) >= ext2fs_inode_table_loc((fs), (i))) && \ 63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((blk) < (ext2fs_inode_table_loc((fs), (i)) + \ 6465f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall (fs)->inode_blocks_per_group))) 651773c87c7e9ee5c4b8753919320d6d06910ea25bTheodore Ts'o 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* Some bigalloc helper macros which are more succint... */ 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define B2C(x) EXT2FS_B2C(fs, (x)) 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define C2B(x) EXT2FS_C2B(fs, (x)) 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define EQ_CLSTR(x, y) (B2C(x) == B2C(y)) 70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define LE_CLSTR(x, y) (B2C(x) <= B2C(y)) 71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define LT_CLSTR(x, y) (B2C(x) < B2C(y)) 72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define GE_CLSTR(x, y) (B2C(x) >= B2C(y)) 73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#define GT_CLSTR(x, y) (B2C(x) > B2C(y)) 74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int lazy_itable_init; 762d8c0c8a4fd99d79caa45afba1462dd5ae0f1e45Theodore Ts'o 77a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 78a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This is the top-level routine which does the dirty deed.... 79a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 80e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t resize_fs(ext2_filsys fs, blk64_t *new_size, int flags, 81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t (*progress)(ext2_resize_t rfs, int pass, 8286acdebd539864908127561034752082c86105e2Theodore Ts'o unsigned long cur, 8386acdebd539864908127561034752082c86105e2Theodore Ts'o unsigned long max_val)) 84a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 85a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 86a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall struct resource_track rtrack, overall_track; 8896cdb37e27ff101fb23cefe422b4f77fb55209beTheodore Ts'o 89a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 90a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Create the data structure 91a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 92c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), &rfs); 93a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 94a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 9565f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall 96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(rfs, 0, sizeof(struct ext2_resize_struct)); 977f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o fs->priv_data = rfs; 98a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs = fs; 99a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf = 0; 101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->progress = progress; 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&overall_track, "overall resize2fs", fs->io); 104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "read_bitmaps", fs->io); 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_read_bitmaps(fs); 106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto errout; 108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 110e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_state |= EXT2_ERROR_FS; 111e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_super_dirty(fs); 112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_flush(fs); 113e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 114e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "fix_uninit_block_bitmaps 1", fs->io); 115e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fix_uninit_block_bitmaps(fs); 116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dup_handle(fs, &rfs->new_fs); 118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 121e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "adjust_superblock", fs->io); 122116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o retval = adjust_superblock(rfs, *new_size); 123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1271eb31c4885156b595e6ceb4516cb1e1fb2d251fdTheodore Ts'o 128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "fix_uninit_block_bitmaps 2", fs->io); 12986acdebd539864908127561034752082c86105e2Theodore Ts'o fix_uninit_block_bitmaps(rfs->new_fs); 130e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 13186acdebd539864908127561034752082c86105e2Theodore Ts'o /* Clear the block bitmap uninit flag for the last block group */ 132e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_clear(rfs->new_fs, rfs->new_fs->group_desc_count - 1, 133e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_BG_BLOCK_UNINIT); 13486acdebd539864908127561034752082c86105e2Theodore Ts'o 135e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall *new_size = ext2fs_blocks_count(rfs->new_fs->super); 136116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o 137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "blocks_to_move", fs->io); 138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = blocks_to_move(rfs); 139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 145e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Number of free blocks: %llu/%llu, Needed: %llu\n", 146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(rfs->old_fs->super), 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(rfs->new_fs->super), 148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->needed_blocks); 149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 150efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "block_mover", fs->io); 152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = block_mover(rfs); 153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 155e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 157e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "inode_scan_and_fix", fs->io); 158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_scan_and_fix(rfs); 159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 161e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "inode_ref_fix", fs->io); 164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_ref_fix(rfs); 165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 167e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 169e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "move_itables", fs->io); 170a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = move_itables(rfs); 171a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 173e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 174a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 175e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "calculate_summary_stats", fs->io); 17664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o retval = ext2fs_calculate_summary_stats(rfs->new_fs); 17764ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o if (retval) 17864ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o goto errout; 179e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 180efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "fix_resize_inode", fs->io); 1829213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o retval = fix_resize_inode(rfs->new_fs); 1839213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) 1849213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o goto errout; 185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 1869213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall init_resource_track(&rtrack, "fix_sb_journal_backup", fs->io); 1888a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen retval = fix_sb_journal_backup(rfs->new_fs); 1898a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen if (retval) 1908a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen goto errout; 191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &rtrack, fs->io); 1928a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen 19396cdb37e27ff101fb23cefe422b4f77fb55209beTheodore Ts'o rfs->new_fs->super->s_state &= ~EXT2_ERROR_FS; 194efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o rfs->new_fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; 195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 196e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall print_resource_track(rfs, &overall_track, fs->io); 197a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_close(rfs->new_fs); 198a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 199a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 200a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 201a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 202efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 203a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->old_fs); 204a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 205c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&rfs->itable_buf); 206e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o if (rfs->reserve_blocks) 207e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o ext2fs_free_block_bitmap(rfs->reserve_blocks); 208e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o if (rfs->move_blocks) 209e2ca097fc641e9be2bbafc3db7fd96e4ac87387aTheodore Ts'o ext2fs_free_block_bitmap(rfs->move_blocks); 210c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&rfs); 211efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 212a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 213a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->new_fs) 216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->new_fs); 217a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 218c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&rfs->itable_buf); 219c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&rfs); 220a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 221a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 222a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 22386acdebd539864908127561034752082c86105e2Theodore Ts'o/* 22486acdebd539864908127561034752082c86105e2Theodore Ts'o * Clean up the bitmaps for unitialized bitmaps 22586acdebd539864908127561034752082c86105e2Theodore Ts'o */ 22686acdebd539864908127561034752082c86105e2Theodore Ts'ostatic void fix_uninit_block_bitmaps(ext2_filsys fs) 22786acdebd539864908127561034752082c86105e2Theodore Ts'o{ 228e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, lblk; 22986acdebd539864908127561034752082c86105e2Theodore Ts'o dgrp_t g; 230e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int i; 23186acdebd539864908127561034752082c86105e2Theodore Ts'o 23286acdebd539864908127561034752082c86105e2Theodore Ts'o if (!(EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 23386acdebd539864908127561034752082c86105e2Theodore Ts'o EXT4_FEATURE_RO_COMPAT_GDT_CSUM))) 23486acdebd539864908127561034752082c86105e2Theodore Ts'o return; 23586acdebd539864908127561034752082c86105e2Theodore Ts'o 23686acdebd539864908127561034752082c86105e2Theodore Ts'o for (g=0; g < fs->group_desc_count; g++) { 237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!(ext2fs_bg_flags_test(fs, g, EXT2_BG_BLOCK_UNINIT))) 23886acdebd539864908127561034752082c86105e2Theodore Ts'o continue; 23986acdebd539864908127561034752082c86105e2Theodore Ts'o 240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_group_first_block2(fs, g); 241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lblk = ext2fs_group_last_block2(fs, g); 242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_unmark_block_bitmap_range2(fs->block_map, blk, 243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lblk - blk + 1); 244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_reserve_super_and_bgd(fs, g, fs->block_map); 246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(fs->block_map, 247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc(fs, g)); 248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(fs->block_map, 249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc(fs, g)); 250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0, blk = ext2fs_inode_table_loc(fs, g); 251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i < (unsigned int) fs->inode_blocks_per_group; 252e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i++, blk++) 253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(fs->block_map, blk); 25486acdebd539864908127561034752082c86105e2Theodore Ts'o } 25586acdebd539864908127561034752082c86105e2Theodore Ts'o} 25686acdebd539864908127561034752082c86105e2Theodore Ts'o 257a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 258a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 259a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 1. 260a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust the in-memory superblock information, and 262a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * initialize any new parts of the inode table. The new parts of the 263a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode table are created in virgin disk space, so we can abort here 264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * without any side effects. 265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 266a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 267a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 26824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 2699227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o * If the group descriptor's bitmap and inode table blocks are valid, 270c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * release them in the new filesystem data structure, and mark them as 271c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * reserved so the old inode table blocks don't get overwritten. 2729227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o */ 273c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'ostatic void free_gdp_blocks(ext2_filsys fs, 274c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o ext2fs_block_bitmap reserve_blocks, 275e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_filsys old_fs, 276e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t group) 2779227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o{ 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 2799227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o int j; 2809227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_block_bitmap_loc(old_fs, group); 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk && 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk < ext2fs_blocks_count(fs->super))) { 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, -1); 285e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(reserve_blocks, blk); 286c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o } 2879227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o 288e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_inode_bitmap_loc(old_fs, group); 289e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk && 290e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk < ext2fs_blocks_count(fs->super))) { 291e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, -1); 292e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(reserve_blocks, blk); 293c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o } 2949227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o 295e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_inode_table_loc(old_fs, group); 296e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk == 0 || 297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk >= ext2fs_blocks_count(fs->super))) 2989227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o return; 2999227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o 300e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j = 0; 3019227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o j < fs->inode_blocks_per_group; j++, blk++) { 302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk >= ext2fs_blocks_count(fs->super)) 3039227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o break; 304e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, -1); 305e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(reserve_blocks, blk); 3069227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o } 3079227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o} 3089227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o 3099227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o/* 310bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine is shared by the online and offline resize routines. 311bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * All of the information which is adjusted in memory is done here. 31224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 313c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'oerrcode_t adjust_fs_info(ext2_filsys fs, ext2_filsys old_fs, 314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap reserve_blocks, blk64_t new_size) 31524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 31624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 317e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t overhead = 0; 318e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t rem; 319e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, group_block; 320e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t real_end; 321e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t old_numblocks, numblocks, adjblocks; 322e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned long i, j, old_desc_blocks; 323544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int meta_bg, meta_bg_size; 32474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o int has_super, csum_flag; 325de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger unsigned long long new_inodes; /* u64 to check for overflow */ 3269ff8ece57d46a9419fc60057547810824881bb45Theodore Ts'o double percent; 327bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count_set(fs->super, new_size); 32924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 33024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'oretry: 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) - 33269022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o fs->super->s_first_data_block, 33369022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o EXT2_BLOCKS_PER_GROUP(fs->super)); 33424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (fs->group_desc_count == 0) 33524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 336efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, 33769022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o EXT2_DESC_PER_BLOCK(fs->super)); 33824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 33924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 34024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Overhead is the number of bookkeeping blocks per group. It 34124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * includes the superblock backup, the group descriptor 34224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * backups, the inode bitmap, the block bitmap, and the inode 34324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * table. 34424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 3459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o overhead = (int) (2 + fs->inode_blocks_per_group); 3469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 3479213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (ext2fs_bg_has_super(fs, fs->group_desc_count - 1)) 348efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o overhead += 1 + fs->desc_blocks + 3499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o fs->super->s_reserved_gdt_blocks; 3509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 35124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 35224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * See if the last group is big enough to support the 35324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * necessary data structures. If not, we need to get rid of 35424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * it. 35524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rem = (ext2fs_blocks_count(fs->super) - fs->super->s_first_data_block) % 35724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_per_group; 35824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if ((fs->group_desc_count == 1) && rem && (rem < overhead)) 35924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((fs->group_desc_count > 1) && rem && (rem < overhead+50)) { 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count_set(fs->super, 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count(fs->super) - rem); 36324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o goto retry; 36424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 36524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 36624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of inodes 36724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 368de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger new_inodes =(unsigned long long) fs->super->s_inodes_per_group * fs->group_desc_count; 369f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen if (new_inodes > ~0U) { 370f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen fprintf(stderr, _("inodes (%llu) must be less than %u"), 371f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen new_inodes, ~0U); 372f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen return EXT2_ET_TOO_MANY_INODES; 373f335864338a6fbce8134a445ffdd0cdeb3f3f1bcEric Sandeen } 37424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count = fs->super->s_inodes_per_group * 37524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->group_desc_count; 37624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 37724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 37824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of free blocks 37924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_blocks_count(old_fs->super); 381e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk > ext2fs_blocks_count(fs->super)) 382e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count_set(fs->super, 383e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(fs->super) - 384e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk - ext2fs_blocks_count(fs->super))); 38524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o else 386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count_set(fs->super, 387e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(fs->super) + 388e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (ext2fs_blocks_count(fs->super) - blk)); 38924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 39024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 391c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Adjust the number of reserved blocks 392c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall percent = (ext2fs_r_blocks_count(old_fs->super) * 100.0) / 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count(old_fs->super); 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_r_blocks_count_set(fs->super, 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (percent * ext2fs_blocks_count(fs->super) / 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 100.0)); 398c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 399c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 40024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the bitmaps for size 40124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_resize_inode_bitmap2(fs->super->s_inodes_count, 40324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count, 40424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->inode_map); 405c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 406efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall real_end = (((blk64_t) EXT2_BLOCKS_PER_GROUP(fs->super) * 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->group_desc_count)) - 1 + 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_first_data_block; 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_resize_block_bitmap2(new_size - 1, 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall real_end, fs->block_map); 41265f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall if (retval) goto errout; 413f026f1a37061a021f7188c9e45d0fbff1bde9e60Theodore Ts'o 414f026f1a37061a021f7188c9e45d0fbff1bde9e60Theodore Ts'o /* 415e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If we are growing the file system, also grow the size of 416e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * the reserve_blocks bitmap 417e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (reserve_blocks && new_size > ext2fs_blocks_count(old_fs->super)) { 419e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_resize_block_bitmap2(new_size - 1, 420e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall real_end, reserve_blocks); 421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) goto errout; 422e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 423e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 424e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 42524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Reallocate the group descriptors as necessary. 42624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 427bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (old_fs->desc_blocks != fs->desc_blocks) { 428bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = ext2fs_resize_mem(old_fs->desc_blocks * 42976f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o fs->blocksize, 43076f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o fs->desc_blocks * fs->blocksize, 431c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &fs->group_desc); 432ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 433a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 434efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (fs->desc_blocks > old_fs->desc_blocks) 435efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o memset((char *) fs->group_desc + 436bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o (old_fs->desc_blocks * fs->blocksize), 0, 437bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o (fs->desc_blocks - old_fs->desc_blocks) * 4382787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o fs->blocksize); 43924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 4401e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 4411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 4429213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * If the resize_inode feature is set, and we are changing the 4439213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * number of descriptor blocks, then adjust 4449213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * s_reserved_gdt_blocks if possible to avoid needing to move 4459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * the inode table either now or in the future. 4469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o */ 447efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if ((fs->super->s_feature_compat & 4489213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o EXT2_FEATURE_COMPAT_RESIZE_INODE) && 449bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o (old_fs->desc_blocks != fs->desc_blocks)) { 4509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o int new; 4519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 452efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o new = ((int) fs->super->s_reserved_gdt_blocks) + 453bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o (old_fs->desc_blocks - fs->desc_blocks); 4549213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (new < 0) 4559213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o new = 0; 456de8f3a76218255e443ba57dec5d74850180fa75dAndreas Dilger if (new > (int) fs->blocksize/4) 4579213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o new = fs->blocksize/4; 4589213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o fs->super->s_reserved_gdt_blocks = new; 4599213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o } 4609213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 4619213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o /* 462c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * If we are shrinking the number of block groups, we're done 463c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o * and can exit now. 4641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 465bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (old_fs->group_desc_count > fs->group_desc_count) { 4669227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o /* 4679227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o * Check the block groups that we are chopping off 4689227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o * and free any blocks associated with their metadata 4699227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o */ 4709227c5bbbd0861878ae73f7dceb4deb9e9f06a3cTheodore Ts'o for (i = fs->group_desc_count; 471e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i < old_fs->group_desc_count; i++) 472e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall free_gdp_blocks(fs, reserve_blocks, old_fs, i); 473c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 474c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 475c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 476bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 477a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 478a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Fix the count of the last (old) block group 479a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_numblocks = (ext2fs_blocks_count(old_fs->super) - 481bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o old_fs->super->s_first_data_block) % 482bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o old_fs->super->s_blocks_per_group; 4831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!old_numblocks) 484bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o old_numblocks = old_fs->super->s_blocks_per_group; 485bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (old_fs->group_desc_count == fs->group_desc_count) { 486e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall numblocks = (ext2fs_blocks_count(fs->super) - 487bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o fs->super->s_first_data_block) % 488bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o fs->super->s_blocks_per_group; 4891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!numblocks) 490bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 4911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } else 492bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 493bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o i = old_fs->group_desc_count - 1; 494e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_free_blocks_count_set(fs, i, ext2fs_bg_free_blocks_count(fs, i) + (numblocks - old_numblocks)); 495236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos ext2fs_group_desc_csum_set(fs, i); 496236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos 4971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 498a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * If the number of block groups is staying the same, we're 499a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * done and can exit now. (If the number block groups is 500a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * shrinking, we had exited earlier.) 5011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 502bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (old_fs->group_desc_count >= fs->group_desc_count) { 503c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 504c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 505c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 506bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 507a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 508a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Initialize the new block group descriptors 509a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall group_block = ext2fs_group_first_block2(fs, 511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_fs->group_desc_count); 51274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o csum_flag = EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 51374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o EXT4_FEATURE_RO_COMPAT_GDT_CSUM); 514e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (access("/sys/fs/ext4/features/lazy_itable_init", F_OK) == 0) 515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall lazy_itable_init = 1; 51676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 51776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_desc_blocks = fs->super->s_first_meta_bg; 51876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o else 519efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o old_desc_blocks = fs->desc_blocks + 5209213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o fs->super->s_reserved_gdt_blocks; 521e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 522e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If we changed the number of block_group descriptor blocks, 524e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * we need to make sure they are all marked as reserved in the 525e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * file systems's block allocation map. 526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 527e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < old_fs->group_desc_count; i++) 528e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_reserve_super_and_bgd(fs, i, fs->block_map); 529e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 530bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o for (i = old_fs->group_desc_count; 5311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o i < fs->group_desc_count; i++) { 532e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall memset(ext2fs_group_desc(fs, fs->group_desc, i), 0, 5331e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o sizeof(struct ext2_group_desc)); 5341e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks = 0; 5351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 536e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_zap(fs, i); 537e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (csum_flag) { 538e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_UNINIT); 539e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!lazy_itable_init) 540e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_set(fs, i, 541e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_BG_INODE_ZEROED); 542e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_itable_unused_set(fs, i, 543e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_inodes_per_group); 5442d8c0c8a4fd99d79caa45afba1462dd5ae0f1e45Theodore Ts'o } 54598f4547198b369bef7e41eb7ce4a16855726c393Eric Sandeen 546e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall numblocks = ext2fs_group_blocks_count(fs, i); 547e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((i < fs->group_desc_count - 1) && csum_flag) 548e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_set(fs, i, EXT2_BG_BLOCK_UNINIT); 549e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 55076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = ext2fs_bg_has_super(fs, i); 55176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) { 552e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, group_block, +1); 55376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o adjblocks++; 55476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 555f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 55676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg = i / meta_bg_size; 55776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (!(fs->super->s_feature_incompat & 55876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) || 55976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o (meta_bg < fs->super->s_first_meta_bg)) { 56076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) { 56176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o for (j=0; j < old_desc_blocks; j++) 562e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, 56374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o group_block + 1 + j, +1); 56476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o adjblocks += old_desc_blocks; 56576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 56676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 56776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 56876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = 1; 56976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (((i % meta_bg_size) == 0) || 57076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == 1) || 57176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == (meta_bg_size-1))) 572e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, 57374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o group_block + has_super, +1); 57424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 575efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks += 2 + fs->inode_blocks_per_group; 577efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 5781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks -= adjblocks; 579e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count_set(fs->super, 580e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(fs->super) - adjblocks); 5811e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_free_inodes_count += 5821e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_inodes_per_group; 583e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_free_blocks_count_set(fs, i, numblocks); 584e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_free_inodes_count_set(fs, i, 585e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_inodes_per_group); 586e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_used_dirs_count_set(fs, i, 0); 587236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos ext2fs_group_desc_csum_set(fs, i); 58824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 5891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 0); 590c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 59124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 592bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o group_block += fs->super->s_blocks_per_group; 593bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o } 594bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = 0; 595bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 596e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 597e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Mark all of the metadata blocks as reserved so they won't 598e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * get allocated by the call to ext2fs_allocate_group_table() 599e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * in blocks_to_move(), where we allocate new blocks to 600e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * replace those allocation bitmap and inode table blocks 601e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * which have to get relocated to make space for an increased 602e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * number of the block group descriptors. 603e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 604e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (reserve_blocks) 605e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall mark_table_blocks(fs, reserve_blocks); 606e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 607bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'oerrout: 608bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o return (retval); 609bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o} 610bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 611bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o/* 612bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * This routine adjusts the superblock and other data structures, both 613bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * in disk as well as in memory... 614bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */ 615e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic errcode_t adjust_superblock(ext2_resize_t rfs, blk64_t new_size) 616bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o{ 617bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o ext2_filsys fs; 618bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o int adj = 0; 619bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o errcode_t retval; 620e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t group_block; 621bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o unsigned long i; 622bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o unsigned long max_group; 623efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 624bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o fs = rfs->new_fs; 625bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o ext2fs_mark_super_dirty(fs); 626bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o ext2fs_mark_bb_dirty(fs); 627bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o ext2fs_mark_ib_dirty(fs); 628bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 629c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"), 630c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o &rfs->reserve_blocks); 631c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o if (retval) 632c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o return retval; 633c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o 634c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o retval = adjust_fs_info(fs, rfs->old_fs, rfs->reserve_blocks, new_size); 635bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (retval) 636bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 637bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 638bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o /* 639bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * Check to make sure there are enough inodes 640bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */ 641bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if ((rfs->old_fs->super->s_inodes_count - 642bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o rfs->old_fs->super->s_free_inodes_count) > 643bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o rfs->new_fs->super->s_inodes_count) { 644bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = ENOSPC; 645bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 646bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o } 647bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 648bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o /* 649bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * If we are shrinking the number block groups, we're done and 650bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * can exit now. 651bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */ 652bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (rfs->old_fs->group_desc_count > fs->group_desc_count) { 653bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = 0; 654bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 655bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o } 656bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 657bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o /* 658bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * If the number of block groups is staying the same, we're 659bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * done and can exit now. (If the number block groups is 660bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o * shrinking, we had exited earlier.) 661bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */ 662bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (rfs->old_fs->group_desc_count >= fs->group_desc_count) { 663bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = 0; 664bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 665bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o } 666bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 667bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o /* 668e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If we are using uninit_bg (aka GDT_CSUM) and the kernel 669e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * supports lazy inode initialization, we can skip 670e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * initializing the inode table. 671e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 672e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (lazy_itable_init && 673e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 674e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 675e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = 0; 676e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto errout; 677e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 678e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 679e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 680e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Initialize the inode table 681bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o */ 682e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o retval = ext2fs_get_array(fs->blocksize, fs->inode_blocks_per_group, 683bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o &rfs->itable_buf); 684bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (retval) 685bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 686bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 687bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group); 688e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall group_block = ext2fs_group_first_block2(fs, 689e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->old_fs->group_desc_count); 690bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o adj = rfs->old_fs->group_desc_count; 691bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o max_group = fs->group_desc_count - adj; 692bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (rfs->progress) { 693bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 694bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o 0, max_group); 695bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o if (retval) 696bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o goto errout; 697bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o } 698bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o for (i = rfs->old_fs->group_desc_count; 699bf69235ad0073c80386b70caba0e1b58e5f85697Theodore Ts'o i < fs->group_desc_count; i++) { 70005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 70105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Write out the new inode table 70205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 703e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, 704e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc(fs, i), 705e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group, 706e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->itable_buf); 707c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 708c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 709a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 7103b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 7113b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 7123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o i - adj + 1, max_group); 7133b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 7143b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 7153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 7161e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block += fs->super->s_blocks_per_group; 71724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 718c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o io_channel_flush(fs->io); 719c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 720c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 721c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 722c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 723c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o} 724c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 725a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 726a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 727a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 2. 728a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 729a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust determine which blocks need to be moved, in 730a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * blocks_to_move(). We then copy the blocks to their ultimate new 731a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * destinations using block_mover(). Since we are copying blocks to 732a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * their new locations, again during this pass we can abort without 733a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * any problems. 734a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 735a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 736a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 737c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o/* 738c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * This helper function creates a block bitmap with all of the 739c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * filesystem meta-data blocks. 740c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 741c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t mark_table_blocks(ext2_filsys fs, 74264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o ext2fs_block_bitmap bmap) 743c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o{ 744544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o dgrp_t i; 745e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 746c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 747c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (i = 0; i < fs->group_desc_count; i++) { 74864ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o ext2fs_reserve_super_and_bgd(fs, i, bmap); 749efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 750c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 751c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark the blocks used for the inode table 752c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 753e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_inode_table_loc(fs, i); 754e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk) 755e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap_range2(bmap, blk, 756e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group); 757efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 758c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 759efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Mark block used for the block bitmap 760c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 761e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_block_bitmap_loc(fs, i); 762e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk) 763e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(bmap, blk); 76464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o 765c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 766efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Mark block used for the inode bitmap 767c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 768e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_inode_bitmap_loc(fs, i); 769e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blk) 770e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(bmap, blk); 771c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 7721e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return 0; 77324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o} 77424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 77524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 77676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * This function checks to see if a particular block (either a 77776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * superblock or a block group descriptor) overlaps with an inode or 77876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * block bitmap block, or with the inode table. 77976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */ 78076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'ostatic void mark_fs_metablock(ext2_resize_t rfs, 78176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_block_bitmap meta_bmap, 782e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int group, blk64_t blk) 78376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o{ 78476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2_filsys fs = rfs->new_fs; 785efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 786e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 787e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, +1); 78876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 78976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o /* 79076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * Check to see if we overlap with the inode or block bitmap, 79176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * or the inode tables. If not, and the block is in use, then 79276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * mark it as a block to be moved. 79376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */ 79476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (IS_BLOCK_BM(fs, group, blk)) { 795e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc_set(fs, group, 0); 79676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 798e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (IS_INODE_BM(fs, group, blk)) { 800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc_set(fs, group, 0); 80176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 802e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 803e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (IS_INODE_TB(fs, group, blk)) { 805e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc_set(fs, group, 0); 80676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 807e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 808e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 809e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 810e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t i; 811e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 812e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i=0; i < rfs->old_fs->group_desc_count; i++) { 813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (IS_BLOCK_BM(fs, i, blk)) { 814e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc_set(fs, i, 0); 815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->needed_blocks++; 816e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 818e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (IS_INODE_BM(fs, i, blk)) { 819e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc_set(fs, i, 0); 820e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->needed_blocks++; 821e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 822e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 823e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (IS_INODE_TB(fs, i, blk)) { 824e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc_set(fs, i, 0); 825e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->needed_blocks++; 826e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return; 827e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 828e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 830e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 831e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 832e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT))) { 83386acdebd539864908127561034752082c86105e2Theodore Ts'o /* 83486acdebd539864908127561034752082c86105e2Theodore Ts'o * If the block bitmap is uninitialized, which means 83586acdebd539864908127561034752082c86105e2Theodore Ts'o * nothing other than standard metadata in use. 83686acdebd539864908127561034752082c86105e2Theodore Ts'o */ 83786acdebd539864908127561034752082c86105e2Theodore Ts'o return; 838e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } else if (ext2fs_test_block_bitmap2(rfs->old_fs->block_map, blk) && 839e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_block_bitmap2(meta_bmap, blk)) { 840e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->move_blocks, blk); 84176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 84276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 84376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o} 84476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 84576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 84676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o/* 84724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine marks and unmarks reserved blocks in the new block 84824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * bitmap. It also determines which blocks need to be moved and 84924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * places this information into the move_blocks bitmap. 85024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 851c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs) 85224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 853544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int j, has_super; 85486acdebd539864908127561034752082c86105e2Theodore Ts'o dgrp_t i, max_groups, g; 855e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, group_blk; 856e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t old_blocks, new_blocks; 857e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t new_size; 858544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int meta_bg, meta_bg_size; 85924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 860c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2_filsys fs, old_fs; 861c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap meta_bmap; 862e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int flex_bg; 86324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 864c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 865c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o old_fs = rfs->old_fs; 866e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_blocks_count(old_fs->super) > ext2fs_blocks_count(fs->super)) 867c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->old_fs; 868efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 869a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"), 870c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o &rfs->move_blocks); 871c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 872c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 873c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 874efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"), 87564ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o &meta_bmap); 87664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o if (retval) 87764ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o return retval; 878efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 87964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o retval = mark_table_blocks(old_fs, meta_bmap); 880c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 881c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 882c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 883c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 884efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 8851e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 886e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * If we're shrinking the filesystem, we need to move any 887e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * group's metadata blocks (either allocation bitmaps or the 888e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * inode table) which are beyond the end of the new 889e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * filesystem. 890e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 891e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_size = ext2fs_blocks_count(fs->super); 892e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new_size < ext2fs_blocks_count(old_fs->super)) { 893e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (g = 0; g < fs->group_desc_count; g++) { 894e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int realloc = 0; 895e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 896e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * ext2fs_allocate_group_table will re-allocate any 897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * metadata blocks whose location is set to zero. 898e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 899e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_block_bitmap_loc(fs, g) >= new_size) { 900e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc_set(fs, g, 0); 901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall realloc = 1; 902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 903e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_bitmap_loc(fs, g) >= new_size) { 904e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc_set(fs, g, 0); 905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall realloc = 1; 906e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 907e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((ext2fs_inode_table_loc(fs, g) + 908e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group) > new_size) { 909e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc_set(fs, g, 0); 910e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall realloc = 1; 911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (realloc) { 914e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_allocate_group_table(fs, g, 0); 915e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) 916e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return retval; 917e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 918e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 9221e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * If we're shrinking the filesystem, we need to move all of 9231e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * the blocks that don't fit any more 9241e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = ext2fs_blocks_count(fs->super); 926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk < ext2fs_blocks_count(old_fs->super); blk++) { 927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall g = ext2fs_group_of_blk2(fs, blk); 92886acdebd539864908127561034752082c86105e2Theodore Ts'o if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 92986acdebd539864908127561034752082c86105e2Theodore Ts'o EXT4_FEATURE_RO_COMPAT_GDT_CSUM) && 930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_test(old_fs, g, EXT2_BG_BLOCK_UNINIT)) { 93186acdebd539864908127561034752082c86105e2Theodore Ts'o /* 93286acdebd539864908127561034752082c86105e2Theodore Ts'o * The block bitmap is uninitialized, so skip 93386acdebd539864908127561034752082c86105e2Theodore Ts'o * to the next block group. 93486acdebd539864908127561034752082c86105e2Theodore Ts'o */ 935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_group_first_block2(fs, g+1) - 1; 93686acdebd539864908127561034752082c86105e2Theodore Ts'o continue; 93786acdebd539864908127561034752082c86105e2Theodore Ts'o } 938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_block_bitmap2(meta_bmap, blk)) { 940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->move_blocks, blk); 9411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->needed_blocks++; 942c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 943e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 9441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 945efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 94676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) { 94776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_blocks = old_fs->super->s_first_meta_bg; 94876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o new_blocks = fs->super->s_first_meta_bg; 94976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 9509213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o old_blocks = old_fs->desc_blocks + old_fs->super->s_reserved_gdt_blocks; 9519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o new_blocks = fs->desc_blocks + fs->super->s_reserved_gdt_blocks; 95276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 953efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 954c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (old_blocks == new_blocks) { 955c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 956c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 957c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 95824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 9591333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = fs->group_desc_count; 9601333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o if (max_groups > old_fs->group_desc_count) 9611333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = old_fs->group_desc_count; 962c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o group_blk = old_fs->super->s_first_data_block; 96324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 96424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're reducing the number of descriptor blocks, this 96524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * makes life easy. :-) We just have to mark some extra 96624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * blocks as free. 96724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 96824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (old_blocks > new_blocks) { 9691333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i = 0; i < max_groups; i++) { 9701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!ext2fs_bg_has_super(fs, i)) { 9711e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 97224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o continue; 97324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 974c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (blk = group_blk+1+new_blocks; 975c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk < group_blk+1+old_blocks; blk++) { 976e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, -1); 977052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o rfs->needed_blocks--; 978052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 9791e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 98024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 981c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 982c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 98324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 98424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 98524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're increasing the number of descriptor blocks, life 986efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * gets interesting.... 98724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 988f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement meta_bg_size = EXT2_DESC_PER_BLOCK(fs->super); 989e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall flex_bg = fs->super->s_feature_incompat & 990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_INCOMPAT_FLEX_BG; 991e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* first reserve all of the existing fs meta blocks */ 9921333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i = 0; i < max_groups; i++) { 99376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = ext2fs_bg_has_super(fs, i); 99476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 99576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, i, group_blk); 99676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 99776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg = i / meta_bg_size; 99876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (!(fs->super->s_feature_incompat & 99976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) || 100076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o (meta_bg < fs->super->s_first_meta_bg)) { 1001424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o if (has_super) { 1002424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o for (blk = group_blk+1; 1003424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o blk < group_blk + 1 + new_blocks; blk++) 1004efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, 1005424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o i, blk); 1006424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o } 100776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 100876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 100976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = 1; 101076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (((i % meta_bg_size) == 0) || 101176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == 1) || 101276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == (meta_bg_size-1))) 101376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, i, 101476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o group_blk + has_super); 101524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 101676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 10171e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 1018c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Reserve the existing meta blocks that we know 1019c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * aren't to be moved. 102065f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall * 1021e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * For flex_bg file systems, in order to avoid 1022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * overwriting fs metadata (especially inode table 1023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * blocks) belonging to a different block group when 1024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * we are relocating the inode tables, we need to 1025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * reserve all existing fs metadata blocks. 102665f0aab98b20b5994a726ab90d355248bcddfffdJP Abgrall */ 1027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_block_bitmap_loc(fs, i)) 1028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc(fs, i)); 1030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (flex_bg && i < old_fs->group_desc_count) 1031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc(old_fs, i)); 1033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_bitmap_loc(fs, i)) 1035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc(fs, i)); 1037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (flex_bg && i < old_fs->group_desc_count) 1038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, 1039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc(old_fs, i)); 1040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_table_loc(fs, i)) 1042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1043e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc(fs, i), 1044e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group); 1045e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (flex_bg && i < old_fs->group_desc_count) 1046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap_range2(rfs->reserve_blocks, 1047e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc(old_fs, i), 1048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_fs->inode_blocks_per_group); 1049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall group_blk += rfs->new_fs->super->s_blocks_per_group; 1051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 1052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* Allocate the missing data structures */ 1054e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (i = 0; i < max_groups; i++) { 1055e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_table_loc(fs, i) && 1056e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_bitmap_loc(fs, i) && 1057e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_bitmap_loc(fs, i)) 1058e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; 1059e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 10601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 10611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->reserve_blocks); 10621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 1063c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 106424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 10651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 1066c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * For those structures that have changed, we need to 1067c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * do bookkeepping. 10681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 1069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_block_bitmap_loc(old_fs, i) != 1070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk = ext2fs_block_bitmap_loc(fs, i))) { 1071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, +1); 1072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1073e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1074e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->move_blocks, 1075c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 1076c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 1077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_bitmap_loc(old_fs, i) != 1078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (blk = ext2fs_inode_bitmap_loc(fs, i))) { 1079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, +1); 1080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1082e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->move_blocks, 1083c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 1084c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 108524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 1086052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1087052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * The inode table, if we need to relocate it, is 1088052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * handled specially. We have to reserve the blocks 1089052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * for both the old and the new inode table, since we 1090052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * can't have the inode table be destroyed during the 1091052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block relocation phase. 1092052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1093e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_table_loc(fs, i) == ext2fs_inode_table_loc(old_fs, i)) 1094e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall continue; /* inode table not moved */ 1095052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1096c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->needed_blocks += fs->inode_blocks_per_group; 1097052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1098052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1099052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Mark the new inode table as in use in the new block 1100efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * allocation bitmap, and move any blocks that might 1101c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * be necessary. 1102052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = ext2fs_inode_table_loc(fs, i), j=0; 1104c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) { 1105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, +1); 1106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(old_fs->block_map, blk) && 1107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_test_block_bitmap2(meta_bmap, blk)) 1108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->move_blocks, 1109c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 1110c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 1111efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 11121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 1113052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Make sure the old inode table is reserved in the 1114052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block reservation bitmap. 11151e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 1116e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 1117052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 1118e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->reserve_blocks, blk); 11191e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 1120c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 1121c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1122c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 1123c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (meta_bmap) 1124c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_free_block_bitmap(meta_bmap); 1125efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1126c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 11271e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o} 112824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 1129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 1130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This helper function tries to allocate a new block. We try to 1131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * avoid hitting the original group descriptor blocks at least at 1132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * first, since we want to make it possible to recover from a badly 1133a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * aborted resize operation as much as possible. 1134a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In the future, I may further modify this routine to balance out 1136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * where we get the new blocks across the various block groups. 1137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Ideally we would allocate blocks that corresponded with the block 1138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * group of the containing inode, and keep contiguous blocks 1139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * together. However, this very difficult to do efficiently, since we 1140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * don't have the necessary information up front. 1141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define AVOID_OLD 1 1144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define DESPERATION 2 1145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic void init_block_alloc(ext2_resize_t rfs) 1147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = AVOID_OLD; 1149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = rfs->new_fs->super->s_first_data_block; 11502bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#if 0 11512bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* HACK for testing */ 1152e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_blocks_count(rfs->new_fs->super) > 1153e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count(rfs->old_fs->super)) 1154e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->new_blk = ext2fs_blocks_count(rfs->old_fs->super); 11552bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#endif 1156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1158e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic blk64_t get_new_block(ext2_resize_t rfs) 1159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 1161efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1163e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (rfs->new_blk >= ext2fs_blocks_count(fs->super)) { 1164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->alloc_state == DESPERATION) 1165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1167a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 1169f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o printf("Going into desperation mode " 1170f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o "for block allocations\n"); 1171efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#endif 1172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = DESPERATION; 1173a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = fs->super->s_first_data_block; 1174a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 1175a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_test_block_bitmap2(fs->block_map, rfs->new_blk) || 1177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_test_block_bitmap2(rfs->reserve_blocks, 1178a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk) || 1179a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ((rfs->alloc_state == AVOID_OLD) && 1180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (rfs->new_blk < ext2fs_blocks_count(rfs->old_fs->super)) && 1181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_test_block_bitmap2(rfs->old_fs->block_map, 1182a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk))) { 1183a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk++; 1184a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 1185a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1186a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return rfs->new_blk; 1187a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1188a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1189a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 11907f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'ostatic errcode_t resize2fs_get_alloc_block(ext2_filsys fs, blk64_t goal, 11917f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o blk64_t *ret) 11927f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o{ 11937f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o ext2_resize_t rfs = (ext2_resize_t) fs->priv_data; 1194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 11957f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o 11967f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o blk = get_new_block(rfs); 11977f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o if (!blk) 11987f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o return ENOSPC; 11997f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o 12007f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o#ifdef RESIZE2FS_DEBUG 12017f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o if (rfs->flags & 0xF) 1202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("get_alloc_block allocating %llu\n", blk); 12037f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o#endif 12047f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o 1205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->old_fs->block_map, blk); 1206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_block_bitmap2(rfs->new_fs->block_map, blk); 12077f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o *ret = (blk64_t) blk; 12087f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o return 0; 12097f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o} 12107f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o 1211a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs) 1212a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1213e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk, old_blk, new_blk; 1214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 1215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys old_fs = rfs->old_fs; 1216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1217e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 size; 1218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int c; 1219a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int to_move, moved; 12207d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2_badblocks_list badblock_list = 0; 12217d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o int bb_modified = 0; 1222efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 12237f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o fs->get_alloc_block = resize2fs_get_alloc_block; 12247f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o old_fs->get_alloc_block = resize2fs_get_alloc_block; 12257f9c96ee74315388d758675f69a930b9990e0789Theodore Ts'o 12267d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o retval = ext2fs_read_bb_inode(old_fs, &badblock_list); 12277d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (retval) 12287d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o return retval; 1229a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1230a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = fs->super->s_first_data_block; 1231a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->itable_buf) { 1232e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o retval = ext2fs_get_array(fs->blocksize, 1233a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->inode_blocks_per_group, 1234c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &rfs->itable_buf); 1235a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1236a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1237a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1238a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->bmap, 0); 1239a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1240a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1241a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1242a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1243a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * The first step is to figure out where all of the blocks 1244a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will go. 1245a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1246a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move = moved = 0; 1247a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o init_block_alloc(rfs); 1248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = B2C(old_fs->super->s_first_data_block); 1249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk < ext2fs_blocks_count(old_fs->super); 1250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk += EXT2FS_CLUSTER_RATIO(fs)) { 1251e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_test_block_bitmap2(old_fs->block_map, blk)) 1252a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 1253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!ext2fs_test_block_bitmap2(rfs->move_blocks, blk)) 1254a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 12557d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (ext2fs_badblocks_list_test(badblock_list, blk)) { 12567d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2fs_badblocks_list_del(badblock_list, blk); 12577d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o bb_modified++; 12587d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o continue; 12597d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o } 1260a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = get_new_block(rfs); 1262a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_blk) { 1263a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 1264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, new_blk, +1); 1267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_add_extent_entry(rfs->bmap, B2C(blk), B2C(new_blk)); 1268a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move++; 1269a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1270efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1271a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (to_move == 0) { 1272cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o if (rfs->bmap) { 1273cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o ext2fs_free_extent_table(rfs->bmap); 1274cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o rfs->bmap = 0; 1275cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o } 1276a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = 0; 1277a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1278a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1279a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Step two is to actually move the blocks 1282a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1283a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, 0, 0, 0); 1284a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1285a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 12863b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 12873b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS, 12883b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 12893b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 12903b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 12913b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1292a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1293a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size); 1294a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1295a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!size) 1296a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 1297e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_blk = C2B(old_blk); 1298e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_blk = C2B(new_blk); 1299e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall size = C2B(size); 1300a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1301a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 1302e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Moving %llu blocks %llu->%llu\n", 1303f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o size, old_blk, new_blk); 1304a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1305a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o do { 1306a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = size; 1307a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (c > fs->inode_blocks_per_group) 1308a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = fs->inode_blocks_per_group; 1309e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_read_blk64(fs->io, old_blk, c, 1310e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->itable_buf); 1311a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1312e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, new_blk, c, 1313e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->itable_buf); 1314a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1315a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o size -= c; 1316a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk += c; 1317a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o old_blk += c; 1318a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved += c; 1319a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 1320a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 13213b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, 13223b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_BLOCK_RELOC_PASS, 1323a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved, to_move); 13243b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 13253b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 1326a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1327a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } while (size > 0); 1328a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 1329a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1330a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1331a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 13327d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (badblock_list) { 13337d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (!retval && bb_modified) 13347d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o retval = ext2fs_update_bb_inode(old_fs, 13357d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o badblock_list); 13367d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2fs_badblocks_list_free(badblock_list); 13377d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o } 1338a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1339a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1340a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1341a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1342a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1343a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1344a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 3 1345a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1346a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1347a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1348a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1349a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1350e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall/* 1351e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * The extent translation table is stored in clusters so we need to 1352e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * take special care when mapping a source block number to its 1353e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * destination block number. 1354e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 1355e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic __u64 extent_translate(ext2_filsys fs, ext2_extent extent, __u64 old_loc) 1356e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 1357e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall __u64 new_block = C2B(ext2fs_extent_translate(extent, B2C(old_loc))); 1358e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1359e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (new_block != 0) 1360e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_block += old_loc & (EXT2FS_CLUSTER_RATIO(fs) - 1); 1361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return new_block; 1362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 1363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1364a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct process_block_struct { 1365a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 1366dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino; 1367a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_inode * inode; 1368a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t error; 1369a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int is_dir; 1370a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int changed; 1371a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 1372a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1373e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int process_block(ext2_filsys fs, blk64_t *block_nr, 1374efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o e2_blkcnt_t blockcnt, 1375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ref_block EXT2FS_ATTR((unused)), 1376544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int ref_offset EXT2FS_ATTR((unused)), void *priv_data) 1377a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1378a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct *pb; 1379a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1380e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t block, new_block; 1381a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int ret = 0; 1382a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1383a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb = (struct process_block_struct *) priv_data; 1384a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = *block_nr; 1385a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->bmap) { 1386e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_block = extent_translate(fs, pb->rfs->bmap, block); 1387a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (new_block) { 1388a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *block_nr = new_block; 1389a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_CHANGED; 1390a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->changed = 1; 1391a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1392a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->flags & RESIZE_DEBUG_BMOVE) 1393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("ino=%u, blockcnt=%lld, %llu->%llu\n", 1394a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->ino, blockcnt, block, new_block); 1395a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1396a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = new_block; 1397a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1398a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1399a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->is_dir) { 1400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_add_dir_block2(fs->dblist, pb->ino, 1401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall block, (int) blockcnt); 1402a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) { 1403a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->error = retval; 1404a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_ABORT; 1405a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1406a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1407a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return ret; 1408a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1409a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1410a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 1411a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Progress callback 1412a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1413efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic errcode_t progress_callback(ext2_filsys fs, 1414544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o ext2_inode_scan scan EXT2FS_ATTR((unused)), 1415a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dgrp_t group, void * priv_data) 1416a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1417a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs = (ext2_resize_t) priv_data; 14183b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t retval; 1419a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1420a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1421f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * This check is to protect against old ext2 libraries. It 1422f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * shouldn't be needed against new libraries. 1423a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1424f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o if ((group+1) == 0) 1425a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1426a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1427a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 1428a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 14293b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 14303b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o group+1, fs->group_desc_count); 14313b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 14323b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return retval; 1433a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1434efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1435a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1436a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1437a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1438a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs) 1439a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1440a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct pb; 1441dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino, new_inode; 1442edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o struct ext2_inode *inode = NULL; 1443a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_inode_scan scan = NULL; 1444a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1445a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o char *block_buf = 0; 1446dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t start_to_move; 1447e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t orig_size; 1448e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t new_block; 14494ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen int inode_size; 1450efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1451a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if ((rfs->old_fs->group_desc_count <= 1452a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->group_desc_count) && 1453a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o !rfs->bmap) 1454a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1455a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 14562bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* 14572bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * Save the original size of the old filesystem, and 14582bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * temporarily set the size to be the new size if the new size 14592bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * is larger. We need to do this to avoid catching an error 14602bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * by the block iterator routines 14612bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o */ 1462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall orig_size = ext2fs_blocks_count(rfs->old_fs->super); 1463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (orig_size < ext2fs_blocks_count(rfs->new_fs->super)) 1464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count_set(rfs->old_fs->super, 1465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count(rfs->new_fs->super)); 14662bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o 1467a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan); 1468a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1469a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1470a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_init_dblist(rfs->old_fs, 0); 1471a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1472e5aace908e9d1161a594944d9360f9f0cdd18099Theodore Ts'o retval = ext2fs_get_array(rfs->old_fs->blocksize, 3, &block_buf); 1473a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1474a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1475a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o start_to_move = (rfs->new_fs->group_desc_count * 1476a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_inodes_per_group); 1477efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 14783b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 14793b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 14803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, rfs->old_fs->group_desc_count); 14813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 14823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 14833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1484a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs); 1485a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.rfs = rfs; 1486edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o pb.inode = inode; 1487a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.error = 0; 1488a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = EXT2_FIRST_INODE(rfs->new_fs->super); 14894ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen inode_size = EXT2_INODE_SIZE(rfs->new_fs->super); 1490edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o inode = malloc(inode_size); 1491edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o if (!inode) { 14924ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen retval = ENOMEM; 14934ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen goto errout; 14944ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen } 1495a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1496a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * First, copy all of the inodes that need to be moved 1497a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * elsewhere in the inode table 1498a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1499a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1500edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o retval = ext2fs_get_next_inode_full(scan, &ino, inode, inode_size); 1501a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1502a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ino) 1503a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 1504a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1505edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o if (inode->i_links_count == 0 && ino != EXT2_RESIZE_INO) 1506a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* inode not in use */ 1507a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1508edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o pb.is_dir = LINUX_S_ISDIR(inode->i_mode); 1509a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.changed = 0; 1510a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1511e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_file_acl_block(rfs->old_fs, inode) && rfs->bmap) { 1512e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_block = extent_translate(rfs->old_fs, rfs->bmap, 1513e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_acl_block(rfs->old_fs, inode)); 1514ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (new_block) { 1515e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_file_acl_block_set(rfs->old_fs, inode, 1516e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_block); 1517efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o retval = ext2fs_write_inode_full(rfs->old_fs, 1518edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o ino, inode, inode_size); 1519ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (retval) goto errout; 1520ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o } 1521ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o } 1522efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1523e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_has_valid_blocks2(rfs->old_fs, inode) && 1524a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (rfs->bmap || pb.is_dir)) { 1525a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.ino = ino; 1526e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_block_iterate3(rfs->old_fs, 1527a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino, 0, block_buf, 1528a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o process_block, &pb); 1529a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1530a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1531a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.error) { 1532a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = pb.error; 1533a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1534a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1535a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1536a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1537a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ino <= start_to_move) 1538a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* Don't need to move it. */ 1539a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1540a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1541a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Find a new inode 1542a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 154386acdebd539864908127561034752082c86105e2Theodore Ts'o retval = ext2fs_new_inode(rfs->new_fs, 0, 0, 0, &new_inode); 154486acdebd539864908127561034752082c86105e2Theodore Ts'o if (retval) 154586acdebd539864908127561034752082c86105e2Theodore Ts'o goto errout; 154686acdebd539864908127561034752082c86105e2Theodore Ts'o 154774128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o ext2fs_inode_alloc_stats2(rfs->new_fs, new_inode, +1, 154874128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o pb.is_dir); 1549a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.changed) { 1550a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* Get the new version of the inode */ 15514ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen retval = ext2fs_read_inode_full(rfs->old_fs, ino, 1552edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o inode, inode_size); 1553a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1554a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1555edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o inode->i_ctime = time(0); 15564ef28824ca29e86053398c3e4cecca6d88b2b397Eric Sandeen retval = ext2fs_write_inode_full(rfs->old_fs, new_inode, 1557edfd9b0a9fe7b90f56da981ca26d5233cc3749d6Theodore Ts'o inode, inode_size); 1558a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1559a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1560a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1561a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_INODEMAP) 1562f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o printf("Inode moved %u->%u\n", ino, new_inode); 1563a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1564a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) { 1565a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->imap, 0); 1566a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1567a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1568a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1569a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_add_extent_entry(rfs->imap, ino, new_inode); 1570a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1571a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(rfs->old_fs->io); 1572a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1573a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 1574e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count_set(rfs->old_fs->super, orig_size); 1575a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->bmap) { 1576a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->bmap); 1577a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->bmap = 0; 1578a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1579a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (scan) 1580a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_close_inode_scan(scan); 1581a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (block_buf) 1582c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o ext2fs_free_mem(&block_buf); 158345e338f5332a54295893dba2e32cc093d1316f60Jim Meyering free(inode); 1584a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1585a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1586a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1587a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1588a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1589a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 4. 1590a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1591a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1592a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1593a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1594a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct istruct { 1595a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 15963b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t err; 159703fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o unsigned int max_dirs; 159803fa6f8ae28a87018325c892f731097cc97d9eacTheodore Ts'o unsigned int num; 1599a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 1600a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1601efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ostatic int check_and_change_inodes(ext2_ino_t dir, 1602544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int entry EXT2FS_ATTR((unused)), 1603a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_dir_entry *dirent, int offset, 1604544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o int blocksize EXT2FS_ATTR((unused)), 1605efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o char *buf EXT2FS_ATTR((unused)), 1606544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o void *priv_data) 1607a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1608a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct *is = (struct istruct *) priv_data; 1609085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o struct ext2_inode inode; 1610085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o ext2_ino_t new_inode; 1611085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o errcode_t retval; 1612a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1613a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->progress && offset == 0) { 1614a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(is->rfs->old_fs->io); 16153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is->err = (is->rfs->progress)(is->rfs, 16163b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_INODE_REF_UPD_PASS, 16171333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o ++is->num, is->max_dirs); 16183b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is->err) 16193b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return DIRENT_ABORT; 1620a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1621a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1622a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!dirent->inode) 1623a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1624a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1625a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode); 1626a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1627a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_inode) 1628a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1629a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1630a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) 1631f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o printf("Inode translate (dir=%u, name=%.*s, %u->%u)\n", 163206191693d4d253a8496677dd02e3b8529a7fce2cTheodore Ts'o dir, dirent->name_len&0xFF, dirent->name, 1633a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode, new_inode); 1634a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1635a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1636a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode = new_inode; 1637a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1638085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o /* Update the directory mtime and ctime */ 1639085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode); 1640085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o if (retval == 0) { 1641085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o inode.i_mtime = inode.i_ctime = time(0); 1642d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf is->err = ext2fs_write_inode(is->rfs->old_fs, dir, &inode); 1643d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf if (is->err) 1644d2b2a488f996871e6e40789a7890afc2f59730dbBrian Behlendorf return DIRENT_ABORT; 1645085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o } 1646085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o 1647a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return DIRENT_CHANGED; 1648a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1649a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1650a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs) 1651a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1652a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1653a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct is; 1654efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1655a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) 1656a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1657efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1658a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1659a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Now, we iterate over all of the directories to update the 1660a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode references 1661a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1662a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.num = 0; 1663e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall is.max_dirs = ext2fs_dblist_count2(rfs->old_fs->dblist); 1664a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.rfs = rfs; 16653b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is.err = 0; 1666a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 16673b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 16683b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 16691333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o 0, is.max_dirs); 16703b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 16713b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 16723b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1673efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1674a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 1675a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o DIRENT_FLAG_INCLUDE_EMPTY, 0, 1676a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o check_and_change_inodes, &is); 16773b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 16783b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 16793b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is.err) { 16803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = is.err; 16813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 16823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1683a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 168488dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o if (rfs->progress && (is.num < is.max_dirs)) 168588dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 168688dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o is.max_dirs, is.max_dirs); 168788dbf8287f831d02e8d5023be4f9b42ca224fb75Theodore Ts'o 16883b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'oerrout: 1689a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->imap); 1690a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->imap = 0; 1691a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1692a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1693a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1694a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1695a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1696a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1697a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 5. 1698a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1699a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we actually move the inode table around, and then 1700a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the summary statistics. This is scary, since aborting here 1701a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will potentially scramble the filesystem. (We are moving the 1702a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode tables around in place, and so the potential for lost data, 1703a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * or at the very least scrambling the mapping between filenames and 1704a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode numbers is very high in case of a power failure here.) 1705a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1706a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1707a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 170824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 170924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 1710052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * A very scary routine --- this one moves the inode table around!!! 1711052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * 1712052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * After this you have to use the rfs->new_fs file handle to read and 1713052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * write inodes. 1714052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1715c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs) 1716052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 1717e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int n, num, size; 1718e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall long long diff; 1719544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o dgrp_t i, max_groups; 1720052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2_filsys fs = rfs->new_fs; 172105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o char *cp; 1722e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t old_blk, new_blk, blk; 1723a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 172464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o int j, to_move, moved; 1725052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 17261333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = fs->group_desc_count; 17271333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o if (max_groups > rfs->old_fs->group_desc_count) 17281333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = rfs->old_fs->group_desc_count; 1729052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 173005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o size = fs->blocksize * fs->inode_blocks_per_group; 173105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!rfs->itable_buf) { 1732c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(size, &rfs->itable_buf); 1733ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 1734ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o return retval; 173505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o } 1736c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1737c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 1738c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Figure out how many inode tables we need to move 1739c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 1740c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move = moved = 0; 17411333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i=0; i < max_groups; i++) 1742e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (ext2fs_inode_table_loc(rfs->old_fs, i) != 1743e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc(fs, i)) 1744c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move++; 1745c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1746c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (to_move == 0) 1747c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return 0; 1748c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 17493b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 17503b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 17513b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 17523b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 17533b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 17543b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 175563b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o 1756a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1757a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 17581333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i=0; i < max_groups; i++) { 1759e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_blk = ext2fs_inode_table_loc(rfs->old_fs, i); 1760e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall new_blk = ext2fs_inode_table_loc(fs, i); 1761ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o diff = new_blk - old_blk; 1762efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 176380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 1764efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1765e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Itable move group %d block %llu->%llu (diff %lld)\n", 1766ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o i, old_blk, new_blk, diff); 176780c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1768efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 176905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!diff) 1770052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o continue; 1771052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1772e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_read_blk64(fs->io, old_blk, 1773e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group, 1774e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall rfs->itable_buf); 1775efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (retval) 1776a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 177705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 177805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * The end of the inode table segment often contains 1779a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * all zeros, and we're often only moving the inode 1780a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * table down a block or two. If so, we can optimize 1781a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * things by not rewriting blocks that we know to be zero 1782a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * already. 178305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 17842787276ec59e1d52087d307bc30446d088ec65bcTheodore Ts'o for (cp = rfs->itable_buf+size-1, n=0; n < size; n++, cp--) 178505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (*cp) 178605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o break; 178705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); 178880c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 1789efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1790f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o printf("%d blocks of zeros...\n", n); 179180c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 179205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num = fs->inode_blocks_per_group; 179305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) 179405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num -= n; 179505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o 1796e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, new_blk, 1797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num, rfs->itable_buf); 1798052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (retval) { 1799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall io_channel_write_blk64(fs->io, old_blk, 1800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall num, rfs->itable_buf); 1801a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1802052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 180305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) { 1804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, 1805ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o old_blk + fs->inode_blocks_per_group, 1806a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o diff, (rfs->itable_buf + 1807a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (fs->inode_blocks_per_group - diff) * 1808a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->blocksize)); 180905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (retval) 1810a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1811c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 181264ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o 1813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = ext2fs_inode_table_loc(rfs->old_fs, i), j=0; 181464ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 1815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_block_alloc_stats2(fs, blk, -1); 181664ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o 1817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_inode_table_loc_set(rfs->old_fs, i, new_blk); 1818236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos ext2fs_group_desc_csum_set(rfs->old_fs, i); 1819a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_super_dirty(rfs->old_fs); 182064ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o ext2fs_flush(rfs->old_fs); 182164ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o 1822a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 18233b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 18243b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o ++moved, to_move); 18253b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 18263b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 1827a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1828052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 182964ad98acbe694e74925ad4e4fc88fd10fd3b3a44Theodore Ts'o mark_table_blocks(fs, fs->block_map); 1830a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_flush(fs); 183180c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 1832efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1833f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o printf("Inode table move finished.\n"); 183480c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1835052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1836efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1837a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 1838052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return retval; 1839052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1840052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1841052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o/* 1842efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * Fix the resize inode 18439213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o */ 18449213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'ostatic errcode_t fix_resize_inode(ext2_filsys fs) 18459213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o{ 18469213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o struct ext2_inode inode; 18479213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o errcode_t retval; 1848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall char *block_buf = NULL; 18499213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 1850efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (!(fs->super->s_feature_compat & 18519213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o EXT2_FEATURE_COMPAT_RESIZE_INODE)) 18529213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o return 0; 18539213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18549213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o retval = ext2fs_get_mem(fs->blocksize, &block_buf); 18559213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) goto errout; 18569213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18579213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode); 18589213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) goto errout; 18599213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18601ca1059fd0126fd2c065f272a566c18f14bab16dTheodore Ts'o ext2fs_iblk_set(fs, &inode, 1); 18619213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18629213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o retval = ext2fs_write_inode(fs, EXT2_RESIZE_INO, &inode); 18639213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) goto errout; 18649213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18659213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (!inode.i_block[EXT2_DIND_BLOCK]) { 1866efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o /* 18679213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * Avoid zeroing out block #0; that's rude. This 18689213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * should never happen anyway since the filesystem 18699213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o * should be fsck'ed and we assume it is consistent. 18709213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o */ 1871e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fprintf(stderr, "%s", 1872f35fd3d5eeb3e35660ea87adbc170978c3cdf9e3Theodore Ts'o _("Should never happen: resize inode corrupt!\n")); 18739213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o exit(1); 18749213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o } 18759213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18769213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o memset(block_buf, 0, fs->blocksize); 18779213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 1878e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_write_blk64(fs->io, inode.i_block[EXT2_DIND_BLOCK], 1879e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 1, block_buf); 18809213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) goto errout; 1881efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 18829213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o retval = ext2fs_create_resize_inode(fs); 18839213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (retval) 18849213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o goto errout; 18859213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18869213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'oerrout: 18879213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o if (block_buf) 18889213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o ext2fs_free_mem(&block_buf); 18899213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o return retval; 18909213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o} 18919213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o 18929213a93b22accd2a27064b12f6bc5f1221ca6a70Theodore Ts'o/* 1893052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Finally, recalculate the summary information 1894052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1895052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) 1896052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 1897e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blk; 1898dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino; 1899544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int group = 0; 1900544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o unsigned int count = 0; 1901e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t total_blocks_free = 0; 1902e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int total_inodes_free = 0; 1903dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o int group_free = 0; 190474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o int uninit = 0; 1905e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t super_blk, old_desc_blk, new_desc_blk; 190674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o int old_desc_blocks; 1907052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1908052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1909052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * First calculate the block statistics 1910052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1911e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1912e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_super_and_bgd_loc2(fs, group, &super_blk, &old_desc_blk, 1913e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &new_desc_blk, 0); 191474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 191574128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o old_desc_blocks = fs->super->s_first_meta_bg; 191674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o else 191774128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o old_desc_blocks = fs->desc_blocks + 191874128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o fs->super->s_reserved_gdt_blocks; 1919e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (blk = B2C(fs->super->s_first_data_block); 1920e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk < ext2fs_blocks_count(fs->super); 1921e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk += EXT2FS_CLUSTER_RATIO(fs)) { 192274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o if ((uninit && 1923e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(EQ_CLSTR(blk, super_blk) || 192474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o ((old_desc_blk && old_desc_blocks && 1925e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall GE_CLSTR(blk, old_desc_blk) && 1926e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall LT_CLSTR(blk, old_desc_blk + old_desc_blocks))) || 1927e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((new_desc_blk && EQ_CLSTR(blk, new_desc_blk))) || 1928e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EQ_CLSTR(blk, ext2fs_block_bitmap_loc(fs, group)) || 1929e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EQ_CLSTR(blk, ext2fs_inode_bitmap_loc(fs, group)) || 1930e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ((GE_CLSTR(blk, ext2fs_inode_table_loc(fs, group)) && 1931e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall LT_CLSTR(blk, ext2fs_inode_table_loc(fs, group) 1932e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall + fs->inode_blocks_per_group))))) || 1933e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (!ext2fs_fast_test_block_bitmap2(fs->block_map, blk))) { 1934052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1935e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_blocks_free++; 1936052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1937052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1938e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((count == fs->super->s_clusters_per_group) || 1939e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EQ_CLSTR(blk, ext2fs_blocks_count(fs->super)-1)) { 1940e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_free_blocks_count_set(fs, group, group_free); 1941236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos ext2fs_group_desc_csum_set(fs, group); 1942236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos group++; 19434828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o if (group >= fs->group_desc_count) 19444828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o break; 1945052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1946052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1947e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_BLOCK_UNINIT); 1948e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_super_and_bgd_loc2(fs, group, &super_blk, 1949e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &old_desc_blk, 1950e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &new_desc_blk, 0); 195174128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o if (fs->super->s_feature_incompat & 195274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) 195374128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o old_desc_blocks = fs->super->s_first_meta_bg; 195474128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o else 195574128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o old_desc_blocks = fs->desc_blocks + 195674128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o fs->super->s_reserved_gdt_blocks; 1957052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1958052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1959e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_blocks_free = C2B(total_blocks_free); 1960e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count_set(fs->super, total_blocks_free); 1961efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1962052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1963052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Next, calculate the inode statistics 1964052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1965052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1966052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1967052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group = 0; 19685830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen 19695830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen /* Protect loop from wrap-around if s_inodes_count maxed */ 1970e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 19715830d6be9c33e23bb20c339036083e6e4fa6795eEric Sandeen for (ino = 1; ino <= fs->super->s_inodes_count && ino > 0; ino++) { 197274128f8d7e93fe633aa87951319a4afd252a4494Theodore Ts'o if (uninit || 1973e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !ext2fs_fast_test_inode_bitmap2(fs->inode_map, ino)) { 1974052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1975e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall total_inodes_free++; 1976052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1977052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1978052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if ((count == fs->super->s_inodes_per_group) || 1979052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o (ino == fs->super->s_inodes_count)) { 1980e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_free_inodes_count_set(fs, group, group_free); 1981236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos ext2fs_group_desc_csum_set(fs, group); 1982236efede1922fa173b3c2f20d9e0886856664ab4Jose R. Santos group++; 19834828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o if (group >= fs->group_desc_count) 19844828bbe9e7380da0d9153109ab290e88b5d53bf5Theodore Ts'o break; 1985052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1986052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1987e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall uninit = ext2fs_bg_flags_test(fs, group, EXT2_BG_INODE_UNINIT); 1988052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1989052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1990e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_free_inodes_count = total_inodes_free; 1991052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2fs_mark_super_dirty(fs); 1992052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1993052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1994199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 1995199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik/* 19968a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen * Journal may have been relocated; update the backup journal blocks 19978a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen * in the superblock. 19988a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen */ 19998a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeenstatic errcode_t fix_sb_journal_backup(ext2_filsys fs) 20008a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen{ 20018a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen errcode_t retval; 20028a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen struct ext2_inode inode; 20038a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen 20048a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen if (!(fs->super->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) 20058a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen return 0; 20068a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen 2007d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen /* External journal? Nothing to do. */ 2008d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen if (fs->super->s_journal_dev && !fs->super->s_journal_inum) 2009d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen return 0; 2010d93d5bbf605f81eb13fa71a55dfbed06f88fe930Eric Sandeen 20118a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen retval = ext2fs_read_inode(fs, fs->super->s_journal_inum, &inode); 20128a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen if (retval) 20138a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen return retval; 20148a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen memcpy(fs->super->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); 2015e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_jnl_blocks[15] = inode.i_size_high; 20168a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen fs->super->s_jnl_blocks[16] = inode.i_size; 20178a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen fs->super->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; 20188a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen ext2fs_mark_super_dirty(fs); 20198a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen return 0; 20208a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen} 20218a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen 2022e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallstatic int calc_group_overhead(ext2_filsys fs, blk64_t grp, 2023e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int old_desc_blocks) 2024e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 2025e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t super_blk, old_desc_blk, new_desc_blk; 2026e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int overhead; 2027e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2028e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* inode table blocks plus allocation bitmaps */ 2029e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = fs->inode_blocks_per_group + 2; 2030e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2031e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_super_and_bgd_loc2(fs, grp, &super_blk, 2032e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall &old_desc_blk, &new_desc_blk, 0); 2033e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((grp == 0) || super_blk) 2034e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead++; 2035e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (old_desc_blk) 2036e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead += old_desc_blocks; 2037e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else if (new_desc_blk) 2038e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead++; 2039e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return overhead; 2040e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 2041e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2042e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 20438a6ede8b7a8d5be0d49d6bfa7616537b61dfdc1bEric Sandeen/* 2044199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * calcluate the minimum number of blocks the given fs can be resized to 2045199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2046e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags) 2047199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik{ 2048e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2_ino_t inode_count; 2049e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t groups; 2050e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t blks_needed, data_blocks; 2051e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t grp, data_needed, last_start; 2052e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t overhead = 0; 2053e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall int old_desc_blocks; 20542884d208a37fe8813267198a247694bc90b00f96Peng Tao int extra_groups = 0; 20552884d208a37fe8813267198a247694bc90b00f96Peng Tao int flexbg_size = 1 << fs->super->s_log_groups_per_flex; 2056199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2057199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2058199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * first figure out how many group descriptors we need to 2059199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * handle the number of inodes we have 2060199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2061199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik inode_count = fs->super->s_inodes_count - 2062199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik fs->super->s_free_inodes_count; 2063199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik blks_needed = ext2fs_div_ceil(inode_count, 2064199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik fs->super->s_inodes_per_group) * 2065199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik EXT2_BLOCKS_PER_GROUP(fs->super); 2066e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall groups = ext2fs_div64_ceil(blks_needed, 2067e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_BLOCKS_PER_GROUP(fs->super)); 2068e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2069e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2070e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("fs has %d inodes, %d groups required.\n", 2071e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall inode_count, groups); 2072e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2073199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2074199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2075e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * number of old-style block group descriptor blocks 2076199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2077e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 2078e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_desc_blocks = fs->super->s_first_meta_bg; 2079e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall else 2080e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_desc_blocks = fs->desc_blocks + 2081e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_reserved_gdt_blocks; 2082199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2083199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* calculate how many blocks are needed for data */ 2084e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall data_needed = ext2fs_blocks_count(fs->super) - 2085e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_free_blocks_count(fs->super); 2086199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2087e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (grp = 0; grp < fs->group_desc_count; grp++) 2088e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall data_needed -= calc_group_overhead(fs, grp, old_desc_blocks); 2089e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2090e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2091e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("fs requires %llu data blocks.\n", data_needed); 2092e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2093e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2094e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 2095e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * For ext4 we need to allow for up to a flex_bg worth of 2096e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * inode tables of slack space so the resize operation can be 2097e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * guaranteed to finish. 2098e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 2099c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o if (fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) { 2100c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o extra_groups = flexbg_size - (groups & (flexbg_size - 1)); 2101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall data_needed += fs->inode_blocks_per_group * extra_groups; 21022884d208a37fe8813267198a247694bc90b00f96Peng Tao extra_groups = groups % flexbg_size; 2103c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o } 2104c09043f1abb99c73d681e630ee0a4b142e4abf6bTheodore Ts'o 2105199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2106199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * figure out how many data blocks we have given the number of groups 2107199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * we need for our inodes 2108199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2109199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik data_blocks = groups * EXT2_BLOCKS_PER_GROUP(fs->super); 2110199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik last_start = 0; 2111199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik for (grp = 0; grp < groups; grp++) { 2112e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = calc_group_overhead(fs, grp, old_desc_blocks); 2113199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2114199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2115199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * we want to keep track of how much data we can store in 2116199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * the groups leading up to the last group so we can determine 2117199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * how big the last group needs to be 2118199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2119199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik if (grp != (groups - 1)) 2120199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - 2121199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik overhead; 2122199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2123199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik data_blocks -= overhead; 2124199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik } 2125e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2126e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2127e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("With %d group(s), we have %llu blocks available.\n", 2128e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall groups, data_blocks); 2129e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2130199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2131199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2132199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * if we need more group descriptors in order to accomodate our data 2133199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * then we need to add them here 2134199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2135199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik while (data_needed > data_blocks) { 2136e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t remainder = data_needed - data_blocks; 2137e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t extra_grps; 2138199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2139199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* figure out how many more groups we need for the data */ 2140e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extra_grps = ext2fs_div64_ceil(remainder, 2141e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_BLOCKS_PER_GROUP(fs->super)); 2142199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2143199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik data_blocks += extra_grps * EXT2_BLOCKS_PER_GROUP(fs->super); 2144199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2145199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* ok we have to account for the last group */ 2146e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2147199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik last_start += EXT2_BLOCKS_PER_GROUP(fs->super) - overhead; 2148199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2149199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik for (grp = groups; grp < groups+extra_grps; grp++) { 2150e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = calc_group_overhead(fs, grp, 2151e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall old_desc_blocks); 2152199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2153199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2154199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * again, we need to see how much data we cram into 2155199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * all of the groups leading up to the last group 2156199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2157199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik if (grp != (groups + extra_grps - 1)) 2158199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik last_start += EXT2_BLOCKS_PER_GROUP(fs->super) 2159199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik - overhead; 2160199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2161199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik data_blocks -= overhead; 2162199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik } 2163199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2164199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik groups += extra_grps; 21652884d208a37fe8813267198a247694bc90b00f96Peng Tao extra_groups += extra_grps; 21662884d208a37fe8813267198a247694bc90b00f96Peng Tao if (fs->super->s_feature_incompat 21672884d208a37fe8813267198a247694bc90b00f96Peng Tao & EXT4_FEATURE_INCOMPAT_FLEX_BG 21682884d208a37fe8813267198a247694bc90b00f96Peng Tao && extra_groups > flexbg_size) { 21692884d208a37fe8813267198a247694bc90b00f96Peng Tao /* 21702884d208a37fe8813267198a247694bc90b00f96Peng Tao * For ext4 we need to allow for up to a flex_bg worth 21712884d208a37fe8813267198a247694bc90b00f96Peng Tao * of inode tables of slack space so the resize 21722884d208a37fe8813267198a247694bc90b00f96Peng Tao * operation can be guaranteed to finish. 21732884d208a37fe8813267198a247694bc90b00f96Peng Tao */ 21742884d208a37fe8813267198a247694bc90b00f96Peng Tao extra_groups = flexbg_size - 21752884d208a37fe8813267198a247694bc90b00f96Peng Tao (groups & (flexbg_size - 1)); 2176e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall data_needed += (fs->inode_blocks_per_group * 2177e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extra_groups); 21782884d208a37fe8813267198a247694bc90b00f96Peng Tao extra_groups = groups % flexbg_size; 21792884d208a37fe8813267198a247694bc90b00f96Peng Tao } 2180e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2181e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2182e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Added %d extra group(s), " 2183e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "data_needed %llu, data_blocks %llu, " 2184e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall "last_start %llu\n", 2185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall extra_grps, data_needed, data_blocks, 2186e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall last_start); 2187e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2188199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik } 2189199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2190199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* now for the fun voodoo */ 2191e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = calc_group_overhead(fs, groups-1, old_desc_blocks); 2192e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2193e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2194e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Last group's overhead is %llu\n", overhead); 2195e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2196199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2197199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2198199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * if this is the case then the last group is going to have data in it 2199199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * so we need to adjust the size of the last group accordingly 2200199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2201199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik if (last_start < data_needed) { 2202e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t remainder = data_needed - last_start; 2203199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2204e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2205e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2206e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Need %llu data blocks in last group\n", 2207e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall remainder); 2208e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2209199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2210199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * 50 is a magic number that mkfs/resize uses to see if its 2211199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * even worth making/resizing the fs. basically you need to 2212199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * have at least 50 blocks in addition to the blocks needed 2213199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * for the metadata in the last group 2214199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2215199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik if (remainder > 50) 2216199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik overhead += remainder; 2217199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik else 2218199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik overhead += 50; 2219199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik } else 2220199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik overhead += 50; 2221199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead += fs->super->s_first_data_block; 2223e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2225e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Final size of last group is %lld\n", overhead); 2226e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2227199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 2228199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik /* 2229199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * since our last group doesn't have to be BLOCKS_PER_GROUP large, we 2230199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * only do groups-1, and then add the number of blocks needed to 2231199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik * handle the group descriptor metadata+data that we need 2232199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik */ 2233199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik blks_needed = (groups-1) * EXT2_BLOCKS_PER_GROUP(fs->super); 2234199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik blks_needed += overhead; 2235199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik 22362215293c7e85c88d2fbc06f9e9438fca9a25213cTheodore Ts'o /* 2237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * Make sure blks_needed covers the end of the inode table in 2238e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * the last block group. 2239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 2240e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall overhead = ext2fs_inode_table_loc(fs, groups-1) + 2241e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->inode_blocks_per_group; 2242e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blks_needed < overhead) 2243e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blks_needed = overhead; 2244e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2245e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2246e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2247e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Estimated blocks needed: %llu\n", blks_needed); 2248e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 2250e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 225169f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen * If at this point we've already added up more "needed" than 225269f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen * the current size, just return current size as minimum. 225369f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen */ 2254e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (blks_needed >= ext2fs_blocks_count(fs->super)) 2255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_blocks_count(fs->super); 225669f7c80eaf25a642b0eb85f4557605c89acd80b6Eric Sandeen /* 2257793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o * We need to reserve a few extra blocks if extents are 2258793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o * enabled, in case we need to grow the extent tree. The more 2259793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o * we shrink the file system, the more space we need. 2260793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o */ 2261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->super->s_feature_incompat & EXT3_FEATURE_INCOMPAT_EXTENTS) { 2262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t safe_margin = (ext2fs_blocks_count(fs->super) - 2263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blks_needed)/500; 2264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef RESIZE2FS_DEBUG 2265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (flags & RESIZE_DEBUG_MIN_CALC) 2266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall printf("Extents safety margin: %llu\n", safe_margin); 2267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 2268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blks_needed += safe_margin; 2269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 2270793a04a0719d5688a0033e4bda3cf267f57ea760Theodore Ts'o 2271199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik return blks_needed; 2272199ddaaa445e14fca8113b0db85e2576267071c9Josef Bacik} 2273