resize2fs.c revision 7d7bdd578b307cad1dc248310eb279c6fb73b682
124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * resize2fs.c --- ext2 main routine 324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 40cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1997, 1998 by Theodore Ts'o and 50cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * PowerQuest, Inc. 60cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * 70cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * Copyright (C) 1999, 2000 by Theosore Ts'o 824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %Begin-Header% 100cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 110cee8a5c423c2a1054c7366e74870592ec8db95eTheodore Ts'o * License. 1224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * %End-Header% 1324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 1424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 1505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o/* 1605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Resizing a filesystem consists of the following phases: 1705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * 18a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1. Adjust superblock and write out new parts of the inode 1905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * table 20a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 2. Determine blocks which need to be relocated, and copy the 21a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * contents of blocks from their old locations to the new ones. 22a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 3. Scan the inode table, doing the following: 23a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * a. If blocks have been moved, update the block 24a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * pointers in the inodes and indirect blocks to 25a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * point at the new block locations. 26a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * b. If parts of the inode table need to be evacuated, 27a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * copy inodes from their old locations to their 28a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * new ones. 29a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * c. If (b) needs to be done, note which blocks contain 30a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * directory information, since we will need to 31a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the directory information. 32a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 4. Update the directory blocks with the new inode locations. 33a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 5. Move the inode tables, if necessary. 3405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 35a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 3624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o#include "resize2fs.h" 3724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 38546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o#ifdef __linux__ /* Kludge for debugging */ 39a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define RESIZE2FS_DEBUG 40a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 41a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 42a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size); 43a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs); 44a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs); 45a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs); 46a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs); 47a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs); 48a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs); 49a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 50a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 51a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Some helper CPP macros 52a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 53a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_BLOCK_BM(fs, i) ((fs)->group_desc[(i)].bg_block_bitmap) 54a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_BM(fs, i) ((fs)->group_desc[(i)].bg_inode_bitmap) 55a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define FS_INODE_TB(fs, i) ((fs)->group_desc[(i)].bg_inode_table) 56a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 57a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_BLOCK_BM(fs, i, blk) ((blk) == FS_BLOCK_BM((fs),(i))) 58a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_BM(fs, i, blk) ((blk) == FS_INODE_BM((fs),(i))) 59a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 60a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define IS_INODE_TB(fs, i, blk) (((blk) >= FS_INODE_TB((fs), (i))) && \ 61a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ((blk) < (FS_INODE_TB((fs), (i)) + \ 62a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (fs)->inode_blocks_per_group))) 63a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 64a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 65a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 66a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 67a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This is the top-level routine which does the dirty deed.... 68a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 69116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'oerrcode_t resize_fs(ext2_filsys fs, blk_t *new_size, int flags, 703b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t (*progress)(ext2_resize_t rfs, int pass, 71a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o unsigned long cur, 721333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o unsigned long max_val)) 73a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 74a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 75a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 76a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 77a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_read_bitmaps(fs); 78a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 79a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 80a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 81a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 82a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Create the data structure 83a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 84a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_resize_struct), 85a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &rfs); 86a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 87a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 88a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o memset(rfs, 0, sizeof(struct ext2_resize_struct)); 89a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 90a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs = fs; 91a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 92a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf = 0; 93a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->progress = progress; 94a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dup_handle(fs, &rfs->new_fs); 95a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 96a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 97a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 98116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o retval = adjust_superblock(rfs, *new_size); 99a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 102116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o *new_size = rfs->new_fs->super->s_blocks_count; 103116db1b513f6901415d1f5f8c01fc297d7cc64a4Theodore Ts'o 104a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = blocks_to_move(rfs); 105a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 106a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 107a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 108a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 109a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 110a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("Number of free blocks: %d/%d, Needed: %d\n"), 111a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->super->s_free_blocks_count, 112a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_free_blocks_count, 113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->needed_blocks); 114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 116a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = block_mover(rfs); 117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_scan_and_fix(rfs); 121a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = inode_ref_fix(rfs); 125a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 126a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 127a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 128a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_calculate_summary_stats(rfs->new_fs); 129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = move_itables(rfs); 133a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 134a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_close(rfs->new_fs); 137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->flags = flags; 141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->old_fs); 143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs->itable_buf); 145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs); 146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 149a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 150a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->new_fs) 151a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free(rfs->new_fs); 152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->itable_buf) 153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs->itable_buf); 154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &rfs); 155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 159a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 1. 161a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust the in-memory superblock information, and 163a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * initialize any new parts of the inode table. The new parts of the 164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode table are created in virgin disk space, so we can abort here 165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * without any side effects. 166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 167a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 16924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 17024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine adjusts the superblock and other data structures... 17124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 17224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'ostatic errcode_t adjust_superblock(ext2_resize_t rfs, blk_t new_size) 17324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 17424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o ext2_filsys fs; 17524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o int overhead = 0; 176c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int rem, adj = 0; 17724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 178dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t real_end; 17924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk_t blk, group_block; 1801e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o unsigned long i, j; 1811e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o int old_numblocks, numblocks, adjblocks; 18276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o int has_super, meta_bg, meta_bg_size, old_desc_blocks; 18363b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o unsigned long max_group; 18424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 18524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs = rfs->new_fs; 18624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_count = new_size; 1871e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_super_dirty(fs); 1881e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_bb_dirty(fs); 1891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_ib_dirty(fs); 19024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 19124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'oretry: 19224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->group_desc_count = (fs->super->s_blocks_count - 19324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_first_data_block + 19424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o EXT2_BLOCKS_PER_GROUP(fs->super) - 1) 19524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o / EXT2_BLOCKS_PER_GROUP(fs->super); 19624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (fs->group_desc_count == 0) 19724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 19824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->desc_blocks = (fs->group_desc_count + 19924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o EXT2_DESC_PER_BLOCK(fs->super) - 1) 20024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o / EXT2_DESC_PER_BLOCK(fs->super); 20124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 20224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 20324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Overhead is the number of bookkeeping blocks per group. It 20424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * includes the superblock backup, the group descriptor 20524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * backups, the inode bitmap, the block bitmap, and the inode 20624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * table. 20724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * 20824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * XXX Not all block groups need the descriptor blocks, but 20924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * being clever is tricky... 21024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 21124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o overhead = 3 + fs->desc_blocks + fs->inode_blocks_per_group; 21224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 21324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 21424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * See if the last group is big enough to support the 21524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * necessary data structures. If not, we need to get rid of 21624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * it. 21724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 21824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o rem = (fs->super->s_blocks_count - fs->super->s_first_data_block) % 21924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_per_group; 22024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if ((fs->group_desc_count == 1) && rem && (rem < overhead)) 22124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return EXT2_ET_TOOSMALL; 22224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (rem && (rem < overhead+50)) { 22324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_blocks_count -= rem; 22424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o goto retry; 22524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 22624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 22724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of inodes 22824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 22924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count = fs->super->s_inodes_per_group * 23024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->group_desc_count; 23124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 23224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 23324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the number of free blocks 23424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 23524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk = rfs->old_fs->super->s_blocks_count; 23624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (blk > fs->super->s_blocks_count) 23724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_free_blocks_count -= 23824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o (blk - fs->super->s_blocks_count); 23924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o else 24024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_free_blocks_count += 24124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o (fs->super->s_blocks_count - blk); 24224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 24324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 244c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Adjust the number of reserved blocks 245c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 246c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk = rfs->old_fs->super->s_r_blocks_count * 100 / 247c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->old_fs->super->s_blocks_count; 248c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->super->s_r_blocks_count = ((fs->super->s_blocks_count * blk) 249c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o / 100); 250c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 251c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 25224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Adjust the bitmaps for size 25324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 25424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o retval = ext2fs_resize_inode_bitmap(fs->super->s_inodes_count, 25524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_inodes_count, 25624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->inode_map); 257c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 25824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 25924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o real_end = ((EXT2_BLOCKS_PER_GROUP(fs->super) 26024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * fs->group_desc_count)) - 1 + 26124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o fs->super->s_first_data_block; 26224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o retval = ext2fs_resize_block_bitmap(fs->super->s_blocks_count-1, 26324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o real_end, fs->block_map); 26424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 265c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 26624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 26724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 26824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * Reallocate the group descriptors as necessary. 26924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 27024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (rfs->old_fs->desc_blocks != fs->desc_blocks) { 27176f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o retval = ext2fs_resize_mem(rfs->old_fs->desc_blocks * 27276f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o fs->blocksize, 27376f875daa1c9c2cdc72f0c6f0f7be4bbc7f0fc07Theodore Ts'o fs->desc_blocks * fs->blocksize, 274ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o (void **) &fs->group_desc); 275ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 276a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 27724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 2781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 2791e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Check to make sure there are enough inodes 281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 282a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if ((rfs->old_fs->super->s_inodes_count - 283a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->super->s_free_inodes_count) > 284a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_inodes_count) { 285a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 286a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 287a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 288a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 289a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 290a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * If we are shrinking the number block groups, we're done and 291a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * can exit now. 2921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 293c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc_count > fs->group_desc_count) { 294c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 295c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 296c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 297a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 298a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Fix the count of the last (old) block group 299a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 3001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o old_numblocks = (rfs->old_fs->super->s_blocks_count - 3011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->super->s_first_data_block) % 3021e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->super->s_blocks_per_group; 3031e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!old_numblocks) 3041e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o old_numblocks = rfs->old_fs->super->s_blocks_per_group; 3051e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (rfs->old_fs->group_desc_count == fs->group_desc_count) { 3061e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = (rfs->new_fs->super->s_blocks_count - 3071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->new_fs->super->s_first_data_block) % 3081e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->new_fs->super->s_blocks_per_group; 3091e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!numblocks) 3101e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = rfs->new_fs->super->s_blocks_per_group; 3111e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } else 3121e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = rfs->new_fs->super->s_blocks_per_group; 3131e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o i = rfs->old_fs->group_desc_count - 1; 3141e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_blocks_count += (numblocks-old_numblocks); 3151e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3161e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 317a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * If the number of block groups is staying the same, we're 318a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * done and can exit now. (If the number block groups is 319a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * shrinking, we had exited earlier.) 3201e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 321c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc_count >= fs->group_desc_count) { 322c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 323c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 324c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 325a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 326a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Initialize the new block group descriptors 327a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 328ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group, 329ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o (void **) &rfs->itable_buf); 330ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 331c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 332ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o 33305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o memset(rfs->itable_buf, 0, fs->blocksize * fs->inode_blocks_per_group); 3341e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block = fs->super->s_first_data_block + 3351e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->old_fs->group_desc_count * fs->super->s_blocks_per_group; 336c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 33763b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o adj = rfs->old_fs->group_desc_count; 33863b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o max_group = fs->group_desc_count - adj; 3393b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 3403b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 3413b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, max_group); 3423b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 3433b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 3443b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 34576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 34676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_desc_blocks = fs->super->s_first_meta_bg; 34776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o else 34876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_desc_blocks = fs->desc_blocks; 3491e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (i = rfs->old_fs->group_desc_count; 3501e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o i < fs->group_desc_count; i++) { 3511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o memset(&fs->group_desc[i], 0, 3521e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o sizeof(struct ext2_group_desc)); 3531e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks = 0; 3541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3551e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (i == fs->group_desc_count-1) { 3561e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = (fs->super->s_blocks_count - 3571e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_first_data_block) % 3581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_blocks_per_group; 3591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!numblocks) 3601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 3611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } else 3621e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks = fs->super->s_blocks_per_group; 3631e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 36476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = ext2fs_bg_has_super(fs, i); 36576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) { 36676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, group_block); 36776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o adjblocks++; 36876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 36976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg_size = (fs->blocksize / 37076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o sizeof (struct ext2_group_desc)); 37176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg = i / meta_bg_size; 37276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (!(fs->super->s_feature_incompat & 37376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) || 37476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o (meta_bg < fs->super->s_first_meta_bg)) { 37576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) { 37676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o for (j=0; j < old_desc_blocks; j++) 37776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, 37876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o group_block + 1 + j); 37976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o adjblocks += old_desc_blocks; 38076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 38176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 38276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 38376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = 1; 38476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (((i % meta_bg_size) == 0) || 38576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == 1) || 38676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == (meta_bg_size-1))) 3871e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, 38876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o group_block + has_super); 38924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 39076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 3911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o adjblocks += 2 + fs->inode_blocks_per_group; 3921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 3931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o numblocks -= adjblocks; 3941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_free_blocks_count -= adjblocks; 3951e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_free_inodes_count += 3961e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_inodes_per_group; 3971e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_blocks_count = numblocks; 3981e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_free_inodes_count = 3991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->super->s_inodes_per_group; 4001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_used_dirs_count = 0; 40124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 4021e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 0); 403c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 40424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 40505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 40605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * Write out the new inode table 40705e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 40805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o retval = io_channel_write_blk(fs->io, 40905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->group_desc[i].bg_inode_table, 41005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->inode_blocks_per_group, 41105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o rfs->itable_buf); 412c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) goto errout; 413c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 414a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 4153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 4163b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_EXTEND_ITABLE_PASS, 4173b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o i - adj + 1, max_group); 4183b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 4193b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 4203b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 4211e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_block += fs->super->s_blocks_per_group; 42224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 423c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o io_channel_flush(fs->io); 424c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 425c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 426c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 427c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 428c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o} 429c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 430a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 431a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 432a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 2. 433a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 434a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we adjust determine which blocks need to be moved, in 435a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * blocks_to_move(). We then copy the blocks to their ultimate new 436a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * destinations using block_mover(). Since we are copying blocks to 437a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * their new locations, again during this pass we can abort without 438a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * any problems. 439a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 440a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 441a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 442c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o/* 443c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * This helper function creates a block bitmap with all of the 444c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * filesystem meta-data blocks. 445c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 446c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t mark_table_blocks(ext2_filsys fs, 447c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap *ret_bmap) 448c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o{ 449c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk_t block, b; 45076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o int i,j, has_super, meta_bg, meta_bg_size; 45176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o int old_desc_blocks; 452c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap bmap; 453c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o errcode_t retval; 454c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 455a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("meta-data blocks"), 456a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o &bmap); 457c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 458c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 459c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 46076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); 461c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o block = fs->super->s_first_data_block; 46276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 46376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_desc_blocks = fs->super->s_first_meta_bg; 46476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o else 46576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_desc_blocks = fs->desc_blocks; 466c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (i = 0; i < fs->group_desc_count; i++) { 46776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = ext2fs_bg_has_super(fs, i); 46876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 469c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 470c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark this group's copy of the superblock 471c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 472c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, block); 473c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 47476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg = i / meta_bg_size; 475c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 47676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (!(fs->super->s_feature_incompat & 47776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) || 47876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o (meta_bg < fs->super->s_first_meta_bg)) { 47976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) { 48076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o /* 48176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * Mark this group's copy of the descriptors 48276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */ 48376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o for (j = 0; j < old_desc_blocks; j++) 48476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 48576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o block + j + 1); 48676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 48776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 48876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 48976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = 1; 49076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (((i % meta_bg_size) == 0) || 49176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == 1) || 49276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == (meta_bg_size-1))) 49376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 49476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o block + has_super); 49576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 49676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 497c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 498c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark the blocks used for the inode table 499c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 500c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (j = 0, b = fs->group_desc[i].bg_inode_table; 501c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j < fs->inode_blocks_per_group; 502c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j++, b++) 503c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, b); 504c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 505c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 506c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark block used for the block bitmap 507c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 508c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 509c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_block_bitmap); 510c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 511c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Mark block used for the inode bitmap 512c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 513c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(bmap, 514c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap); 515c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o block += fs->super->s_blocks_per_group; 516c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 517c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o *ret_bmap = bmap; 5181e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o return 0; 51924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o} 52024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 52124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 52276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * This function checks to see if a particular block (either a 52376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * superblock or a block group descriptor) overlaps with an inode or 52476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * block bitmap block, or with the inode table. 52576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */ 52676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'ostatic void mark_fs_metablock(ext2_resize_t rfs, 52776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_block_bitmap meta_bmap, 52876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o int group, blk_t blk) 52976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o{ 53076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2_filsys fs = rfs->new_fs; 53176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 53276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 53376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 53476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 53576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o /* 53676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * Check to see if we overlap with the inode or block bitmap, 53776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * or the inode tables. If not, and the block is in use, then 53876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o * mark it as a block to be moved. 53976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o */ 54076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (IS_BLOCK_BM(fs, group, blk)) { 54176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o FS_BLOCK_BM(fs, group) = 0; 54276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 54376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else if (IS_INODE_BM(fs, group, blk)) { 54476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o FS_INODE_BM(fs, group) = 0; 54576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 54676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else if (IS_INODE_TB(fs, group, blk)) { 54776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o FS_INODE_TB(fs, group) = 0; 54876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 54976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else if (ext2fs_test_block_bitmap(rfs->old_fs->block_map, blk) && 55076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) { 55176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, blk); 55276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o rfs->needed_blocks++; 55376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 55476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o} 55576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 55676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 55776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o/* 55824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * This routine marks and unmarks reserved blocks in the new block 55924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * bitmap. It also determines which blocks need to be moved and 56024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * places this information into the move_blocks bitmap. 56124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 562c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t blocks_to_move(ext2_resize_t rfs) 56324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o{ 56476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o int i, j, max_groups, has_super, meta_bg, meta_bg_size; 56524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk_t blk, group_blk; 56624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o unsigned long old_blocks, new_blocks; 56724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o errcode_t retval; 568c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2_filsys fs, old_fs; 569c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_block_bitmap meta_bmap; 57024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 571c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 572c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o old_fs = rfs->old_fs; 573c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (old_fs->super->s_blocks_count > fs->super->s_blocks_count) 574c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->old_fs; 575c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 576a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("reserved blocks"), 5771e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o &rfs->reserve_blocks); 57824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (retval) 57924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o return retval; 5801e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 581a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o retval = ext2fs_allocate_block_bitmap(fs, _("blocks to be moved"), 582c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o &rfs->move_blocks); 583c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 584c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 585c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 586bce49798f7f4380dff5693bc8308019b3cf8de25Theodore Ts'o retval = mark_table_blocks(old_fs, &meta_bmap); 587c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (retval) 588c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 589c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 590c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs = rfs->new_fs; 591c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 5921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 5931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * If we're shrinking the filesystem, we need to move all of 5941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * the blocks that don't fit any more 5951e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 5961e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->super->s_blocks_count; 597c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk < old_fs->super->s_blocks_count; blk++) { 598c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 599c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) { 600c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, blk); 6011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->needed_blocks++; 602c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 6031e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 6041e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 60524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 60676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) { 60776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_blocks = old_fs->super->s_first_meta_bg; 60876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o new_blocks = fs->super->s_first_meta_bg; 60976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 61076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o old_blocks = old_fs->desc_blocks; 61176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o new_blocks = fs->desc_blocks; 61276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } 61376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 614c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (old_blocks == new_blocks) { 615c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 616c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 617c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 61824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 6191333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = fs->group_desc_count; 6201333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o if (max_groups > old_fs->group_desc_count) 6211333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = old_fs->group_desc_count; 622c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o group_blk = old_fs->super->s_first_data_block; 62324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 62424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're reducing the number of descriptor blocks, this 62524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * makes life easy. :-) We just have to mark some extra 62624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * blocks as free. 62724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 62824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o if (old_blocks > new_blocks) { 6291333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i = 0; i < max_groups; i++) { 6301e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (!ext2fs_bg_has_super(fs, i)) { 6311e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 63224b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o continue; 63324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 634c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o for (blk = group_blk+1+new_blocks; 635c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk < group_blk+1+old_blocks; blk++) { 6361e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_unmark_block_bitmap(fs->block_map, 63724b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o blk); 638052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o rfs->needed_blocks--; 639052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 6401e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += fs->super->s_blocks_per_group; 64124b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 642c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 643c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 64424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 64524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o /* 64624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o * If we're increasing the number of descriptor blocks, life 6471e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o * gets interesting.... 64824b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o */ 64976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg_size = (fs->blocksize / sizeof (struct ext2_group_desc)); 6501333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i = 0; i < max_groups; i++) { 65176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = ext2fs_bg_has_super(fs, i); 65276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 65376dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, i, group_blk); 65476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 65576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o meta_bg = i / meta_bg_size; 65676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (!(fs->super->s_feature_incompat & 65776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o EXT2_FEATURE_INCOMPAT_META_BG) || 65876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o (meta_bg < fs->super->s_first_meta_bg)) { 659424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o if (has_super) { 660424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o for (blk = group_blk+1; 661424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o blk < group_blk + 1 + new_blocks; blk++) 662424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, 663424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o i, blk); 664424cb7b62aa417db2eaec79cfaec7433b31f8726Theodore Ts'o } 66576dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o } else { 66676dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (has_super) 66776dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o has_super = 1; 66876dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o if (((i % meta_bg_size) == 0) || 66976dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == 1) || 67076dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o ((i % meta_bg_size) == (meta_bg_size-1))) 67176dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o mark_fs_metablock(rfs, meta_bmap, i, 67276dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o group_blk + has_super); 67324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o } 67476dd5e5c2842fb1a7b858aad3e68b5e9c16890c9Theodore Ts'o 6751e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_table && 6761e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap && 6771e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_block_bitmap) 6781e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o goto next_group; 67924b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 6801e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 681c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Reserve the existing meta blocks that we know 682c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * aren't to be moved. 6831e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 6841e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_block_bitmap) 6851e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 6861e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_block_bitmap); 6871e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_bitmap) 6881e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 6891e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o fs->group_desc[i].bg_inode_bitmap); 6901e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (fs->group_desc[i].bg_inode_table) 6911e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->group_desc[i].bg_inode_table, j=0; 6921e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 6931e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, 6941e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o blk); 69524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 696c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 697c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Allocate the missing data structures 698c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 6991e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o retval = ext2fs_allocate_group_table(fs, i, 7001e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o rfs->reserve_blocks); 7011e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o if (retval) 702c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o goto errout; 70324b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 7041e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 705c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * For those structures that have changed, we need to 706c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * do bookkeepping. 7071e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 708c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_BLOCK_BM(old_fs, i) != 709c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o (blk = FS_BLOCK_BM(fs, i))) { 710c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 711c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 712c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 713c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 714c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 715c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 716c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_INODE_BM(old_fs, i) != 717c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o (blk = FS_INODE_BM(fs, i))) { 718c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 719c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 720c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 721c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 722c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 723c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 72424b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 725052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 726052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * The inode table, if we need to relocate it, is 727052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * handled specially. We have to reserve the blocks 728052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * for both the old and the new inode table, since we 729052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * can't have the inode table be destroyed during the 730052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block relocation phase. 731052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 732c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (FS_INODE_TB(fs, i) == FS_INODE_TB(old_fs, i)) 733052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o goto next_group; /* inode table not moved */ 734052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 735c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o rfs->needed_blocks += fs->inode_blocks_per_group; 736052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 737052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 738052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Mark the new inode table as in use in the new block 739c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * allocation bitmap, and move any blocks that might 740c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * be necessary. 741052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 7421e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o for (blk = fs->group_desc[i].bg_inode_table, j=0; 743c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) { 7441e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 745c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (ext2fs_test_block_bitmap(old_fs->block_map, blk) && 746c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o !ext2fs_test_block_bitmap(meta_bmap, blk)) 747c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_mark_block_bitmap(rfs->move_blocks, 748c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o blk); 749c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 750c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 7511e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o /* 752052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Make sure the old inode table is reserved in the 753052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * block reservation bitmap. 7541e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o */ 755052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (blk = rfs->old_fs->group_desc[i].bg_inode_table, j=0; 756052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o j < fs->inode_blocks_per_group ; j++, blk++) 757052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2fs_mark_block_bitmap(rfs->reserve_blocks, blk); 7581e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o 7591e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o next_group: 7601e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o group_blk += rfs->new_fs->super->s_blocks_per_group; 7611e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o } 762c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o retval = 0; 763c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 764c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'oerrout: 765c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (meta_bmap) 766c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o ext2fs_free_block_bitmap(meta_bmap); 767c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 768c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return retval; 7691e1da29fbd4204a267ebd7c64d37e1f95a9dad08Theodore Ts'o} 77024b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 771a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 772a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * This helper function tries to allocate a new block. We try to 773a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * avoid hitting the original group descriptor blocks at least at 774a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * first, since we want to make it possible to recover from a badly 775a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * aborted resize operation as much as possible. 776a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 777a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In the future, I may further modify this routine to balance out 778a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * where we get the new blocks across the various block groups. 779a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Ideally we would allocate blocks that corresponded with the block 780a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * group of the containing inode, and keep contiguous blocks 781a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * together. However, this very difficult to do efficiently, since we 782a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * don't have the necessary information up front. 783a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 784a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 785a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define AVOID_OLD 1 786a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#define DESPERATION 2 787a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 788a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic void init_block_alloc(ext2_resize_t rfs) 789a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 790a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = AVOID_OLD; 791a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = rfs->new_fs->super->s_first_data_block; 7922bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#if 0 7932bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* HACK for testing */ 7942bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o if (rfs->new_fs->super->s_blocks_count > 7952bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count) 7962bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->new_blk = rfs->old_fs->super->s_blocks_count; 7972bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o#endif 798a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 799a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 800a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic blk_t get_new_block(ext2_resize_t rfs) 801a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 802a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 803a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 804a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 805a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->new_blk >= fs->super->s_blocks_count) { 806a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->alloc_state == DESPERATION) 807a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 808a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 809a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 810a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 811a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("Going into desperation " 812a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o "mode for block allocations\n")); 813a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 814a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->alloc_state = DESPERATION; 815a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk = fs->super->s_first_data_block; 816a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 817a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 818a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ext2fs_test_block_bitmap(fs->block_map, rfs->new_blk) || 819a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_test_block_bitmap(rfs->reserve_blocks, 820a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk) || 821a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ((rfs->alloc_state == AVOID_OLD) && 822bce49798f7f4380dff5693bc8308019b3cf8de25Theodore Ts'o (rfs->new_blk < rfs->old_fs->super->s_blocks_count) && 823a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_test_block_bitmap(rfs->old_fs->block_map, 824a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk))) { 825a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_blk++; 826a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 827a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 828a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return rfs->new_blk; 829a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 830a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 831a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 832a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t block_mover(ext2_resize_t rfs) 833a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 834a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk_t blk, old_blk, new_blk; 835a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys fs = rfs->new_fs; 836a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_filsys old_fs = rfs->old_fs; 837a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 838a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int size, c; 839a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int to_move, moved; 8407d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2_badblocks_list badblock_list = 0; 8417d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o int bb_modified = 0; 8427d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o 8437d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o retval = ext2fs_read_bb_inode(old_fs, &badblock_list); 8447d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (retval) 8457d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o return retval; 846a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 847a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = fs->super->s_first_data_block; 848a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->itable_buf) { 849a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(fs->blocksize * 850a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->inode_blocks_per_group, 851a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &rfs->itable_buf); 852a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 853a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 854a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 855a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->bmap, 0); 856a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 857a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 858a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 859a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 860a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * The first step is to figure out where all of the blocks 861a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will go. 862a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 863a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move = moved = 0; 864a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o init_block_alloc(rfs); 865a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o for (blk = old_fs->super->s_first_data_block; 866a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk < old_fs->super->s_blocks_count; blk++) { 867a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_block_bitmap(old_fs->block_map, blk)) 868a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 869a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_block_bitmap(rfs->move_blocks, blk)) 870a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; 8717d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (ext2fs_badblocks_list_test(badblock_list, blk)) { 8727d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2fs_badblocks_list_del(badblock_list, blk); 8737d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o bb_modified++; 8747d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o continue; 8757d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o } 876a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 877a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk = get_new_block(rfs); 878a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_blk) { 879a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 880a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 881a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 882a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, new_blk); 883a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_add_extent_entry(rfs->bmap, blk, new_blk); 884a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o to_move++; 885a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 886a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 887a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (to_move == 0) { 888cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o if (rfs->bmap) { 889cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o ext2fs_free_extent_table(rfs->bmap); 890cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o rfs->bmap = 0; 891cefbf4870c0593e3c7a01b8d5494463b247d90f0Theodore Ts'o } 892a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = 0; 893a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 894a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 895a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 896a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 897a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Step two is to actually move the blocks 898a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 899a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, 0, 0, 0); 900a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 901a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 9023b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 9033b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_BLOCK_RELOC_PASS, 9043b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 9053b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 9063b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 9073b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 908a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 909a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_iterate_extent(rfs->bmap, &old_blk, &new_blk, &size); 910a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 911a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!size) 912a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 913a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 914a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_BMOVE) 915a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("Moving %d blocks %u->%u\n"), size, 916a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o old_blk, new_blk); 917a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 918a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o do { 919a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = size; 920a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (c > fs->inode_blocks_per_group) 921a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o c = fs->inode_blocks_per_group; 922a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = io_channel_read_blk(fs->io, old_blk, c, 923a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf); 924a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 925a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, c, 926a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->itable_buf); 927a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 928a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o size -= c; 929a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_blk += c; 930a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o old_blk += c; 931a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved += c; 932a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 933a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 9343b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, 9353b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_BLOCK_RELOC_PASS, 936a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o moved, to_move); 9373b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 9383b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 939a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 940a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } while (size > 0); 941a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 942a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 943a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 944a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 9457d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (badblock_list) { 9467d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o if (!retval && bb_modified) 9477d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o retval = ext2fs_update_bb_inode(old_fs, 9487d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o badblock_list); 9497d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o ext2fs_badblocks_list_free(badblock_list); 9507d7bdd578b307cad1dc248310eb279c6fb73b682Theodore Ts'o } 951a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 952a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 953a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 954a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 955a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 956a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 957a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 3 958a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 959a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 960a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 961a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 962a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 963a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct process_block_struct { 964a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 965dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino; 966a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_inode * inode; 967a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t error; 968a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int is_dir; 969a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int changed; 970a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 971a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 972a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic int process_block(ext2_filsys fs, blk_t *block_nr, 973084307590c5e28b6a8305933220ff5b2bd1bcda2Theodore Ts'o e2_blkcnt_t blockcnt, blk_t ref_block, 974a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int ref_offset, void *priv_data) 975a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 976a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct *pb; 977a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 978a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o blk_t block, new_block; 979a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int ret = 0; 980a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 981a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb = (struct process_block_struct *) priv_data; 982a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = *block_nr; 983a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->bmap) { 984a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_block = ext2fs_extent_translate(pb->rfs->bmap, block); 985a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (new_block) { 986a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o *block_nr = new_block; 987a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_CHANGED; 988a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->changed = 1; 989a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 990a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->rfs->flags & RESIZE_DEBUG_BMOVE) 991546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o printf(_("ino=%u, blockcnt=%lld, %u->%u\n"), 992a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->ino, blockcnt, block, new_block); 993a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 994a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o block = new_block; 995a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 996a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 997a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb->is_dir) { 998a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_add_dir_block(fs->dblist, pb->ino, 999101c84f2e049bffcdb6c5ba1784842cdd50dbf05Theodore Ts'o block, (int) blockcnt); 1000a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) { 1001a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb->error = retval; 1002a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ret |= BLOCK_ABORT; 1003a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1004a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1005a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return ret; 1006a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1007a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1008a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* 1009a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Progress callback 1010a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1011a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t progress_callback(ext2_filsys fs, ext2_inode_scan scan, 1012a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dgrp_t group, void * priv_data) 1013a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1014a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs = (ext2_resize_t) priv_data; 10153b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t retval; 1016a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1017a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1018f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * This check is to protect against old ext2 libraries. It 1019f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o * shouldn't be needed against new libraries. 1020a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1021f4b2a6db3f13f4210697bcd273086006c719929bTheodore Ts'o if ((group+1) == 0) 1022a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1023a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1024a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 1025a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(fs->io); 10263b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 10273b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o group+1, fs->group_desc_count); 10283b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 10293b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return retval; 1030a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1031a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1032a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1033a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1034a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1035a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_scan_and_fix(ext2_resize_t rfs) 1036a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1037a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct process_block_struct pb; 1038dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino, new_inode; 1039a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_inode inode; 1040a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_inode_scan scan = NULL; 1041a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1042a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int group; 1043a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o char *block_buf = 0; 1044dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t start_to_move; 10450ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o blk_t orig_size, new_block; 1046a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1047a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if ((rfs->old_fs->group_desc_count <= 1048a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->group_desc_count) && 1049a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o !rfs->bmap) 1050a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1051a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 10522bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o /* 10532bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * Save the original size of the old filesystem, and 10542bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * temporarily set the size to be the new size if the new size 10552bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * is larger. We need to do this to avoid catching an error 10562bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o * by the block iterator routines 10572bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o */ 10582bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o orig_size = rfs->old_fs->super->s_blocks_count; 10592bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o if (orig_size < rfs->new_fs->super->s_blocks_count) 10602bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count = 10612bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->new_fs->super->s_blocks_count; 10622bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o 1063a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_open_inode_scan(rfs->old_fs, 0, &scan); 1064a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1065a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1066a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_init_dblist(rfs->old_fs, 0); 1067a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1068a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_mem(rfs->old_fs->blocksize * 3, 1069a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (void **) &block_buf); 1070a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1071a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1072a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o start_to_move = (rfs->new_fs->group_desc_count * 1073a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->super->s_inodes_per_group); 1074a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 10753b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 10763b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_SCAN_PASS, 10773b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, rfs->old_fs->group_desc_count); 10783b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 10793b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 10803b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1081a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_set_inode_callback(scan, progress_callback, (void *) rfs); 1082a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.rfs = rfs; 1083a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.inode = &inode; 1084a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.error = 0; 1085a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = EXT2_FIRST_INODE(rfs->new_fs->super); 1086a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1087a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * First, copy all of the inodes that need to be moved 1088a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * elsewhere in the inode table 1089a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1090a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1091a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_get_next_inode(scan, &ino, &inode); 1092a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1093a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ino) 1094a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 1095a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1096a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (inode.i_links_count == 0) 1097a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* inode not in use */ 1098a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1099a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.is_dir = LINUX_S_ISDIR(inode.i_mode); 1100a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.changed = 0; 1101a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 11020ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o if (inode.i_file_acl && rfs->bmap) { 11030ccd488a764c14b27983b92435deca5e1adf9061Theodore Ts'o new_block = ext2fs_extent_translate(rfs->bmap, 1104ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o inode.i_file_acl); 1105ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (new_block) { 1106ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o inode.i_file_acl = new_block; 1107ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o retval = ext2fs_write_inode(rfs->old_fs, 1108ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o ino, &inode); 1109ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o if (retval) goto errout; 1110ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o } 1111ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o } 1112ed909bbe20d3fbeeee65c48dc0df2dbffdf2a0a9Theodore Ts'o 1113a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ext2fs_inode_has_valid_blocks(&inode) && 1114a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (rfs->bmap || pb.is_dir)) { 1115a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o pb.ino = ino; 1116a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_block_iterate2(rfs->old_fs, 1117a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ino, 0, block_buf, 1118a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o process_block, &pb); 1119a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1120a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1121a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.error) { 1122a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = pb.error; 1123a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1124a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1125a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1126a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1127a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (ino <= start_to_move) 1128a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o continue; /* Don't need to move it. */ 1129a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1130a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1131a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Find a new inode 1132a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1133a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o while (1) { 1134a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!ext2fs_test_inode_bitmap(rfs->new_fs->inode_map, 1135a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode)) 1136a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o break; 1137a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode++; 1138a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (new_inode > rfs->new_fs->super->s_inodes_count) { 1139a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ENOSPC; 1140a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1141a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1142a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1143a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_inode_bitmap(rfs->new_fs->inode_map, new_inode); 1144a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (pb.changed) { 1145a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* Get the new version of the inode */ 1146a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_read_inode(rfs->old_fs, ino, &inode); 1147a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1148a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1149085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o inode.i_ctime = time(0); 1150a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_write_inode(rfs->old_fs, new_inode, &inode); 1151a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) goto errout; 1152a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1153a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o group = (new_inode-1) / EXT2_INODES_PER_GROUP(rfs->new_fs->super); 1154a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (LINUX_S_ISDIR(inode.i_mode)) 1155a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->new_fs->group_desc[group].bg_used_dirs_count++; 1156a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1157a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1158a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_INODEMAP) 1159546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o printf(_("Inode moved %u->%u\n"), ino, new_inode); 1160a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1161a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) { 1162a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_create_extent_table(&rfs->imap, 0); 1163a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (retval) 1164a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1165a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1166a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_add_extent_entry(rfs->imap, ino, new_inode); 1167a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1168a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(rfs->old_fs->io); 1169a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1170a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 11712bc4d4f7e52ae1af9fb1a3dcff7c8752145d5a5cTheodore Ts'o rfs->old_fs->super->s_blocks_count = orig_size; 1172a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->bmap) { 1173a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->bmap); 1174a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->bmap = 0; 1175a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1176a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (scan) 1177a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_close_inode_scan(scan); 1178a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (block_buf) 1179a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_mem((void **) &block_buf); 1180a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1181a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1182a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1183a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1184a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1185a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 4. 1186a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1187a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1188a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1189a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1190a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostruct istruct { 1191a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2_resize_t rfs; 11923b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o errcode_t err; 11931333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o unsigned long max_dirs; 1194a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int num; 1195a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o}; 1196a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1197dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'ostatic int check_and_change_inodes(ext2_ino_t dir, int entry, 1198a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct ext2_dir_entry *dirent, int offset, 1199a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o int blocksize, char *buf, void *priv_data) 1200a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1201a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct *is = (struct istruct *) priv_data; 1202085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o struct ext2_inode inode; 1203085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o ext2_ino_t new_inode; 1204085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o errcode_t retval; 1205a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1206a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->progress && offset == 0) { 1207a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o io_channel_flush(is->rfs->old_fs->io); 12083b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is->err = (is->rfs->progress)(is->rfs, 12093b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o E2_RSZ_INODE_REF_UPD_PASS, 12101333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o ++is->num, is->max_dirs); 12113b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is->err) 12123b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o return DIRENT_ABORT; 1213a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1214a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1215a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!dirent->inode) 1216a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1217a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1218a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o new_inode = ext2fs_extent_translate(is->rfs->imap, dirent->inode); 1219a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1220a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!new_inode) 1221a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1222a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#ifdef RESIZE2FS_DEBUG 1223a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (is->rfs->flags & RESIZE_DEBUG_INODEMAP) 1224546a1ff18cc912003883ff67ba3e87c69f700fc4Theodore Ts'o printf(_("Inode translate (dir=%u, name=%.*s, %u->%u)\n"), 1225a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dir, dirent->name_len, dirent->name, 1226a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode, new_inode); 1227a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o#endif 1228a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1229a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o dirent->inode = new_inode; 1230a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1231085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o /* Update the directory mtime and ctime */ 1232085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o retval = ext2fs_read_inode(is->rfs->old_fs, dir, &inode); 1233085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o if (retval == 0) { 1234085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o inode.i_mtime = inode.i_ctime = time(0); 1235085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o ext2fs_write_inode(is->rfs->old_fs, dir, &inode); 1236085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o } 1237085d2a8397d4eb37ad604f568edb8b2662c22d46Theodore Ts'o 1238a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return DIRENT_CHANGED; 1239a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1240a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1241a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'ostatic errcode_t inode_ref_fix(ext2_resize_t rfs) 1242a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o{ 1243a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1244a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o struct istruct is; 1245a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1246a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (!rfs->imap) 1247a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return 0; 1248a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1249a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o /* 1250a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Now, we iterate over all of the directories to update the 1251a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode references 1252a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1253a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.num = 0; 12541333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o is.max_dirs = ext2fs_dblist_count(rfs->old_fs->dblist); 1255a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o is.rfs = rfs; 12563b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o is.err = 0; 1257a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 12583b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 12593b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = (rfs->progress)(rfs, E2_RSZ_INODE_REF_UPD_PASS, 12601333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o 0, is.max_dirs); 12613b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 12623b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 12633b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1264a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1265a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o retval = ext2fs_dblist_dir_iterate(rfs->old_fs->dblist, 1266a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o DIRENT_FLAG_INCLUDE_EMPTY, 0, 1267a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o check_and_change_inodes, &is); 12683b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 12693b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 12703b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (is.err) { 12713b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = is.err; 12723b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 12733b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 1274a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 12753b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'oerrout: 1276a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_free_extent_table(rfs->imap); 1277a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->imap = 0; 1278a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o return retval; 1279a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o} 1280a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1281a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 1282a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o/* -------------------------------------------------------------------- 1283a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1284a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * Resize processing, phase 5. 1285a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * 1286a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * In this phase we actually move the inode table around, and then 1287a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * update the summary statistics. This is scary, since aborting here 1288a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * will potentially scramble the filesystem. (We are moving the 1289a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode tables around in place, and so the potential for lost data, 1290a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * or at the very least scrambling the mapping between filenames and 1291a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * inode numbers is very high in case of a power failure here.) 1292a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * -------------------------------------------------------------------- 1293a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o */ 1294a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 129524b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o 129624b2c7a7a14cec8480a75af7d535cf267e6abe1fTheodore Ts'o/* 1297052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * A very scary routine --- this one moves the inode table around!!! 1298052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * 1299052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * After this you have to use the rfs->new_fs file handle to read and 1300052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * write inodes. 1301052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1302c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'ostatic errcode_t move_itables(ext2_resize_t rfs) 1303052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 13041333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o int i, n, num, max_groups, size, diff; 1305052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2_filsys fs = rfs->new_fs; 130605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o char *cp; 1307ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o blk_t old_blk, new_blk; 1308a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o errcode_t retval; 1309c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o int to_move, moved; 1310052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 13111333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = fs->group_desc_count; 13121333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o if (max_groups > rfs->old_fs->group_desc_count) 13131333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o max_groups = rfs->old_fs->group_desc_count; 1314052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 131505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o size = fs->blocksize * fs->inode_blocks_per_group; 131605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!rfs->itable_buf) { 1317ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = ext2fs_get_mem(size, (void **) &rfs->itable_buf); 1318ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o if (retval) 1319ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o return retval; 132005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o } 1321c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1322c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o /* 1323c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o * Figure out how many inode tables we need to move 1324c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o */ 1325c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move = moved = 0; 13261333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i=0; i < max_groups; i++) 1327c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (rfs->old_fs->group_desc[i].bg_inode_table != 1328c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o fs->group_desc[i].bg_inode_table) 1329c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o to_move++; 1330c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 1331c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o if (to_move == 0) 1332c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o return 0; 1333c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o 13343b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (rfs->progress) { 13353b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 13363b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o 0, to_move); 13373b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 13383b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 13393b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o } 134063b44fbe303ea00118cbe24cbbcde351a9bc0aacTheodore Ts'o 1341a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1342a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o 13431333fe93446a09ceb866a7f2a1ca0c196964b952Theodore Ts'o for (i=0; i < max_groups; i++) { 1344ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o old_blk = rfs->old_fs->group_desc[i].bg_inode_table; 1345ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o new_blk = fs->group_desc[i].bg_inode_table; 1346ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o diff = new_blk - old_blk; 1347052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 134880c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 134905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1350a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("Itable move group %d block " 1351a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o "%u->%u (diff %d)\n"), 1352ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o i, old_blk, new_blk, diff); 135380c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1354052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 135505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (!diff) 1356052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o continue; 1357052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1358ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = io_channel_read_blk(fs->io, old_blk, 135905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o fs->inode_blocks_per_group, 136005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o rfs->itable_buf); 1361052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (retval) 1362a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 136305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o /* 136405e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o * The end of the inode table segment often contains 1365a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * all zeros, and we're often only moving the inode 1366a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * table down a block or two. If so, we can optimize 1367a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * things by not rewriting blocks that we know to be zero 1368a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o * already. 136905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o */ 137005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o for (cp = rfs->itable_buf+size, n=0; n < size; n++, cp--) 137105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (*cp) 137205e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o break; 137305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o n = n >> EXT2_BLOCK_SIZE_BITS(fs->super); 137480c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 137505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1376a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("%d blocks of zeros...\n"), n); 137780c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 137805e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num = fs->inode_blocks_per_group; 137905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) 138005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num -= n; 138105e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o 1382ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, 138305e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num, rfs->itable_buf); 1384052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (retval) { 1385ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o io_channel_write_blk(fs->io, old_blk, 138605e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o num, rfs->itable_buf); 1387a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1388052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 138905e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (n > diff) { 139005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o retval = io_channel_write_blk(fs->io, 1391ca8abba7e0970fd1702db53e3f89ceb68c70768cTheodore Ts'o old_blk + fs->inode_blocks_per_group, 1392a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o diff, (rfs->itable_buf + 1393a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o (fs->inode_blocks_per_group - diff) * 1394a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o fs->blocksize)); 139505e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (retval) 1396a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o goto errout; 1397c762c8e63216a301c9de7d24c6136d8370378a08Theodore Ts'o } 1398a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o rfs->old_fs->group_desc[i].bg_inode_table = new_blk; 1399a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_mark_super_dirty(rfs->old_fs); 1400a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o if (rfs->progress) { 1401a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_flush(rfs->old_fs); 14023b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o retval = rfs->progress(rfs, E2_RSZ_MOVE_ITABLE_PASS, 14033b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o ++moved, to_move); 14043b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o if (retval) 14053b627e8d6735fd81906117d580ee70292b2cfaafTheodore Ts'o goto errout; 1406a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o } 1407052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1408a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'o ext2fs_flush(fs); 140980c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#ifdef RESIZE2FS_DEBUG 141005e112a11b6508c2b12d5d4ee0c322171db9b538Theodore Ts'o if (rfs->flags & RESIZE_DEBUG_ITABLEMOVE) 1411a13575f4d29a908add19ea27baa102bc6944ee30Theodore Ts'o printf(_("Inode table move finished.\n")); 141280c0fc3492278168448017e79730905aa5b9b62bTheodore Ts'o#endif 1413052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1414052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1415a8519a2dbec429846d89fee581a2ecb829904cd2Theodore Ts'oerrout: 1416052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return retval; 1417052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1418052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1419052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o/* 1420052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Finally, recalculate the summary information 1421052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1422052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'ostatic errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs) 1423052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o{ 1424dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o blk_t blk; 1425dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o ext2_ino_t ino; 1426dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o int group = 0; 1427dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o int count = 0; 1428dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o int total_free = 0; 1429dfcdc32f8d6623a35a9e66f503c535e4081b7266Theodore Ts'o int group_free = 0; 1430052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1431052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1432052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * First calculate the block statistics 1433052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1434052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (blk = fs->super->s_first_data_block; 1435052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o blk < fs->super->s_blocks_count; blk++) { 1436052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (!ext2fs_fast_test_block_bitmap(fs->block_map, blk)) { 1437052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1438052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free++; 1439052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1440052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1441052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if ((count == fs->super->s_blocks_per_group) || 1442052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o (blk == fs->super->s_blocks_count-1)) { 1443052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->group_desc[group++].bg_free_blocks_count = 1444052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free; 1445052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1446052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1447052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1448052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1449052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->super->s_free_blocks_count = total_free; 1450052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o 1451052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o /* 1452052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o * Next, calculate the inode statistics 1453052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o */ 1454052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1455052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free = 0; 1456052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1457052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group = 0; 1458052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o for (ino = 1; ino <= fs->super->s_inodes_count; ino++) { 1459052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if (!ext2fs_fast_test_inode_bitmap(fs->inode_map, ino)) { 1460052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free++; 1461052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o total_free++; 1462052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1463052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count++; 1464052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o if ((count == fs->super->s_inodes_per_group) || 1465052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o (ino == fs->super->s_inodes_count)) { 1466052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->group_desc[group++].bg_free_inodes_count = 1467052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free; 1468052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o count = 0; 1469052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o group_free = 0; 1470052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1471052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o } 1472052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o fs->super->s_free_inodes_count = total_free; 1473052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o ext2fs_mark_super_dirty(fs); 1474052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o return 0; 1475052db4b76e552682c1ad94ff4943faa98c958343Theodore Ts'o} 1476