--- old/usr/src/lib/libparted/common/libparted/fs/ext2/ext2.c 2014-07-17 16:13:48.645765411 +0200
+++ /dev/null 2014-07-17 16:13:48.000000000 +0200
@@ -1,792 +0,0 @@
-/*
- ext2.c -- generic ext2 stuff
- Copyright (C) 1998, 1999, 2000, 2001, 2007 Free Software Foundation, Inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-
-#include
-
-#ifndef DISCOVER_ONLY
-
-#include
-#include
-#include
-#include
-#include
-#include "ext2.h"
-
-/* ext2 stuff ****************************************************************/
-
-unsigned char _bitmap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
-
-int ext2_copy_block(struct ext2_fs *fs, blk_t from, blk_t to)
-{
- unsigned char* buf = ped_malloc (fs->blocksize);
-
- if (!ext2_bcache_flush(fs, from)) return 0;
- if (!ext2_bcache_flush(fs, to)) return 0;
-
- if (!ext2_read_blocks(fs, buf, from, 1)) return 0;
- if (!ext2_write_blocks(fs, buf, to, 1)) return 0;
-
- return 1;
-}
-
-int ext2_get_block_state(struct ext2_fs *fs, blk_t block)
-{
- struct ext2_buffer_head *bh;
- int group;
- int offset;
- int state;
-
- block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
- group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
- offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
-
- bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
- state = bh->data[offset>>3] & _bitmap[offset&7];
- ext2_brelse(bh, 0);
-
- return state;
-}
-
-blk_t ext2_find_free_block(struct ext2_fs *fs)
-{
- int i;
-
- for (i=0;inumgroups;i++)
- if (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[i]))
- {
- blk_t j;
- blk_t offset;
-
- offset = i * EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb)
- + EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
- for (j=fs->adminblocks;
- jsb);
- j++)
- if (ext2_is_data_block(fs, offset + j) &&
- !ext2_get_block_state(fs, offset + j))
- return offset + j;
-
- ped_exception_throw (PED_EXCEPTION_ERROR,
- PED_EXCEPTION_CANCEL,
- _("Inconsistent group descriptors!"));
- }
-
- ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
- _("File system full!"));
- return 0;
-}
-
-ino_t ext2_find_free_inode(struct ext2_fs *fs)
-{
- int i;
-
- for (i=0;inumgroups;i++)
- if (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[i]))
- {
- ino_t j;
- ino_t offset;
-
- offset = i * EXT2_SUPER_INODES_PER_GROUP(fs->sb) + 1;
- for (j=0;jsb);j++)
- if (!ext2_get_inode_state(fs, offset + j))
- return offset + j;
-
- ped_exception_throw (PED_EXCEPTION_ERROR,
- PED_EXCEPTION_CANCEL,
- _("Inconsistent group descriptors!"));
- }
-
- ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
- _("File system full!"));
- return 0;
-}
-
-int ext2_move_blocks(struct ext2_fs *fs, blk_t src, blk_t num, blk_t dest)
-{
- unsigned char *buf;
- blk_t i;
-
- ped_exception_fetch_all();
- if ((buf = ped_malloc(num << fs->logsize)) != NULL)
- {
- ped_exception_leave_all();
-
- if (!ext2_bcache_flush_range(fs, src, num)) return 0;
- if (!ext2_bcache_flush_range(fs, dest, num)) return 0;
-
- if (!ext2_read_blocks(fs, buf, src, num)) return 0;
- if (!ext2_write_blocks(fs, buf, dest, num)) return 0;
-
- ped_free(buf);
- return 1;
- }
- ped_exception_catch();
- ped_exception_leave_all();
-
- if (src > dest)
- {
- for (i=0;i0;i--)
- if (!ext2_copy_block(fs, src+i, dest+i))
- return 0;
- }
- return 1;
-}
-
-int ext2_read_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
-{
- return fs->devhandle->ops->read(fs->devhandle->cookie, ptr, block, num);
-}
-
-int ext2_set_block_state(struct ext2_fs *fs, blk_t block, int state, int updatemetadata)
-{
- struct ext2_buffer_head *bh;
- int group;
- int offset;
-
- block -= EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb);
- group = block / EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
- offset = block % EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb);
-
- bh = ext2_bread(fs, EXT2_GROUP_BLOCK_BITMAP(fs->gd[group]));
- bh->dirty = 1;
- if (state)
- bh->data[offset>>3] |= _bitmap[offset&7];
- else
- bh->data[offset>>3] &= ~_bitmap[offset&7];
- ext2_brelse(bh, 0);
-
- if (updatemetadata)
- {
- int diff;
-
- diff = state ? -1 : 1;
-
- fs->gd[group].bg_free_blocks_count = PED_CPU_TO_LE16
- (EXT2_GROUP_FREE_BLOCKS_COUNT(fs->gd[group]) + diff);
- fs->sb.s_free_blocks_count = PED_CPU_TO_LE32
- (EXT2_SUPER_FREE_BLOCKS_COUNT(fs->sb) + diff);
- fs->metadirty |= EXT2_META_SB | EXT2_META_GD;
- }
- return 1;
-}
-
-int ext2_write_blocks(struct ext2_fs *fs, void *ptr, blk_t block, blk_t num)
-{
- return fs->devhandle->ops->write(fs->devhandle->cookie, ptr, block, num);
-}
-
-int ext2_zero_blocks(struct ext2_fs *fs, blk_t block, blk_t num)
-{
- unsigned char *buf;
- blk_t i;
-
- ped_exception_fetch_all();
- buf = ped_malloc (num << fs->logsize);
- if (buf)
- {
- ped_exception_leave_all();
-
- memset(buf, 0, num << fs->logsize);
- if (!ext2_bcache_flush_range(fs, block, num))
- goto error_free_buf;
- if (!ext2_write_blocks(fs, buf, block, num))
- goto error_free_buf;
- ped_free(buf);
- return 1;
- }
- ped_exception_catch();
-
- buf = ped_malloc (fs->blocksize);
- if (buf)
- {
- ped_exception_leave_all();
-
- memset(buf, 0, fs->blocksize);
-
- for (i=0;idirty = 1;
- if (!ext2_brelse(bh, 1))
- goto error;
- }
- return 1;
-
-error_free_buf:
- ped_free(buf);
-error:
- return 0;
-}
-
-off_t ext2_get_inode_offset(struct ext2_fs *fs, ino_t inode, blk_t *block)
-{
- int group;
- int offset;
-
- inode--;
-
- group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
- offset = (inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb))
- * sizeof(struct ext2_inode);
-
- *block = EXT2_GROUP_INODE_TABLE(fs->gd[group])
- + (offset >> fs->logsize);
-
- return offset & (fs->blocksize - 1);
-}
-
-int ext2_get_inode_state(struct ext2_fs *fs, ino_t inode)
-{
- struct ext2_buffer_head *bh;
- int group;
- int offset;
- int ret;
-
- inode--;
- group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
- offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
-
- bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
- ret = bh->data[offset>>3] & _bitmap[offset&7];
- ext2_brelse(bh, 0);
-
- return ret;
-}
-
-int ext2_read_inode(struct ext2_fs *fs, ino_t inode, struct ext2_inode *data)
-{
- struct ext2_buffer_head *bh;
- blk_t blk;
- off_t off;
-
- off = ext2_get_inode_offset(fs, inode, &blk);
-
- bh = ext2_bread(fs, blk);
- if (!bh)
- return 0;
-
- memcpy(data, bh->data + off, sizeof(struct ext2_inode));
- ext2_brelse(bh, 0);
- return 1;
-}
-
-int ext2_set_inode_state(struct ext2_fs *fs, ino_t inode, int state, int updatemetadata)
-{
- struct ext2_buffer_head *bh;
- int group;
- int offset;
-
- inode--;
- group = inode / EXT2_SUPER_INODES_PER_GROUP(fs->sb);
- offset = inode % EXT2_SUPER_INODES_PER_GROUP(fs->sb);
-
- bh = ext2_bread(fs, EXT2_GROUP_INODE_BITMAP(fs->gd[group]));
- if (!bh)
- return 0;
- bh->dirty = 1;
- if (state)
- bh->data[offset>>3] |= _bitmap[offset&7];
- else
- bh->data[offset>>3] &= ~_bitmap[offset&7];
- ext2_brelse(bh, 0);
-
- if (updatemetadata)
- {
- int diff;
-
- diff = state ? -1 : 1;
-
- fs->gd[group].bg_free_inodes_count = PED_CPU_TO_LE16
- (EXT2_GROUP_FREE_INODES_COUNT(fs->gd[group]) + diff);
- fs->sb.s_free_inodes_count = PED_CPU_TO_LE32
- (EXT2_SUPER_FREE_INODES_COUNT(fs->sb) + diff);
- fs->metadirty = EXT2_META_SB | EXT2_META_GD;
- }
- return 1;
-}
-
-static void
-_inode_update_size(struct ext2_fs *fs, struct ext2_inode *inode, int delta)
-{
- int i512perblock = 1 << (fs->logsize - 9);
- uint64_t size;
-
- /* i_blocks is in 512 byte blocks */
- inode->i_blocks = PED_CPU_TO_LE32(EXT2_INODE_BLOCKS(*inode)
- + delta * i512perblock);
- size = EXT2_INODE_SIZE(*inode) + delta * fs->blocksize;
- inode->i_size = PED_CPU_TO_LE32(size % (1LL << 32));
- inode->i_size_high = PED_CPU_TO_LE32(size / (1LL << 32));
- inode->i_mtime = PED_CPU_TO_LE32(time(NULL));
-}
-
-int ext2_do_inode(struct ext2_fs *fs, struct ext2_inode *inode, blk_t block,
- int action)
-{
- struct ext2_buffer_head *bh;
- uint32_t *udata;
- blk_t count = 0;
- int i;
- int u32perblock = fs->blocksize >> 2;
- int i512perblock = 1 << (fs->logsize - 9);
-
- if (block == 0 || EXT2_INODE_MODE(*inode) == 0)
- return -1;
-
- if (fs->opt_debug)
- switch (action)
- {
- case EXT2_ACTION_ADD:
- fprintf(stderr,"adding 0x%04x to inode\n",
- block);
- break;
- case EXT2_ACTION_DELETE:
- fprintf(stderr,"deleting 0x%04x from inode\n",
- block);
- break;
- case EXT2_ACTION_FIND:
- fprintf(stderr,"finding 0x%04x in inode\n",
- block);
- break;
- }
-
- /* Direct blocks for first 12 blocks */
- for (i = 0; i < EXT2_NDIR_BLOCKS; i++)
- {
- if (action == EXT2_ACTION_ADD && !EXT2_INODE_BLOCK(*inode, i))
- {
- inode->i_block[i] = PED_CPU_TO_LE32(block);
- _inode_update_size (fs, inode, 1);
- ext2_set_block_state(fs, block, 1, 1);
- return i;
- }
- if (EXT2_INODE_BLOCK(*inode, i) == block)
- {
- if (action == EXT2_ACTION_DELETE)
- {
- inode->i_block[i] = 0;
- _inode_update_size (fs, inode, -1);
- ext2_set_block_state(fs, block, 0, 1);
- }
- return i;
- }
- if (EXT2_INODE_BLOCK(*inode, i))
- count += i512perblock;
- }
-
- count += EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ? i512perblock : 0;
- count += EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ? i512perblock : 0;
- count += EXT2_INODE_BLOCK(*inode, EXT2_TIND_BLOCK) ? i512perblock : 0;
-
- if (!EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK) ||
- (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
- return -1;
-
- bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_IND_BLOCK));
- udata = (uint32_t *)bh->data;
-
- /* Indirect blocks for next 256/512/1024 blocks (for 1k/2k/4k blocks) */
- for (i = 0; i < u32perblock; i++) {
- if (action == EXT2_ACTION_ADD && !udata[i]) {
- bh->dirty = 1;
- udata[i] = PED_CPU_TO_LE32(block);
- _inode_update_size (fs, inode, 1);
- ext2_set_block_state(fs, block, 1, 1);
- ext2_brelse(bh, 0);
- return EXT2_NDIR_BLOCKS + i;
- }
- if (PED_LE32_TO_CPU(udata[i]) == block) {
- if (action == EXT2_ACTION_DELETE) {
- bh->dirty = 1;
- udata[i] = 0;
- _inode_update_size (fs, inode, -1);
- ext2_set_block_state(fs, block, 0, 1);
- }
- ext2_brelse(bh, 0);
- return EXT2_NDIR_BLOCKS + i;
- }
- if (udata[i])
- {
- count += i512perblock;
- if (count >= EXT2_INODE_BLOCKS(*inode) &&
- action != EXT2_ACTION_ADD)
- return -1;
- }
- }
-
- ext2_brelse(bh, 0);
-
- if (!EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK) ||
- (count >= EXT2_INODE_BLOCKS(*inode) && action != EXT2_ACTION_ADD))
- return -1;
- bh = ext2_bread(fs, EXT2_INODE_BLOCK(*inode, EXT2_DIND_BLOCK));
- udata = (uint32_t *)bh->data;
-
- /* Double indirect blocks for next 2^16/2^18/2^20 1k/2k/4k blocks */
- for (i = 0; i < u32perblock; i++) {
- struct ext2_buffer_head *bh2;
- uint32_t *udata2;
- int j;
-
- if (!udata[i]) {
- ext2_brelse(bh, 0);
- return -1;
- }
- bh2 = ext2_bread(fs, PED_LE32_TO_CPU(udata[i]));
- udata2 = (uint32_t *)bh2->data;
- count += i512perblock;
-
- for (j = 0; j < u32perblock; j++) {
- if (action == EXT2_ACTION_ADD && !udata2[j]) {
- bh2->dirty = 1;
- udata2[j] = PED_CPU_TO_LE32(block);
- _inode_update_size (fs, inode, 1);
- ext2_set_block_state(fs, block, 1, 1);
- ext2_brelse(bh, 0);
- ext2_brelse(bh2, 0);
- return EXT2_NDIR_BLOCKS + i * u32perblock + j;
- }
- if (PED_LE32_TO_CPU(udata2[j]) == block) {
- if (action == EXT2_ACTION_DELETE) {
- bh2->dirty = 1;
- udata2[j] = 0;
- _inode_update_size (fs, inode, -1);
- ext2_set_block_state(fs, block, 0, 1);
- }
- ext2_brelse(bh, 0);
- ext2_brelse(bh2, 0);
- return EXT2_NDIR_BLOCKS + i * u32perblock + j;
- }
- if (udata2[j])
- {
- count += i512perblock;
- if (count >= EXT2_INODE_BLOCKS(*inode) &&
- action != EXT2_ACTION_ADD)
- return -1;
- }
- }
- ext2_brelse(bh2, 0);
- }
- ext2_brelse(bh, 0);
-
- /* FIXME: we should check for triple-indirect blocks here, but it
- * would be nice to have a better routine to traverse blocks, and
- * file systems that need triple-indirect blocks for the resize
- * inode are too big to worry about yet.
- */
-
- return -1;
-}
-
-int ext2_write_inode(struct ext2_fs *fs, ino_t inode, const struct ext2_inode *data)
-{
- struct ext2_buffer_head *bh;
- blk_t blk;
- off_t off;
-
- off = ext2_get_inode_offset(fs, inode, &blk);
-
- bh = ext2_bread(fs, blk);
- if (!bh)
- return 0;
- bh->dirty = 1;
- memcpy(bh->data + off, data, sizeof(struct ext2_inode));
- ext2_brelse(bh, 0);
-
- return 1;
-}
-
-int ext2_zero_inode(struct ext2_fs *fs, ino_t inode)
-{
- struct ext2_inode buf;
-
- memset(&buf, 0, sizeof(struct ext2_inode));
- return ext2_write_inode(fs, inode, &buf);
-}
-
-
-
-
-
-/* check whether y is root of x
- * (formula grabbed from linux ext2 kernel source) */
-static int is_root(int x, int y)
-{
- if (!x)
- return 1;
-
- while (1)
- {
- if (x == 1)
- return 1;
-
- if (x % y)
- return 0;
-
- x /= y;
- }
-}
-
-/* check whether group contains a superblock copy on file systems
- * where not all groups have one (sparse superblock feature) */
-int ext2_is_group_sparse(struct ext2_fs *fs, int group)
-{
- if (!fs->sparse)
- return 1;
-
- if (is_root(group, 3) || is_root(group, 5) || is_root(group, 7))
- return 1;
-
- return 0;
-}
-
-void ext2_close(struct ext2_fs *fs)
-{
- ext2_commit_metadata(fs, EXT2_META_PRIMARY | EXT2_META_BACKUP);
- ext2_sync(fs);
-
- ext2_bcache_deinit(fs);
-
- fs->devhandle->ops->close(fs->devhandle->cookie);
-
- ped_free(fs->gd);
- ped_free(fs);
-}
-
-int ext2_commit_metadata(struct ext2_fs *fs, int copies)
-{
- int i;
- int num;
- int wmeta = fs->metadirty & copies;
- unsigned char* sb = ped_malloc(fs->blocksize);
- struct ext2_super_block *sb_for_io;
- int sb_block;
-
- /* See if there is even anything to write... */
- if (wmeta == EXT2_META_CLEAN)
- return 1;
-
- fs->sb.s_r_blocks_count = PED_CPU_TO_LE32 (
- fs->r_frac * (loff_t)EXT2_SUPER_BLOCKS_COUNT(fs->sb)
- / 100);
-
- if (!ext2_read_blocks (fs, sb, 0, 1))
- return 0;
-
- if (EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb)) {
- memcpy(sb, &fs->sb, 1024);
- sb_for_io = (struct ext2_super_block *) sb;
- } else {
- memcpy(sb+1024, &fs->sb, 1024);
- sb_for_io = (struct ext2_super_block *) (sb + 1024);
- }
-
- num = copies & EXT2_META_BACKUP ? fs->numgroups : 1;
-
- for (i = 0, sb_block = EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb); i < num;
- i++, sb_block += EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb))
- {
-
- if (!ext2_is_group_sparse(fs, i))
- continue;
-
- if (fs->dynamic_version)
- sb_for_io->s_block_group_nr = PED_CPU_TO_LE16 (i);
-
- if ((i == 0 && wmeta & EXT2_META_PRIMARY_SB) ||
- (i != 0 && wmeta & EXT2_META_SB))
- {
- if (!ext2_bcache_flush_range(fs, sb_block, 1))
- return 0;
- if (!ext2_write_blocks(fs, sb, sb_block, 1))
- return 0;
- }
- if ((i == 0 && wmeta & EXT2_META_PRIMARY_GD) ||
- (i != 0 && wmeta & EXT2_META_GD))
- {
- if (!ext2_bcache_flush_range(fs, sb_block + 1,
- fs->gdblocks))
- return 0;
- if (!ext2_write_blocks(fs, fs->gd, sb_block + 1,
- fs->gdblocks))
- return 0;
- }
- }
-
- sb_for_io->s_block_group_nr = 0;
-
- /* Clear the flags of the components we just finished writing. */
- fs->metadirty &= ~copies;
-
- return 1;
-}
-
-int ext2_sync(struct ext2_fs *fs)
-{
- if (!ext2_commit_metadata(fs, EXT2_META_PRIMARY)) return 0;
- if (!ext2_bcache_sync(fs)) return 0;
- if (!fs->devhandle->ops->sync(fs->devhandle->cookie)) return 0;
- return 1;
-}
-
-struct ext2_fs *ext2_open(struct ext2_dev_handle *handle, int state)
-{
- struct ext2_fs *fs;
-
- if ((fs = (struct ext2_fs *) ped_malloc(sizeof(struct ext2_fs)))
- == NULL)
- goto error;
-
- handle->ops->set_blocksize(handle->cookie, 10);
-
- if (!handle->ops->read(handle->cookie, &fs->sb, 1, 1)
- || EXT2_SUPER_MAGIC(fs->sb) != EXT2_SUPER_MAGIC_CONST)
- {
- ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
- _("Invalid superblock. Are you sure this is an ext2 "
- "file system?"));
- goto error_free_fs;
- }
-
-
- fs->opt_debug = 1;
- fs->opt_safe = 1;
- fs->opt_verbose = 0;
-
- if (EXT2_SUPER_STATE(fs->sb) & EXT2_ERROR_FS & ~(state & EXT2_ERROR_FS))
- {
- if (ped_exception_throw (
- PED_EXCEPTION_WARNING, PED_EXCEPTION_IGNORE_CANCEL,
- _("File system has errors! You should run e2fsck."))
- == PED_EXCEPTION_CANCEL)
- goto error_free_fs;
- }
-
- if (!((EXT2_SUPER_STATE(fs->sb) | state) & EXT2_VALID_FS)
- || (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
- & EXT3_FEATURE_INCOMPAT_RECOVER))
- {
- if (ped_exception_throw (
- PED_EXCEPTION_ERROR, PED_EXCEPTION_IGNORE_CANCEL,
- _("File system was not cleanly unmounted! "
- "You should run e2fsck. Modifying an unclean "
- "file system could cause severe corruption."))
- != PED_EXCEPTION_IGNORE)
- goto error_free_fs;
- }
-
- fs->dynamic_version = EXT2_SUPER_REV_LEVEL (fs->sb) > 0;
-
- if ((EXT2_SUPER_FEATURE_COMPAT(fs->sb)
- & ~(EXT3_FEATURE_COMPAT_HAS_JOURNAL |
- EXT2_FEATURE_COMPAT_HAS_DIR_INDEX)) ||
- (EXT2_SUPER_FEATURE_INCOMPAT(fs->sb)
- & ~(EXT2_FEATURE_INCOMPAT_FILETYPE |
- EXT3_FEATURE_INCOMPAT_RECOVER)) ||
- (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
- & ~(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER |
- EXT2_FEATURE_RO_COMPAT_LARGE_FILE)))
- {
- ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
- _("File system has an incompatible feature enabled."));
- goto error_free_fs;
- }
-
- fs->devhandle = handle;
- fs->logsize = EXT2_SUPER_LOG_BLOCK_SIZE(fs->sb) + 10;
- handle->ops->set_blocksize(handle->cookie, fs->logsize);
-
- if (!ext2_bcache_init(fs))
- {
- ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
- _("Error allocating buffer cache."));
- goto error_free_fs;
- }
-
- fs->blocksize = 1 << fs->logsize;
-
- fs->numgroups = ped_div_round_up (EXT2_SUPER_BLOCKS_COUNT(fs->sb)
- - EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb),
- EXT2_SUPER_BLOCKS_PER_GROUP(fs->sb));
- fs->gdblocks = ped_div_round_up (fs->numgroups
- * sizeof(struct ext2_group_desc),
- fs->blocksize);
- fs->inodeblocks = ped_div_round_up (EXT2_SUPER_INODES_PER_GROUP(fs->sb)
- * sizeof(struct ext2_inode),
- fs->blocksize);
- fs->r_frac = ped_div_round_up (100 * (loff_t)EXT2_SUPER_R_BLOCKS_COUNT(fs->sb),
- EXT2_SUPER_BLOCKS_COUNT(fs->sb));
- fs->adminblocks = 3 + fs->gdblocks + fs->inodeblocks;
-
- fs->sparse = 0;
- if (EXT2_SUPER_FEATURE_RO_COMPAT(fs->sb)
- & EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER)
- fs->sparse = 1;
-
- fs->has_journal = 0 < (EXT2_SUPER_FEATURE_COMPAT(fs->sb)
- & EXT3_FEATURE_COMPAT_HAS_JOURNAL);
- fs->has_internal_journal
- = fs->has_journal
- && uuid_is_null(EXT2_SUPER_JOURNAL_UUID(fs->sb))
- && EXT2_SUPER_JOURNAL_INUM(fs->sb);
-
- fs->gd = ped_malloc (fs->numgroups * sizeof (struct ext2_group_desc)
- + fs->blocksize);
- if (!fs->gd)
- goto error_deinit_bcache;
-
- ext2_read_blocks(fs, fs->gd, EXT2_SUPER_FIRST_DATA_BLOCK(fs->sb) + 1,
- fs->gdblocks);
-
- fs->metadirty = 0;
- return fs;
-
- ped_free(fs->gd);
-error_deinit_bcache:
- ext2_bcache_deinit(fs);
-error_free_fs:
- ped_free(fs);
-error:
- return NULL;
-}
-
-#endif /* !DISCOVER_ONLY */