resize2fs.c revision 101c84f2e049bffcdb6c5ba1784842cdd50dbf05
124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * resize2fs.c --- ext2 main routine 324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Copyright (C) 1997 Theodore Ts'o 524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %Begin-Header% 724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * All rights reserved. 824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %End-Header% 924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 1024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 1105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o/* 1205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Resizing a filesystem consists of the following phases: 1305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * 14a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1. Adjust superblock and write out new parts of the inode 1505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * table 16a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 2. Determine blocks which need to be relocated, and copy the 17a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * contents of blocks from their old locations to the new ones. 18a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 3. Scan the inode table, doing the following: 19a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * a. If blocks have been moved, update the block 20a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * pointers in the inodes and indirect blocks to 21a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * point at the new block locations. 22a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * b. If parts of the inode table need to be evacuated, 23a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * copy inodes from their old locations to their 24a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * new ones. 25a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * c. If (b) needs to be done, note which blocks contain 26a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * directory information, since we will need to 27a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the directory information. 28a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 4. Update the directory blocks with the new inode locations. 29a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 5. Move the inode tables, if necessary. 3005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 31a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 3224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o#include "resize2fs.h" 3324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 34a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef linux /* Kludge for debugging */ 35a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define RESIZE2FS_DEBUG 36a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 37a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 38a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size); 39a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs); 40a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs); 41a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs); 42a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs); 43a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs); 44a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs); 45a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 46a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 47a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Some helper CPP macros 48a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 49a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap) 50a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap) 51a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table) 52a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 53a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i))) 54a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i))) 55a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 56a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_TB(fs, i, blk) (((blk) >= FS_INODE_TB((fs), (i))) && \ 57a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ((blk) < (FS_INODE_TB((fs), (i)) + \ 58a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (fs)->inode_blocks_per_group))) 59a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 60a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 61a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 62a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 63a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This is the top-level routine which does the dirty deed.... 64a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 65a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrcode_t resize_fs(ext2_filsys fs, blk_t new_size, int flags, 663b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t (*progress)(ext2_resize_t rfs, int pass, 67a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o unsigned long cur, 68a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o unsigned long max)) 69a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 70a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 71a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 72a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 73a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_read_bitmaps(fs); 74a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 75a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 76a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 77a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 78a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Create the data structure 79a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 80a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), 81a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &rfs); 82a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 83a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 84a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o memset(rfs, 0, sizeof(struct ext2_resize_struct)); 85a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 86a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs = fs; 87a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 88a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf = 0; 89a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->progress = progress; 90a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dup_handle(fs, &rfs->new_fs); 91a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 92a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 93a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 94a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = adjust_superblock(rfs, new_size); 95a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 96a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 97a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 98a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = blocks_to_move(rfs); 99a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 102a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 103a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 104a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o printf("Number of free blocks: %d/%d, Needed: %d\n", 105a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->super->s_free_blocks_count, 106a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_free_blocks_count, 107a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->needed_blocks); 108a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 109a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 110a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = block_mover(rfs); 111a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 112a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_scan_and_fix(rfs); 115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 116a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_ref_fix(rfs); 119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 121a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_calculate_summary_stats(rfs->new_fs); 123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 125a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 126a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = move_itables(rfs); 127a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 128a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_close(rfs->new_fs); 131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 133a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 134a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->old_fs); 137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs->itable_buf); 139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs); 140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->new_fs) 145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->new_fs); 146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs->itable_buf); 148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs); 149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 150a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 151a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 1. 155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust the in-memory superblock information, and 157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * initialize any new parts of the inode table. The new parts of the 158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode table are created in virgin disk space, so we can abort here 159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * without any side effects. 160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 161a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 16324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 16424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine adjusts the superblock and other data structures... 16524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 16624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size) 16724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 16824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o ext2_filsys fs; 16924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o int overhead = 0; 170c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int rem, adj = 0; 17124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 17224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o ino_t real_end; 17324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk_t blk, group_block; 1741e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o unsigned long i, j; 1751e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o int old_numblocks, numblocks, adjblocks; 17663b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o unsigned long max_group; 17724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 17824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs = rfs->new_fs; 17924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_count = new_size; 1801e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_super_dirty(fs); 1811e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_bb_dirty(fs); 1821e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_ib_dirty(fs); 18324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 18424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'oretry: 18524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->group_desc_count = (fs->super->s_blocks_count - 18624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_first_data_block + 18724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o EXT2_BLOCKS_PER_GROUP(fs->super) - 1) 18824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o / EXT2_BLOCKS_PER_GROUP(fs->super); 18924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (fs->group_desc_count == 0) 19024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 19124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->desc_blocks = (fs->group_desc_count + 19224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o EXT2_DESC_PER_BLOCK(fs->super) - 1) 19324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o / EXT2_DESC_PER_BLOCK(fs->super); 19424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 19524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 19624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Overhead is the number of bookkeeping blocks per group. It 19724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * includes the superblock backup, the group descriptor 19824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * backups, the inode bitmap, the block bitmap, and the inode 19924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * table. 20024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 20124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * XXX Not all block groups need the descriptor blocks, but 20224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * being clever is tricky... 20324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 20424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group; 20524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 20624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 20724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * See if the last group is big enough to support the 20824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * necessary data structures. If not, we need to get rid of 20924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * it. 21024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 21124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) % 21224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_per_group; 21324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if ((fs->group_desc_count == 1) && rem && (rem < overhead)) 21424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 21524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (rem && (rem < overhead+50)) { 21624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_count -= rem; 21724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o goto retry; 21824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 21924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 22024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of inodes 22124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 22224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count = fs->super->s_inodes_per_group * 22324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->group_desc_count; 22424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 22524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 22624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of free blocks 22724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 22824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk = rfs->old_fs->super->s_blocks_count; 22924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (blk > fs->super->s_blocks_count) 23024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_free_blocks_count -= 23124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o (blk - fs->super->s_blocks_count); 23224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o else 23324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_free_blocks_count += 23424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o (fs->super->s_blocks_count - blk); 23524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 23624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 237c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Adjust the number of reserved blocks 238c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 239c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk = rfs->old_fs->super->s_r_blocks_count * 100 / 240c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->old_fs->super->s_blocks_count; 241c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->super->s_r_blocks_count = ((fs->super->s_blocks_count * blk) 242c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o / 100); 243c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 244c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 24524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the bitmaps for size 24624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 24724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count, 24824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count, 24924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->inode_map); 250c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 25124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 25224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super) 25324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * fs->group_desc_count)) - 1 + 25424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_first_data_block; 25524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1, 25624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o real_end, fs->block_map); 25724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 258c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 25924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 26024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 26124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Reallocate the group descriptors as necessary. 26224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 26324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (rfs->old_fs->desc_blocks != fs->desc_blocks) { 264ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = ext2fs_resize_mem(fs->desc_blocks * fs->blocksize, 265ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o (void **) &fs->group_desc); 266ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 267a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 26824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 2691e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 2701e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 271a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Check to make sure there are enough inodes 272a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 273a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if ((rfs->old_fs->super->s_inodes_count - 274a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->super->s_free_inodes_count) > 275a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_inodes_count) { 276a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 277a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 278a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 279a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * If we are shrinking the number block groups, we're done and 282a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * can exit now. 2831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 284c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc_count > fs->group_desc_count) { 285c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 286c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 287c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 288a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 289a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Fix the count of the last (old) block group 290a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 2911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o old_numblocks = (rfs->old_fs->super->s_blocks_count - 2921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->super->s_first_data_block) % 2931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->super->s_blocks_per_group; 2941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!old_numblocks) 2951e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o old_numblocks = rfs->old_fs->super->s_blocks_per_group; 2961e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (rfs->old_fs->group_desc_count == fs->group_desc_count) { 2971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = (rfs->new_fs->super->s_blocks_count - 2981e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->new_fs->super->s_first_data_block) % 2991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->new_fs->super->s_blocks_per_group; 3001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!numblocks) 3011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = rfs->new_fs->super->s_blocks_per_group; 3021e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } else 3031e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = rfs->new_fs->super->s_blocks_per_group; 3041e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o i = rfs->old_fs->group_desc_count - 1; 3051e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks); 3061e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 308a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * If the number of block groups is staying the same, we're 309a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * done and can exit now. (If the number block groups is 310a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * shrinking, we had exited earlier.) 3111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 312c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc_count >= fs->group_desc_count) { 313c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 314c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 315c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 316a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 317a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Initialize the new block group descriptors 318a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 319ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group, 320ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o (void **) &rfs->itable_buf); 321ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 322c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 323ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o 32405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group); 3251e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block = fs->super->s_first_data_block + 3261e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group; 327c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 32863b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o adj = rfs->old_fs->group_desc_count; 32963b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o max_group = fs->group_desc_count - adj; 3303b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 3313b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 3323b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, max_group); 3333b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 3343b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 3353b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 3361e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (i = rfs->old_fs->group_desc_count; 3371e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o i < fs->group_desc_count; i++) { 3381e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o memset(&fs->group_desc[i], 0, 3391e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o sizeof(struct ext2_group_desc)); 3401e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks = 0; 3411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (i == fs->group_desc_count-1) { 3431e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = (fs->super->s_blocks_count - 3441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_first_data_block) % 3451e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_blocks_per_group; 3461e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!numblocks) 3471e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 3481e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } else 3491e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 3501e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (ext2fs_bg_has_super(fs, i)) { 3521e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (j=0; j < fs->desc_blocks+1; j++) 3531e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, 3541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block + j); 3551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks = 1 + fs->desc_blocks; 35624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 3571e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks += 2 + fs->inode_blocks_per_group; 3581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks -= adjblocks; 3601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_free_blocks_count -= adjblocks; 3611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_free_inodes_count += 3621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_inodes_per_group; 3631e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_blocks_count = numblocks; 3641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_inodes_count = 3651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_inodes_per_group; 3661e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_used_dirs_count = 0; 36724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 3681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 0); 369c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 37024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 37105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 37205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Write out the new inode table 37305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 37405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o retval = io_channel_write_blk(fs->io, 37505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->group_desc[i].bg_inode_table, 37605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->inode_blocks_per_group, 37705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o rfs->itable_buf); 378c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 379c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 380a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 3813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 3823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 3833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o i - adj + 1, max_group); 3843b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 3853b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 3863b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 3871e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block += fs->super->s_blocks_per_group; 38824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 389c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o io_channel_flush(fs->io); 390c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 391c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 392c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 393c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 394c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o} 395c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 396a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 397a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 398a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 2. 399a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 400a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust determine which blocks need to be moved, in 401a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * blocks_to_move(). We then copy the blocks to their ultimate new 402a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * destinations using block_mover(). Since we are copying blocks to 403a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * their new locations, again during this pass we can abort without 404a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * any problems. 405a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 406a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 407a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 408c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o/* 409c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * This helper function creates a block bitmap with all of the 410c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * filesystem meta-data blocks. 411c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 412c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t mark_table_blocks(ext2_filsys fs, 413c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap *ret_bmap) 414c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o{ 415c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk_t block, b; 416c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int i,j; 417c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap bmap; 418c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o errcode_t retval; 419c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 420c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, "meta-data blocks", &bmap); 421c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 422c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 423c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 424c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o block = fs->super->s_first_data_block; 425c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (i = 0; i < fs->group_desc_count; i++) { 426c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_bg_has_super(fs, i)) { 427c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 428c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark this group's copy of the superblock 429c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 430c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, block); 431c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 432c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 433c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark this group's copy of the descriptors 434c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 435c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (j = 0; j < fs->desc_blocks; j++) 436c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, block + j + 1); 437c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 438c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 439c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 440c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark the blocks used for the inode table 441c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 442c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (j = 0, b = fs->group_desc[i].bg_inode_table; 443c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j < fs->inode_blocks_per_group; 444c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j++, b++) 445c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, b); 446c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 447c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 448c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark block used for the block bitmap 449c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 450c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 451c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_block_bitmap); 452c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 453c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark block used for the inode bitmap 454c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 455c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 456c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap); 457c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o block += fs->super->s_blocks_per_group; 458c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 459c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o *ret_bmap = bmap; 4601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return 0; 46124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o} 46224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 46324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 46424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine marks and unmarks reserved blocks in the new block 46524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * bitmap. It also determines which blocks need to be moved and 46624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * places this information into the move_blocks bitmap. 46724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 468c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs) 46924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 470c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int i, j, max; 47124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk_t blk, group_blk; 47224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o unsigned long old_blocks, new_blocks; 47324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 474c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2_filsys fs, old_fs; 475c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap meta_bmap; 47624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 477c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 478c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o old_fs = rfs->old_fs; 479c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (old_fs->super->s_blocks_count > fs->super->s_blocks_count) 480c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->old_fs; 481c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 482c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, "reserved blocks", 4831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o &rfs->reserve_blocks); 48424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (retval) 48524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return retval; 4861e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 487c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, "blocks to be moved", 488c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o &rfs->move_blocks); 489c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 490c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 491c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 492bce49798f7f4380dff5693bc8308019b3cf8de25Theodore Ts'o retval = mark_table_blocks(old_fs, &meta_bmap); 493c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 494c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 495c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 496c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 497c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 4981e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 4991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * If we're shrinking the filesystem, we need to move all of 5001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * the blocks that don't fit any more 5011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 5021e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->super->s_blocks_count; 503c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk < old_fs->super->s_blocks_count; blk++) { 504c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 505c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) { 506c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, blk); 5071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->needed_blocks++; 508c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 5091e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 5101e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 51124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 512c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o old_blocks = old_fs->desc_blocks; 5131e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o new_blocks = fs->desc_blocks; 5141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 515c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (old_blocks == new_blocks) { 516c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 517c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 518c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 51924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 520052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o max = fs->group_desc_count; 521c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (max > old_fs->group_desc_count) 522c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o max = old_fs->group_desc_count; 523c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o group_blk = old_fs->super->s_first_data_block; 52424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 52524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're reducing the number of descriptor blocks, this 52624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * makes life easy. :-) We just have to mark some extra 52724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * blocks as free. 52824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 52924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (old_blocks > new_blocks) { 530052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (i = 0; i < max; i++) { 5311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!ext2fs_bg_has_super(fs, i)) { 5321e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 53324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o continue; 53424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 535c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (blk = group_blk+1+new_blocks; 536c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk < group_blk+1+old_blocks; blk++) { 5371e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_unmark_block_bitmap(fs->block_map, 53824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk); 539052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o rfs->needed_blocks--; 540052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 5411e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 54224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 543c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 544c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 54524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 54624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 54724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're increasing the number of descriptor blocks, life 5481e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * gets interesting.... 54924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 550052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (i = 0; i < max; i++) { 5511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!ext2fs_bg_has_super(fs, i)) 5521e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o goto next_group; 5531e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 5541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = group_blk; 5551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o blk < group_blk + 1 + new_blocks; blk++) { 5561e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 5571e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 5581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 5591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 5601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * Check to see if we overlap with the inode 561c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * or block bitmap, or the inode tables. If 562c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * not, and the block is in use, then mark it 563c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * as a block to be moved. 5641e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 565c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (IS_BLOCK_BM(fs, i, blk)) { 566c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o FS_BLOCK_BM(fs, i) = 0; 567052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o rfs->needed_blocks++; 568c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } else if (IS_INODE_BM(fs, i, blk)) { 569c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o FS_INODE_BM(fs, i) = 0; 570c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->needed_blocks++; 571c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } else if (IS_INODE_TB(fs, i, blk)) { 572c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o FS_INODE_TB(fs, i) = 0; 573c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->needed_blocks++; 574c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } else if (ext2fs_test_block_bitmap(old_fs->block_map, 575c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk) && 576c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) { 577c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 578c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 579052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o rfs->needed_blocks++; 580052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 58124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 5821e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_table && 5831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap && 5841e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_block_bitmap) 5851e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o goto next_group; 58624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 5871e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 588c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Reserve the existing meta blocks that we know 589c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * aren't to be moved. 5901e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 5911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_block_bitmap) 5921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 5931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_block_bitmap); 5941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_bitmap) 5951e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 5961e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap); 5971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_table) 5981e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->group_desc[i].bg_inode_table, j=0; 5991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 6001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 6011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o blk); 60224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 603c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 604c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Allocate the missing data structures 605c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 6061e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 6071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->reserve_blocks); 6081e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 609c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 61024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 6111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 612c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * For those structures that have changed, we need to 613c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * do bookkeepping. 6141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 615c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_BLOCK_BM(old_fs, i) != 616c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o (blk = FS_BLOCK_BM(fs, i))) { 617c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 618c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 619c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 620c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 621c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 622c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 623c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_INODE_BM(old_fs, i) != 624c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o (blk = FS_INODE_BM(fs, i))) { 625c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 626c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 627c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 628c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 629c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 630c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 63124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 632052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 633052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * The inode table, if we need to relocate it, is 634052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * handled specially. We have to reserve the blocks 635052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * for both the old and the new inode table, since we 636052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * can't have the inode table be destroyed during the 637052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block relocation phase. 638052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 639c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_INODE_TB(fs, i) == FS_INODE_TB(old_fs, i)) 640052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o goto next_group; /* inode table not moved */ 641052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 642c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->needed_blocks += fs->inode_blocks_per_group; 643052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 644052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 645052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Mark the new inode table as in use in the new block 646c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * allocation bitmap, and move any blocks that might 647c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * be necessary. 648052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 6491e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->group_desc[i].bg_inode_table, j=0; 650c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) { 6511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 652c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 653c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 654c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 655c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 656c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 657c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 6581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 659052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Make sure the old inode table is reserved in the 660052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block reservation bitmap. 6611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 662052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0; 663052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 664052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 6651e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 6661e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o next_group: 6671e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += rfs->new_fs->super->s_blocks_per_group; 6681e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 669c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 670c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 671c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 672c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (meta_bmap) 673c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_free_block_bitmap(meta_bmap); 674c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 675c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 6761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o} 67724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 678a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 679a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This helper function tries to allocate a new block. We try to 680a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * avoid hitting the original group descriptor blocks at least at 681a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * first, since we want to make it possible to recover from a badly 682a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * aborted resize operation as much as possible. 683a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 684a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In the future, I may further modify this routine to balance out 685a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * where we get the new blocks across the various block groups. 686a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Ideally we would allocate blocks that corresponded with the block 687a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * group of the containing inode, and keep contiguous blocks 688a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * together. However, this very difficult to do efficiently, since we 689a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * don't have the necessary information up front. 690a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 691a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 692a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define AVOID_OLD 1 693a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define DESPERATION 2 694a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 695a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic void init_block_alloc(ext2_resize_t rfs) 696a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 697a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = AVOID_OLD; 698a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = rfs->new_fs->super->s_first_data_block; 6992bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#if 0 7002bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* HACK for testing */ 7012bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o if (rfs->new_fs->super->s_blocks_count > 7022bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count) 7032bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->new_blk = rfs->old_fs->super->s_blocks_count; 7042bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#endif 705a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 706a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 707a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic blk_t get_new_block(ext2_resize_t rfs) 708a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 709a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 710a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 711a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 712a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->new_blk >= fs->super->s_blocks_count) { 713a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->alloc_state == DESPERATION) 714a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 715a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 716a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 717a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 718a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o printf("Going into desperation " 719a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o "mode for block allocations\n"); 720a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 721a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = DESPERATION; 722a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = fs->super->s_first_data_block; 723a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 724a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 725a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ext2fs_test_block_bitmap(fs->block_map, rfs->new_blk) || 726a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_test_block_bitmap(rfs->reserve_blocks, 727a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk) || 728a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ((rfs->alloc_state == AVOID_OLD) && 729bce49798f7f4380dff5693bc8308019b3cf8de25Theodore Ts'o (rfs->new_blk < rfs->old_fs->super->s_blocks_count) && 730a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_test_block_bitmap(rfs->old_fs->block_map, 731a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk))) { 732a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk++; 733a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 734a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 735a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return rfs->new_blk; 736a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 737a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 738a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 739a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs) 740a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 741a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk_t blk, old_blk, new_blk; 742a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 743a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys old_fs = rfs->old_fs; 744a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 745a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int size, c; 746a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int to_move, moved; 747a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 748a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = fs->super->s_first_data_block; 749a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->itable_buf) { 750a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(fs->blocksize * 751a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->inode_blocks_per_group, 752a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &rfs->itable_buf); 753a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 754a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 755a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 756a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->bmap, 0); 757a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 758a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 759a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 760a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 761a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * The first step is to figure out where all of the blocks 762a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will go. 763a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 764a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move = moved = 0; 765a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o init_block_alloc(rfs); 766a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o for (blk = old_fs->super->s_first_data_block; 767a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk < old_fs->super->s_blocks_count; blk++) { 768a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_block_bitmap(old_fs->block_map, blk)) 769a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 770a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk)) 771a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 772a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 773a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = get_new_block(rfs); 774a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_blk) { 775a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 776a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 777a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 778a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, new_blk); 779a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_add_extent_entry(rfs->bmap, blk, new_blk); 780a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move++; 781a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 782a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 783a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (to_move == 0) { 784a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = 0; 785a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 786a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 787a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 788a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 789a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Step two is to actually move the blocks 790a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 791a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, 0, 0, 0); 792a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 793a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 7943b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 7953b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS, 7963b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 7973b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 7983b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 7993b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 800a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 801a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size); 802a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 803a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!size) 804a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 805a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 806a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 807a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o printf("Moving %d blocks %u->%u\n", size, 808a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o old_blk, new_blk); 809a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 810a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o do { 811a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = size; 812a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (c > fs->inode_blocks_per_group) 813a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = fs->inode_blocks_per_group; 814a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = io_channel_read_blk(fs->io, old_blk, c, 815a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf); 816a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 817a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, c, 818a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf); 819a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 820a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o size -= c; 821a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk += c; 822a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o old_blk += c; 823a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved += c; 824a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 825a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 8263b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, 8273b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_BLOCK_RELOC_PASS, 828a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved, to_move); 8293b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 8303b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 831a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 832a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } while (size > 0); 833a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 834a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 835a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 836a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 837a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 838a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 839a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 840a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 841a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 842a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 843a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 3 844a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 845a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 846a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 847a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 848a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 849a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct process_block_struct { 850a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 851a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino_t ino; 852a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_inode * inode; 853a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t error; 854a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int is_dir; 855a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int changed; 856a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 857a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 858a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic int process_block(ext2_filsys fs, blk_t *block_nr, 859101c84f2e049bffcdb6c5ba1784842cdd50dbf05Theodore Ts'o blkcnt_t blockcnt, blk_t ref_block, 860a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int ref_offset, void *priv_data) 861a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 862a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct *pb; 863a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 864a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk_t block, new_block; 865a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int ret = 0; 866a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 867a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb = (struct process_block_struct *) priv_data; 868a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = *block_nr; 869a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->bmap) { 870a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_block = ext2fs_extent_translate(pb->rfs->bmap, block); 871a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (new_block) { 872a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *block_nr = new_block; 873a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_CHANGED; 874a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->changed = 1; 875a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 876a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->flags & RESIZE_DEBUG_BMOVE) 877101c84f2e049bffcdb6c5ba1784842cdd50dbf05Theodore Ts'o printf("ino=%ld, blockcnt=%ld, %u->%u\n", 878a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->ino, blockcnt, block, new_block); 879a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 880a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = new_block; 881a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 882a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 883a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->is_dir) { 884a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_add_dir_block(fs->dblist, pb->ino, 885101c84f2e049bffcdb6c5ba1784842cdd50dbf05Theodore Ts'o block, (int) blockcnt); 886a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) { 887a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->error = retval; 888a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_ABORT; 889a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 890a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 891a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return ret; 892a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 893a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 894a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 895a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Progress callback 896a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 897a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t progress_callback(ext2_filsys fs, ext2_inode_scan scan, 898a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dgrp_t group, void * priv_data) 899a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 900a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs = (ext2_resize_t) priv_data; 9013b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t retval; 902a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 903a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 904f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * This check is to protect against old ext2 libraries. It 905f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * shouldn't be needed against new libraries. 906a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 907f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o if ((group+1) == 0) 908a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 909a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 910a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 911a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 9123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 9133b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o group+1, fs->group_desc_count); 9143b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 9153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return retval; 916a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 917a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 918a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 919a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 920a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 921a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs) 922a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 923a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct pb; 924a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino_t ino, new_inode; 925a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_inode inode; 926a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_inode_scan scan = NULL; 927a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 928a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int group; 929a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o char *block_buf = 0; 930a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino_t start_to_move; 9312bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o blk_t orig_size; 932a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 933a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if ((rfs->old_fs->group_desc_count <= 934a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->group_desc_count) && 935a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o !rfs->bmap) 936a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 937a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 9382bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* 9392bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * Save the original size of the old filesystem, and 9402bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * temporarily set the size to be the new size if the new size 9412bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * is larger. We need to do this to avoid catching an error 9422bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * by the block iterator routines 9432bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o */ 9442bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o orig_size = rfs->old_fs->super->s_blocks_count; 9452bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o if (orig_size < rfs->new_fs->super->s_blocks_count) 9462bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count = 9472bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->new_fs->super->s_blocks_count; 9482bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o 949a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan); 950a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 951a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 952a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_init_dblist(rfs->old_fs, 0); 953a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 954a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(rfs->old_fs->blocksize * 3, 955a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &block_buf); 956a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 957a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 958a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o start_to_move = (rfs->new_fs->group_desc_count * 959a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_inodes_per_group); 960a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 9613b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 9623b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 9633b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, rfs->old_fs->group_desc_count); 9643b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 9653b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 9663b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 967a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs); 968a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.rfs = rfs; 969a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.inode = &inode; 970a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.error = 0; 971a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = EXT2_FIRST_INODE(rfs->new_fs->super); 972a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 973a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * First, copy all of the inodes that need to be moved 974a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * elsewhere in the inode table 975a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 976a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 977a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 978a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 979a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ino) 980a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 981a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 982a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (inode.i_links_count == 0) 983a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* inode not in use */ 984a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 985a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.is_dir = LINUX_S_ISDIR(inode.i_mode); 986a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.changed = 0; 987a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 988a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ext2fs_inode_has_valid_blocks(&inode) && 989a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (rfs->bmap || pb.is_dir)) { 990a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.ino = ino; 991a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_block_iterate2(rfs->old_fs, 992a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino, 0, block_buf, 993a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o process_block, &pb); 994a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 995a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 996a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.error) { 997a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = pb.error; 998a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 999a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1000a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1001a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1002a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ino <= start_to_move) 1003a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* Don't need to move it. */ 1004a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1005a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1006a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Find a new inode 1007a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1008a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1009a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_inode_bitmap(rfs->new_fs->inode_map, 1010a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode)) 1011a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 1012a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode++; 1013a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (new_inode > rfs->new_fs->super->s_inodes_count) { 1014a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 1015a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1016a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1017a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1018a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_inode_bitmap(rfs->new_fs->inode_map, new_inode); 1019a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.changed) { 1020a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* Get the new version of the inode */ 1021a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_read_inode(rfs->old_fs, ino, &inode); 1022a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1023a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1024a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_write_inode(rfs->old_fs, new_inode, &inode); 1025a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1026a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1027a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o group = (new_inode-1) / EXT2_INODES_PER_GROUP(rfs->new_fs->super); 1028a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (LINUX_S_ISDIR(inode.i_mode)) 1029a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->group_desc[group].bg_used_dirs_count++; 1030a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1031a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1032a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_INODEMAP) 1033a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o printf("Inode moved %ld->%ld\n", ino, new_inode); 1034a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1035a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) { 1036a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->imap, 0); 1037a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1038a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1039a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1040a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_add_extent_entry(rfs->imap, ino, new_inode); 1041a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1042a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(rfs->old_fs->io); 1043a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1044a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 10452bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count = orig_size; 1046a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->bmap) { 1047a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->bmap); 1048a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->bmap = 0; 1049a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1050a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (scan) 1051a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_close_inode_scan(scan); 1052a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (block_buf) 1053a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &block_buf); 1054a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1055a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1056a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1057a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1058a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1059a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 4. 1060a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1061a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1062a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1063a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1064a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct istruct { 1065a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 10663b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t err; 1067a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o unsigned long max; 1068a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int num; 1069a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 1070a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1071a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic int check_and_change_inodes(ino_t dir, int entry, 1072a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_dir_entry *dirent, int offset, 1073a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int blocksize, char *buf, void *priv_data) 1074a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1075a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct *is = (struct istruct *) priv_data; 10763b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o ino_t new_inode; 1077a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1078a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->progress && offset == 0) { 1079a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(is->rfs->old_fs->io); 10803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is->err = (is->rfs->progress)(is->rfs, 10813b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_INODE_REF_UPD_PASS, 10823b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o ++is->num, is->max); 10833b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is->err) 10843b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return DIRENT_ABORT; 1085a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1086a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1087a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!dirent->inode) 1088a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1089a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1090a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode); 1091a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1092a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_inode) 1093a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1094a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1095a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) 1096a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o printf("Inode translate (dir=%ld, name=%.*s, %u->%ld)\n", 1097a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dir, dirent->name_len, dirent->name, 1098a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode, new_inode); 1099a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode = new_inode; 1102a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1103a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return DIRENT_CHANGED; 1104a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1105a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1106a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs) 1107a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1108a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1109a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct is; 1110a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1111a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) 1112a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Now, we iterate over all of the directories to update the 1116a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode references 1117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.num = 0; 1119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.max = ext2fs_dblist_count(rfs->old_fs->dblist); 1120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.rfs = rfs; 11213b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is.err = 0; 1122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 11233b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 11243b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 11253b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, is.max); 11263b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 11273b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 11283b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 1131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o DIRENT_FLAG_INCLUDE_EMPTY, 0, 1132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o check_and_change_inodes, &is); 11333b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 11343b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 11353b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is.err) { 11363b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = is.err; 11373b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 11383b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 11403b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'oerrout: 1141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->imap); 1142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->imap = 0; 1143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 5. 1150a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1151a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we actually move the inode table around, and then 1152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the summary statistics. This is scary, since aborting here 1153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will potentially scramble the filesystem. (We are moving the 1154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode tables around in place, and so the potential for lost data, 1155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * or at the very least scrambling the mapping between filenames and 1156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode numbers is very high in case of a power failure here.) 1157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 116024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 116124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 1162052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * A very scary routine --- this one moves the inode table around!!! 1163052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * 1164052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * After this you have to use the rfs->new_fs file handle to read and 1165052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * write inodes. 1166052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1167c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs) 1168052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 116905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o int i, n, num, max, size, diff; 1170052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2_filsys fs = rfs->new_fs; 117105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o char *cp; 1172ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o blk_t old_blk, new_blk; 1173a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1174c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int to_move, moved; 1175052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1176052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o max = fs->group_desc_count; 1177052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (max > rfs->old_fs->group_desc_count) 1178052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o max = rfs->old_fs->group_desc_count; 1179052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 118005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o size = fs->blocksize * fs->inode_blocks_per_group; 118105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!rfs->itable_buf) { 1182ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = ext2fs_get_mem(size, (void **) &rfs->itable_buf); 1183ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 1184ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o return retval; 118505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o } 1186c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1187c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 1188c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Figure out how many inode tables we need to move 1189c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 1190c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move = moved = 0; 1191c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (i=0; i < max; i++) 1192c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc[i].bg_inode_table != 1193c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_inode_table) 1194c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move++; 1195c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1196c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (to_move == 0) 1197c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return 0; 1198c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 11993b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 12003b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 12013b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 12023b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 12033b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 12043b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 120563b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o 1206a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1207a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1208052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (i=0; i < max; i++) { 1209ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o old_blk = rfs->old_fs->group_desc[i].bg_inode_table; 1210ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o new_blk = fs->group_desc[i].bg_inode_table; 1211ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o diff = new_blk - old_blk; 1212052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 121380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 121405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 121505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o printf("Itable move group %d block " 1216c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o "%u->%u (diff %d)\n", 1217ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o i, old_blk, new_blk, diff); 121880c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1219052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 122005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!diff) 1221052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o continue; 1222052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1223ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = io_channel_read_blk(fs->io, old_blk, 122405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->inode_blocks_per_group, 122505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o rfs->itable_buf); 1226052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (retval) 1227a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 122805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 122905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * The end of the inode table segment often contains 1230a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * all zeros, and we're often only moving the inode 1231a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * table down a block or two. If so, we can optimize 1232a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * things by not rewriting blocks that we know to be zero 1233a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * already. 123405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 123505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o for (cp = rfs->itable_buf+size, n=0; n < size; n++, cp--) 123605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (*cp) 123705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o break; 123805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); 123980c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 124005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 124105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o printf("%d blocks of zeros...\n", n); 124280c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 124305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num = fs->inode_blocks_per_group; 124405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) 124505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num -= n; 124605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o 1247ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, 124805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num, rfs->itable_buf); 1249052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (retval) { 1250ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o io_channel_write_blk(fs->io, old_blk, 125105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num, rfs->itable_buf); 1252a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1253052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 125405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) { 125505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o retval = io_channel_write_blk(fs->io, 1256ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o old_blk + fs->inode_blocks_per_group, 1257a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o diff, (rfs->itable_buf + 1258a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (fs->inode_blocks_per_group - diff) * 1259a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->blocksize)); 126005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (retval) 1261a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1262c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 1263a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->group_desc[i].bg_inode_table = new_blk; 1264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_super_dirty(rfs->old_fs); 1265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 1266a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_flush(rfs->old_fs); 12673b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 12683b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o ++moved, to_move); 12693b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 12703b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 1271a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1272052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1273a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_flush(fs); 127480c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 127505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 127605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o printf("Inode table move finished.\n"); 127780c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1278052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1279052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 1281052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return retval; 1282052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1283052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1284052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o/* 1285052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Finally, recalculate the summary information 1286052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1287052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) 1288052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 1289052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o blk_t blk; 1290052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ino_t ino; 1291052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o int group = 0; 1292052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o int count = 0; 1293052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o int total_free = 0; 1294052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o int group_free = 0; 1295052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1296052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1297052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * First calculate the block statistics 1298052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1299052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (blk = fs->super->s_first_data_block; 1300052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o blk < fs->super->s_blocks_count; blk++) { 1301052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) { 1302052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1303052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free++; 1304052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1305052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1306052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if ((count == fs->super->s_blocks_per_group) || 1307052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o (blk == fs->super->s_blocks_count-1)) { 1308052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->group_desc[group++].bg_free_blocks_count = 1309052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free; 1310052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1311052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1312052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1313052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1314052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->super->s_free_blocks_count = total_free; 1315052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1316052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1317052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Next, calculate the inode statistics 1318052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1319052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1320052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free = 0; 1321052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1322052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group = 0; 1323052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (ino = 1; ino <= fs->super->s_inodes_count; ino++) { 1324052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) { 1325052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1326052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free++; 1327052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1328052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1329052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if ((count == fs->super->s_inodes_per_group) || 1330052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o (ino == fs->super->s_inodes_count)) { 1331052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->group_desc[group++].bg_free_inodes_count = 1332052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free; 1333052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1334052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1335052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1336052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1337052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->super->s_free_inodes_count = total_free; 1338052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2fs_mark_super_dirty(fs); 1339052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1340052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1341