initialize.c revision 48e6e81362f264aee4f3945c14928efaf71a06c9
16645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org/* 26645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * initialize.c --- initialize a filesystem handle given superblock 36645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * parameters. Used by mke2fs when initializing a filesystem. 46645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * 56645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * Copyright (C) 1994, 1995, 1996 Theodore Ts'o. 66645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * 76645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * %Begin-Header% 86645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * This file may be redistributed under the terms of the GNU Public 96645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * License. 106645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * %End-Header% 116645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org */ 126645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 136645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#include <stdio.h> 146645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#include <string.h> 156645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#if HAVE_UNISTD_H 166645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#include <unistd.h> 1749a07ad0977fb118fe91f5c908b6703e2d89dec6commit-bot@chromium.org#endif 18cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#include <fcntl.h> 196645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#include <time.h> 20cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#if HAVE_SYS_STAT_H 21cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#include <sys/stat.h> 226645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#endif 236645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#if HAVE_SYS_TYPES_H 24cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#include <sys/types.h> 25f16d797497aff698e4dfcef0885dce04915a8c36commit-bot@chromium.org#endif 26cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 27cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#include "ext2_fs.h" 28cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#include "ext2fs.h" 29cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 302e915b32347aa2c2bcf82aba57c325b8fb81ec53commit-bot@chromium.org#if defined(__linux__) && defined(EXT2_OS_LINUX) 31cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define CREATOR_OS EXT2_OS_LINUX 326645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#else 33cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#if defined(__GNU__) && defined(EXT2_OS_HURD) 34cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define CREATOR_OS EXT2_OS_HURD 356645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#else 366645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#if defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) 37cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define CREATOR_OS EXT2_OS_FREEBSD 38cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#else 39cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#if defined(LITES) && defined(EXT2_OS_LITES) 40cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define CREATOR_OS EXT2_OS_LITES 41cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#else 426645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#define CREATOR_OS EXT2_OS_LINUX /* by default */ 436645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#endif /* defined(LITES) && defined(EXT2_OS_LITES) */ 446645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#endif /* defined(__FreeBSD__) && defined(EXT2_OS_FREEBSD) */ 456645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#endif /* defined(__GNU__) && defined(EXT2_OS_HURD) */ 466645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org#endif /* defined(__linux__) && defined(EXT2_OS_LINUX) */ 476645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 486645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org/* 496645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * Note we override the kernel include file's idea of what the default 506645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * check interval (never) should be. It's a good idea to check at 516645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * least *occasionally*, specially since servers will never rarely get 526645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * to reboot, since Linux is so robust these days. :-) 536645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * 546645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * 180 days (six months) seems like a good value. 55cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org */ 56cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#ifdef EXT2_DFL_CHECKINTERVAL 57cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#undef EXT2_DFL_CHECKINTERVAL 58cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#endif 59cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define EXT2_DFL_CHECKINTERVAL (86400L * 180L) 60cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 61cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.orgerrcode_t ext2fs_initialize(const char *name, int flags, 626645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org struct ext2_super_block *param, 636645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org io_manager manager, ext2_filsys *ret_fs) 64cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org{ 65cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org ext2_filsys fs; 66cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org errcode_t retval; 67cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org struct ext2_super_block *super; 68cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org int frags_per_block; 69cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org int rem; 706645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org int overhead = 0; 716645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org blk_t group_block; 72cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org int ipg; 736645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org int i, j; 746645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org blk_t numblocks; 75cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org char *buf; 76cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org int meta_bg_size, meta_bg, has_super, old_desc_blocks; 776645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 786645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org if (!param || !param->s_blocks_count) 79cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org return EXT2_ET_INVALID_ARGUMENT; 806645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 816645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), 826645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org (void **) &fs); 836645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org if (retval) 841d38ae9162d9702a8999e1fe872ead3e0a3f1181sglez@google.com return retval; 851d38ae9162d9702a8999e1fe872ead3e0a3f1181sglez@google.com 86cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org memset(fs, 0, sizeof(struct struct_ext2_filsys)); 876645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; 88cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->flags = flags | EXT2_FLAG_RW; 89cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->umask = 022; 90f16d797497aff698e4dfcef0885dce04915a8c36commit-bot@chromium.org#ifdef WORDS_BIGENDIAN 91f16d797497aff698e4dfcef0885dce04915a8c36commit-bot@chromium.org fs->flags |= EXT2_FLAG_SWAP_BYTES; 92cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#endif 93cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org retval = manager->open(name, IO_FLAG_RW, &fs->io); 94cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (retval) 95cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org goto cleanup; 96cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->io->app_data = fs; 97cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org retval = ext2fs_get_mem(strlen(name)+1, (void **) &fs->device_name); 98cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (retval) 99cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org goto cleanup; 100cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 101cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org strcpy(fs->device_name, name); 102cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org retval = ext2fs_get_mem(SUPERBLOCK_SIZE, (void **) &super); 103cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (retval) 104cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org goto cleanup; 105cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->super = super; 106cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 107cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org memset(super, 0, SUPERBLOCK_SIZE); 108cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 109cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org#define set_field(field, default) (super->field = param->field ? \ 110cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org param->field : (default)) 111cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 112cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_magic = EXT2_SUPER_MAGIC; 113cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_state = EXT2_VALID_FS; 114cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 115cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_log_block_size, 0); /* default blocksize: 1024 bytes */ 116cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_log_frag_size, 0); /* default fragsize: 1024 bytes */ 117cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_first_data_block, super->s_log_block_size ? 0 : 1); 118cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_max_mnt_count, EXT2_DFL_MAX_MNT_COUNT); 119cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_errors, EXT2_ERRORS_DEFAULT); 120cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_feature_compat, 0); 121cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_feature_incompat, 0); 1226645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org set_field(s_feature_ro_compat, 0); 1236645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org set_field(s_first_meta_bg, 0); 124cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (super->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) 125cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org return EXT2_ET_UNSUPP_FEATURE; 126cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (super->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) 127cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org return EXT2_ET_RO_UNSUPP_FEATURE; 128cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 129cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_rev_level, EXT2_GOOD_OLD_REV); 130cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (super->s_rev_level >= EXT2_DYNAMIC_REV) { 131cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_first_ino, EXT2_GOOD_OLD_FIRST_INO); 132cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_inode_size, EXT2_GOOD_OLD_INODE_SIZE); 133cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org } 134cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 135cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org set_field(s_checkinterval, EXT2_DFL_CHECKINTERVAL); 136cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_mkfs_time = super->s_lastcheck = time(NULL); 137cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 1386645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org super->s_creator_os = CREATOR_OS; 1396645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 1406645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org fs->blocksize = EXT2_BLOCK_SIZE(super); 1416645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org fs->fragsize = EXT2_FRAG_SIZE(super); 1426645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org frags_per_block = fs->blocksize / fs->fragsize; 1436645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 1446645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org /* default: (fs->blocksize*8) blocks/group, up to 2^16 (GDT limit) */ 1456645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org set_field(s_blocks_per_group, fs->blocksize * 8); 1466645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org if (super->s_blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(super)) 147cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_blocks_per_group = EXT2_MAX_BLOCKS_PER_GROUP(super); 148cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_frags_per_group = super->s_blocks_per_group * frags_per_block; 149cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 1506645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org super->s_blocks_count = param->s_blocks_count; 151cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org super->s_r_blocks_count = param->s_r_blocks_count; 152cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (super->s_r_blocks_count >= param->s_blocks_count) { 153cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org retval = EXT2_ET_INVALID_ARGUMENT; 154cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org goto cleanup; 155cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org } 156cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 157cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org /* 158cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org * If we're creating an external journal device, we don't need 1596645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * to bother with the rest. 160cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org */ 161cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (super->s_feature_incompat & 162cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { 163cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->group_desc_count = 0; 1646645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org ext2fs_mark_super_dirty(fs); 1656645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org *ret_fs = fs; 1666645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org return 0; 1676645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org } 1682e915b32347aa2c2bcf82aba57c325b8fb81ec53commit-bot@chromium.org 169cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.orgretry: 170cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->group_desc_count = (super->s_blocks_count - 1716645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org super->s_first_data_block + 1726645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org EXT2_BLOCKS_PER_GROUP(super) - 1) 1736645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org / EXT2_BLOCKS_PER_GROUP(super); 174cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org if (fs->group_desc_count == 0) 175cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org return EXT2_ET_TOOSMALL; 176cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org fs->desc_blocks = (fs->group_desc_count + 177cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org EXT2_DESC_PER_BLOCK(super) - 1) 178cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org / EXT2_DESC_PER_BLOCK(super); 179cdd0f92b1aca0c2164ac1a24d7f14a6ad3cc10f5commit-bot@chromium.org 1806645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org i = fs->blocksize >= 4096 ? 1 : 4096 / fs->blocksize; 1816645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org set_field(s_inodes_count, super->s_blocks_count / i); 1826645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 1836645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org /* 1846645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * Make sure we have at least EXT2_FIRST_INO + 1 inodes, so 1856645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * that we have enough inodes for the filesystem(!) 1866645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org */ 1876645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org if (super->s_inodes_count < EXT2_FIRST_INODE(super)+1) 1886645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org super->s_inodes_count = EXT2_FIRST_INODE(super)+1; 1896645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org 1905f3f681db58d613f5b96caa0af45ba15f776fe96sglez@google.com /* 1916645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * There should be at least as many inodes as the user 1926645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * requested. Figure out how many inodes per group that 1936645cde43d7dbf0df76dbda2c089d8f58560e3e2commit-bot@chromium.org * should be. But make sure that we don't allocate more than 1945f3f681db58d613f5b96caa0af45ba15f776fe96sglez@google.com * one bitmap's worth of inodes each group. 195 */ 196 ipg = (super->s_inodes_count + fs->group_desc_count - 1) / 197 fs->group_desc_count; 198 if (ipg > fs->blocksize * 8) { 199 if (super->s_blocks_per_group >= 256) { 200 /* Try again with slightly different parameters */ 201 super->s_blocks_per_group -= 8; 202 super->s_blocks_count = param->s_blocks_count; 203 super->s_frags_per_group = super->s_blocks_per_group * 204 frags_per_block; 205 goto retry; 206 } else 207 return EXT2_ET_TOO_MANY_INODES; 208 } 209 210 if (ipg > EXT2_MAX_INODES_PER_GROUP(super)) 211 ipg = EXT2_MAX_INODES_PER_GROUP(super); 212 213 super->s_inodes_per_group = ipg; 214 if (super->s_inodes_count > ipg * fs->group_desc_count) 215 super->s_inodes_count = ipg * fs->group_desc_count; 216 217 /* 218 * Make sure the number of inodes per group completely fills 219 * the inode table blocks in the descriptor. If not, add some 220 * additional inodes/group. Waste not, want not... 221 */ 222 fs->inode_blocks_per_group = (((super->s_inodes_per_group * 223 EXT2_INODE_SIZE(super)) + 224 EXT2_BLOCK_SIZE(super) - 1) / 225 EXT2_BLOCK_SIZE(super)); 226 super->s_inodes_per_group = ((fs->inode_blocks_per_group * 227 EXT2_BLOCK_SIZE(super)) / 228 EXT2_INODE_SIZE(super)); 229 /* 230 * Finally, make sure the number of inodes per group is a 231 * multiple of 8. This is needed to simplify the bitmap 232 * splicing code. 233 */ 234 super->s_inodes_per_group &= ~7; 235 fs->inode_blocks_per_group = (((super->s_inodes_per_group * 236 EXT2_INODE_SIZE(super)) + 237 EXT2_BLOCK_SIZE(super) - 1) / 238 EXT2_BLOCK_SIZE(super)); 239 240 /* 241 * adjust inode count to reflect the adjusted inodes_per_group 242 */ 243 super->s_inodes_count = super->s_inodes_per_group * 244 fs->group_desc_count; 245 super->s_free_inodes_count = super->s_inodes_count; 246 247 /* 248 * Overhead is the number of bookkeeping blocks per group. It 249 * includes the superblock backup, the group descriptor 250 * backups, the inode bitmap, the block bitmap, and the inode 251 * table. 252 * 253 * XXX Not all block groups need the descriptor blocks, but 254 * being clever is tricky... 255 */ 256 overhead = (int) (3 + fs->desc_blocks + fs->inode_blocks_per_group); 257 258 /* This can only happen if the user requested too many inodes */ 259 if (overhead > super->s_blocks_per_group) 260 return EXT2_ET_TOO_MANY_INODES; 261 262 /* 263 * See if the last group is big enough to support the 264 * necessary data structures. If not, we need to get rid of 265 * it. 266 */ 267 rem = (int) ((super->s_blocks_count - super->s_first_data_block) % 268 super->s_blocks_per_group); 269 if ((fs->group_desc_count == 1) && rem && (rem < overhead)) 270 return EXT2_ET_TOOSMALL; 271 if (rem && (rem < overhead+50)) { 272 super->s_blocks_count -= rem; 273 goto retry; 274 } 275 276 /* 277 * At this point we know how big the filesystem will be. So 278 * we can do any and all allocations that depend on the block 279 * count. 280 */ 281 282 retval = ext2fs_get_mem(strlen(fs->device_name) + 80, 283 (void **) &buf); 284 if (retval) 285 goto cleanup; 286 287 sprintf(buf, "block bitmap for %s", fs->device_name); 288 retval = ext2fs_allocate_block_bitmap(fs, buf, &fs->block_map); 289 if (retval) 290 goto cleanup; 291 292 sprintf(buf, "inode bitmap for %s", fs->device_name); 293 retval = ext2fs_allocate_inode_bitmap(fs, buf, &fs->inode_map); 294 if (retval) 295 goto cleanup; 296 297 ext2fs_free_mem((void **) &buf); 298 299 retval = ext2fs_get_mem((size_t) fs->desc_blocks * fs->blocksize, 300 (void **) &fs->group_desc); 301 if (retval) 302 goto cleanup; 303 304 memset(fs->group_desc, 0, (size_t) fs->desc_blocks * fs->blocksize); 305 306 /* 307 * Reserve the superblock and group descriptors for each 308 * group, and fill in the correct group statistics for group. 309 * Note that although the block bitmap, inode bitmap, and 310 * inode table have not been allocated (and in fact won't be 311 * by this routine), they are accounted for nevertheless. 312 */ 313 group_block = super->s_first_data_block; 314 super->s_free_blocks_count = 0; 315 if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 316 old_desc_blocks = fs->super->s_first_meta_bg; 317 else 318 old_desc_blocks = fs->desc_blocks; 319 for (i = 0; i < fs->group_desc_count; i++) { 320 if (i == fs->group_desc_count-1) { 321 numblocks = (fs->super->s_blocks_count - 322 fs->super->s_first_data_block) % 323 fs->super->s_blocks_per_group; 324 if (!numblocks) 325 numblocks = fs->super->s_blocks_per_group; 326 } else 327 numblocks = fs->super->s_blocks_per_group; 328 329 has_super = ext2fs_bg_has_super(fs, i); 330 331 if (has_super) { 332 ext2fs_mark_block_bitmap(fs->block_map, group_block); 333 numblocks--; 334 } 335 meta_bg_size = (fs->blocksize / 336 sizeof (struct ext2_group_desc)); 337 meta_bg = i / meta_bg_size; 338 339 if (!(fs->super->s_feature_incompat & 340 EXT2_FEATURE_INCOMPAT_META_BG) || 341 (meta_bg < fs->super->s_first_meta_bg)) { 342 if (has_super) { 343 for (j=0; j < old_desc_blocks; j++) 344 ext2fs_mark_block_bitmap(fs->block_map, 345 group_block + j + 1); 346 numblocks -= old_desc_blocks; 347 } 348 } else { 349 if (has_super) 350 has_super = 1; 351 if (((i % meta_bg_size) == 0) || 352 ((i % meta_bg_size) == 1) || 353 ((i % meta_bg_size) == (meta_bg_size-1))) { 354 ext2fs_mark_block_bitmap(fs->block_map, 355 group_block + has_super); 356 numblocks--; 357 } 358 } 359 360 numblocks -= 2 + fs->inode_blocks_per_group; 361 362 super->s_free_blocks_count += numblocks; 363 fs->group_desc[i].bg_free_blocks_count = numblocks; 364 fs->group_desc[i].bg_free_inodes_count = 365 fs->super->s_inodes_per_group; 366 fs->group_desc[i].bg_used_dirs_count = 0; 367 368 group_block += super->s_blocks_per_group; 369 } 370 371 ext2fs_mark_super_dirty(fs); 372 ext2fs_mark_bb_dirty(fs); 373 ext2fs_mark_ib_dirty(fs); 374 375 io_channel_set_blksize(fs->io, fs->blocksize); 376 377 *ret_fs = fs; 378 return 0; 379cleanup: 380 ext2fs_free(fs); 381 return retval; 382} 383