13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * openfs.c --- open an ext2 filesystem 3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996 Theodore Ts'o. 5efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %Begin-Header% 7543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * This file may be redistributed under the terms of the GNU Library 8543547a52a20cb7e69d74921b2f691078fd55d83Theodore Ts'o * General Public License, version 2. 919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h> 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h> 1450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#if HAVE_UNISTD_H 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h> 1650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h> 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <time.h> 191d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_STAT_H 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h> 211d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 221d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#if HAVE_SYS_TYPES_H 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/types.h> 241d2ff46ae7533ffd038534b189f272d2a4122e4eTheodore Ts'o#endif 25e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef HAVE_ERRNO_H 26e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <errno.h> 27e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 29b5abe6fac9c9e7caf4710501d1657d30e4857ef6Theodore Ts'o#include "ext2_fs.h" 30c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o 31c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "ext2fs.h" 33a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o#include "e2image.h" 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 35e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs, blk64_t group_block, 36e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t i) 37c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o{ 38c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o int bg; 39c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o int has_super = 0; 40e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t ret_blk; 41c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o 42c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o if (!(fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) || 43c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o (i < fs->super->s_first_meta_bg)) 44c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o return (group_block + i + 1); 45c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o 46f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement bg = EXT2_DESC_PER_BLOCK(fs->super) * i; 47c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o if (ext2fs_bg_has_super(fs, bg)) 48c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o has_super = 1; 49e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ret_blk = ext2fs_group_first_block2(fs, bg) + has_super; 509ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o /* 519ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * If group_block is not the normal value, we're trying to use 529ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * the backup group descriptors and superblock --- so use the 539ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * alternate location of the second block group in the 549ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * metablock group. Ideally we should be testing each bg 559ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * descriptor block individually for correctness, but we don't 569ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o * have the infrastructure in place to do that. 579ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o */ 589ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o if (group_block != fs->super->s_first_data_block && 599ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o ((ret_blk + fs->super->s_blocks_per_group) < 60e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_blocks_count(fs->super))) 619ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o ret_blk += fs->super->s_blocks_per_group; 629ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o return ret_blk; 63c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o} 64c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o 65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block, dgrp_t i) 66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{ 67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return ext2fs_descriptor_block_loc2(fs, group_block, i); 68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall} 69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 702e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'oerrcode_t ext2fs_open(const char *name, int flags, int superblock, 71efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o unsigned int block_size, io_manager manager, 722e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o ext2_filsys *ret_fs) 732e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o{ 74efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o return ext2fs_open2(name, 0, flags, superblock, block_size, 752e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o manager, ret_fs); 762e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o} 772e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Note: if superblock is non-zero, block-size must also be non-zero. 803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Superblock and block_size can be zero to use the default size. 8119c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * 8219c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Valid flags for ext2fs_open() 83efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 8419c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * EXT2_FLAG_RW - Open the filesystem for read/write. 8519c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * EXT2_FLAG_FORCE - Open the filesystem even if some of the 86a777397e228243cdc35056b14956db7280b0844cTheodore Ts'o * features aren't supported. 87a777397e228243cdc35056b14956db7280b0844cTheodore Ts'o * EXT2_FLAG_JOURNAL_DEV_OK - Open an ext3 journal device 88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * EXT2_FLAG_SKIP_MMP - Open without multi-mount protection check. 89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * EXT2_FLAG_64BITS - Allow 64-bit bitfields (needed for large 90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * filesystems) 913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 922e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'oerrcode_t ext2fs_open2(const char *name, const char *io_options, 932e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o int flags, int superblock, 94efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o unsigned int block_size, io_manager manager, 952e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o ext2_filsys *ret_fs) 963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2_filsys fs; 983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 998203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o unsigned long i, first_meta_bg; 100cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o __u32 features; 101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int blocks_per_group, io_flags; 102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk64_t group_block, blk; 1032e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o char *dest, *cp; 1042d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o#ifdef WORDS_BIGENDIAN 105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall unsigned int groups_per_block; 10650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o struct ext2_group_desc *gdp; 1072d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o int j; 1082d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o#endif 109efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o EXT2_CHECK_MAGIC(manager, EXT2_ET_MAGIC_IO_MANAGER); 1117b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o 112c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct struct_ext2_filsys), &fs); 1137b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1147b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o return retval; 115efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(fs, 0, sizeof(struct struct_ext2_filsys)); 117f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o fs->magic = EXT2_ET_MAGIC_EXT2FS_FILSYS; 1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->flags = flags; 119058ad1c70c9a097d282270c6f76d3c3493e15fe2Theodore Ts'o /* don't overwrite sb backups unless flag is explicitly cleared */ 120058ad1c70c9a097d282270c6f76d3c3493e15fe2Theodore Ts'o fs->flags |= EXT2_FLAG_MASTER_SB_ONLY; 1216a525069a99787ef3ae1156f12230044b3568f4bTheodore Ts'o fs->umask = 022; 1222e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o retval = ext2fs_get_mem(strlen(name)+1, &fs->device_name); 1232e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o if (retval) 1242e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o goto cleanup; 1252e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o strcpy(fs->device_name, name); 1262e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o cp = strchr(fs->device_name, '?'); 1272e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o if (!io_options && cp) { 1282e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o *cp++ = 0; 1292e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o io_options = cp; 1302e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o } 131efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 13239c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o io_flags = 0; 13339c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o if (flags & EXT2_FLAG_RW) 13439c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o io_flags |= IO_FLAG_RW; 13539c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o if (flags & EXT2_FLAG_EXCLUSIVE) 13639c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o io_flags |= IO_FLAG_EXCLUSIVE; 1377f1a1fbf850f6b73b5c9c82365f01029fb250a1cTheodore Ts'o if (flags & EXT2_FLAG_DIRECT_IO) 1387f1a1fbf850f6b73b5c9c82365f01029fb250a1cTheodore Ts'o io_flags |= IO_FLAG_DIRECT_IO; 13939c47ce6417b81aa74596fd0d4d98d542525a444Theodore Ts'o retval = manager->open(fs->device_name, io_flags, &fs->io); 1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 142efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o if (io_options && 1432e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o (retval = io_channel_set_options(fs->io, io_options))) 1442e8ca9a26b0bd7dae546a3f9a98df67b043fe3beTheodore Ts'o goto cleanup; 1451ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o fs->image_io = fs->io; 146e9affb7bec8641abfc1a63abbd6009a2464ef2ddTheodore Ts'o fs->io->app_data = fs; 147e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_alloc_buf(fs->io, -SUPERBLOCK_SIZE, &fs->super); 1487b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 150a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o if (flags & EXT2_FLAG_IMAGE_FILE) { 151a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o retval = ext2fs_get_mem(sizeof(struct ext2_image_hdr), 152c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &fs->image_header); 153a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o if (retval) 154a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o goto cleanup; 155a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o retval = io_channel_read_blk(fs->io, 0, 15685f93ffdc48f19bed280931b00e41039ee696637Theodore Ts'o -(int)sizeof(struct ext2_image_hdr), 157a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o fs->image_header); 158a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o if (retval) 159a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o goto cleanup; 160a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o if (fs->image_header->magic_number != EXT2_ET_MAGIC_E2IMAGE) 161a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o return EXT2_ET_MAGIC_E2IMAGE; 162a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o superblock = 1; 163a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o block_size = fs->image_header->fs_blocksize; 164a78926effb15bbabb1c0ed3e438b03be25c4d48cTheodore Ts'o } 1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If the user specifies a specific block # for the 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * superblock, then he/she must also specify the block size! 1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Otherwise, read the master superblock located at offset 1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * SUPERBLOCK_OFFSET from the start of the partition. 171c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * 172c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * Note: we only save a backup copy of the superblock if we 173c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o * are reading the superblock from the primary superblock location. 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (superblock) { 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!block_size) { 1771f0b6c1f895d189fea6999d0c07a7fee936a4baaTheodore Ts'o retval = EXT2_ET_INVALID_ARGUMENT; 1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel_set_blksize(fs->io, block_size); 1819ed06a1eb90efbc3290c1b5a56e0e09d243f95daTheodore Ts'o group_block = superblock; 182c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o fs->orig_super = 0; 1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else { 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel_set_blksize(fs->io, SUPERBLOCK_OFFSET); 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o superblock = 1; 186f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o group_block = 0; 187c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o retval = ext2fs_get_mem(SUPERBLOCK_SIZE, &fs->orig_super); 188c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (retval) 189c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o goto cleanup; 1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = io_channel_read_blk(fs->io, superblock, -SUPERBLOCK_SIZE, 1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fs->super); 1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 195c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o if (fs->orig_super) 196c180ac86533bcbfb1560bd4aa01464785a760f70Theodore Ts'o memcpy(fs->orig_super, fs->super, SUPERBLOCK_SIZE); 19750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o 198126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 199126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o fs->flags |= EXT2_FLAG_SWAP_BYTES; 200126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o ext2fs_swap_super(fs->super); 201126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#else 202126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o if (fs->flags & EXT2_FLAG_SWAP_BYTES) { 203126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o retval = EXT2_ET_UNIMPLEMENTED; 204126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o goto cleanup; 20550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o } 2065df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 207efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (fs->super->s_magic != EXT2_SUPER_MAGIC) { 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_BAD_MAGIC; 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 212f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (fs->super->s_rev_level > EXT2_LIB_CURRENT_REV) { 213f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o retval = EXT2_ET_REV_TOO_HIGH; 214f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o goto cleanup; 215f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o } 216e5b38a5fafe4807b54d90a2e70bddf4b41b1695bTheodore Ts'o 21719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o /* 21819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o * Check for feature set incompatibility 21919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o */ 22019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if (!(flags & EXT2_FLAG_FORCE)) { 221cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o features = fs->super->s_feature_incompat; 222cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o#ifdef EXT2_LIB_SOFTSUPP_INCOMPAT 223cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o if (flags & EXT2_FLAG_SOFTSUPP_FEATURES) 224e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall features &= ~EXT2_LIB_SOFTSUPP_INCOMPAT; 225cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o#endif 226cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o if (features & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP) { 22719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o retval = EXT2_ET_UNSUPP_FEATURE; 22819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto cleanup; 22919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 230cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o 231cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o features = fs->super->s_feature_ro_compat; 232cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o#ifdef EXT2_LIB_SOFTSUPP_RO_COMPAT 233cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o if (flags & EXT2_FLAG_SOFTSUPP_FEATURES) 234e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall features &= ~EXT2_LIB_SOFTSUPP_RO_COMPAT; 235cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o#endif 23619c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o if ((flags & EXT2_FLAG_RW) && 237cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o (features & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP)) { 23819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o retval = EXT2_ET_RO_UNSUPP_FEATURE; 23919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o goto cleanup; 24019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 241cf8272e1081f69d898d5182ed516e28807135deaTheodore Ts'o 242a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o if (!(flags & EXT2_FLAG_JOURNAL_DEV_OK) && 243a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o (fs->super->s_feature_incompat & 244a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) { 245a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o retval = EXT2_ET_UNSUPP_FEATURE; 246a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o goto cleanup; 247a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o } 24819c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o } 249efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 25049b4670e5c794f3c0f6f5df61dfa199d6cc7de65Manish Katiyar if ((fs->super->s_log_block_size + EXT2_MIN_BLOCK_LOG_SIZE) > 25149b4670e5c794f3c0f6f5df61dfa199d6cc7de65Manish Katiyar EXT2_MAX_BLOCK_LOG_SIZE) { 2521e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o retval = EXT2_ET_CORRUPT_SUPERBLOCK; 2531e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o goto cleanup; 2541e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o } 255e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 256e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* 257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * bigalloc requires cluster-aware bitfield operations, which at the 258e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * moment means we need EXT2_FLAG_64BITS. 259e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall */ 260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 261e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_BIGALLOC) && 262e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(flags & EXT2_FLAG_64BITS)) { 263e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = EXT2_ET_CANT_USE_LEGACY_BITMAPS; 264e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 265e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 266e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 267e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT4_FEATURE_RO_COMPAT_BIGALLOC) && 269e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (fs->super->s_log_block_size != fs->super->s_log_cluster_size)) { 270e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = EXT2_ET_CORRUPT_SUPERBLOCK; 271e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 272e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 273e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->fragsize = fs->blocksize = EXT2_BLOCK_SIZE(fs->super); 274ba9d929d914654f8dba36c634bb537ecf0f0bb04Theodore Ts'o if (EXT2_INODE_SIZE(fs->super) < EXT2_GOOD_OLD_INODE_SIZE) { 275ba9d929d914654f8dba36c634bb537ecf0f0bb04Theodore Ts'o retval = EXT2_ET_CORRUPT_SUPERBLOCK; 276ba9d929d914654f8dba36c634bb537ecf0f0bb04Theodore Ts'o goto cleanup; 277ba9d929d914654f8dba36c634bb537ecf0f0bb04Theodore Ts'o } 278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->cluster_ratio_bits = fs->super->s_log_cluster_size - 279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_log_block_size; 280e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (EXT2_BLOCKS_PER_GROUP(fs->super) != 281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall EXT2_CLUSTERS_PER_GROUP(fs->super) << fs->cluster_ratio_bits) { 282e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = EXT2_ET_CORRUPT_SUPERBLOCK; 283e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 284e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 28579a9ab145467b95b96a885e6ac0b2cdd22cde516Thiemo Nagel fs->inode_blocks_per_group = ((EXT2_INODES_PER_GROUP(fs->super) * 2867f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o EXT2_INODE_SIZE(fs->super) + 2877f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o EXT2_BLOCK_SIZE(fs->super) - 1) / 2887f88b04341d88c5df0360d930832c38040303b61Theodore Ts'o EXT2_BLOCK_SIZE(fs->super)); 2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (block_size) { 2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (block_size != fs->blocksize) { 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = EXT2_ET_UNEXPECTED_BLOCK_SIZE; 2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Set the blocksize to the filesystem's blocksize. 2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o io_channel_set_blksize(fs->io, fs->blocksize); 299a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o 300a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o /* 301a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o * If this is an external journal device, don't try to read 302a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o * the group descriptors, because they're not there. 303a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o */ 304a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o if (fs->super->s_feature_incompat & 305a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { 306a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o fs->group_desc_count = 0; 307a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o *ret_fs = fs; 308a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o return 0; 309a112847b39386f9e7332ba5e5a0a5e54cfe301ccTheodore Ts'o } 310efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o 311341b52dfa8c2afc11d8410de9bd381b03e75c6afTheodore Ts'o if (EXT2_INODES_PER_GROUP(fs->super) == 0) { 312341b52dfa8c2afc11d8410de9bd381b03e75c6afTheodore Ts'o retval = EXT2_ET_CORRUPT_SUPERBLOCK; 313341b52dfa8c2afc11d8410de9bd381b03e75c6afTheodore Ts'o goto cleanup; 314341b52dfa8c2afc11d8410de9bd381b03e75c6afTheodore Ts'o } 315341b52dfa8c2afc11d8410de9bd381b03e75c6afTheodore Ts'o 3163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Read group descriptors 3183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 319b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger blocks_per_group = EXT2_BLOCKS_PER_GROUP(fs->super); 320b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger if (blocks_per_group == 0 || 321b21bf267783274683a432eea6e5c589eab94123eAndreas Dilger blocks_per_group > EXT2_MAX_BLOCKS_PER_GROUP(fs->super) || 32279a9ab145467b95b96a885e6ac0b2cdd22cde516Thiemo Nagel fs->inode_blocks_per_group > EXT2_MAX_INODES_PER_GROUP(fs->super) || 32379a9ab145467b95b96a885e6ac0b2cdd22cde516Thiemo Nagel EXT2_DESC_PER_BLOCK(fs->super) == 0 || 324e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_first_data_block >= ext2fs_blocks_count(fs->super)) { 325f0687a5e5724abf576c106e07363f2e437cc9883Theodore Ts'o retval = EXT2_ET_CORRUPT_SUPERBLOCK; 326f0687a5e5724abf576c106e07363f2e437cc9883Theodore Ts'o goto cleanup; 327f0687a5e5724abf576c106e07363f2e437cc9883Theodore Ts'o } 328e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->group_desc_count = ext2fs_div64_ceil(ext2fs_blocks_count(fs->super) - 329e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_first_data_block, 330e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blocks_per_group); 331e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->group_desc_count * EXT2_INODES_PER_GROUP(fs->super) != 332e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->super->s_inodes_count) { 333e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = EXT2_ET_CORRUPT_SUPERBLOCK; 33479a9ab145467b95b96a885e6ac0b2cdd22cde516Thiemo Nagel goto cleanup; 335e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 33669022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o fs->desc_blocks = ext2fs_div_ceil(fs->group_desc_count, 33769022e029f3273b3b860bf701219cd3fe615f76bTheodore Ts'o EXT2_DESC_PER_BLOCK(fs->super)); 338ee01079a17bfecd17292ccd60058056fb3a8ba6cTheodore Ts'o retval = ext2fs_get_array(fs->desc_blocks, fs->blocksize, 339c4e3d3f374b409500e3dd05c0b0eca6ac98a6b4eTheodore Ts'o &fs->group_desc); 3407b4e4534f9361b21d3fafdd88a58f133decee38cTheodore Ts'o if (retval) 3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 342f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o if (!group_block) 343c046ac7f2e4c53e20cf1e909bbe511f91074b396Theodore Ts'o group_block = fs->super->s_first_data_block; 344e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (group_block == 0 && fs->blocksize == 1024) 345e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall group_block = 1; /* Deal with 1024 blocksize && bigalloc */ 3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dest = (char *) fs->group_desc; 347e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef WORDS_BIGENDIAN 348f2de1d38d0819b17895977fabc52d81d0ea6ec00Valerie Clement groups_per_block = EXT2_DESC_PER_BLOCK(fs->super); 349e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif 3508203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_META_BG) 3518203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o first_meta_bg = fs->super->s_first_meta_bg; 3528203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o else 3538203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o first_meta_bg = fs->desc_blocks; 3548203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o if (first_meta_bg) { 3558203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o retval = io_channel_read_blk(fs->io, group_block+1, 3568203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o first_meta_bg, dest); 3578203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o if (retval) 3588203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o goto cleanup; 3598203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o#ifdef WORDS_BIGENDIAN 3608203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o gdp = (struct ext2_group_desc *) dest; 361e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j=0; j < groups_per_block*first_meta_bg; j++) { 362e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall gdp = ext2fs_group_desc(fs, fs->group_desc, j); 363e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_swap_group_desc2(fs, gdp); 364e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 3658203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o#endif 3668203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o dest += fs->blocksize*first_meta_bg; 3678203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o } 3688203fe506a06524587c18940b6cd19a0592a4bd2Theodore Ts'o for (i=first_meta_bg ; i < fs->desc_blocks; i++) { 369e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall blk = ext2fs_descriptor_block_loc2(fs, group_block, i); 370e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = io_channel_read_blk64(fs->io, blk, 1, dest); 3713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o goto cleanup; 373126a291c768b523bc228b276d3bea82675a86d09Theodore Ts'o#ifdef WORDS_BIGENDIAN 374e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (j=0; j < groups_per_block; j++) { 375e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall gdp = ext2fs_group_desc(fs, fs->group_desc, 376e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall i * groups_per_block + j); 377e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_swap_group_desc2(fs, gdp); 378e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 3795df55d7f847e29d23227592a0bb23daad1a61500Theodore Ts'o#endif 3803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dest += fs->blocksize; 3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 38396c6a3acd377698cb99ffd9925bec9b20ca4f6f9Theodore Ts'o fs->stride = fs->super->s_raid_stride; 38496c6a3acd377698cb99ffd9925bec9b20ca4f6f9Theodore Ts'o 385d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos /* 386d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos * If recovery is from backup superblock, Clear _UNININT flags & 387d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos * reset bg_itable_unused to zero 388d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos */ 389d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos if (superblock > 1 && EXT2_HAS_RO_COMPAT_FEATURE(fs->super, 390d4f34d41be97e23db07d5ed606fcc1a26f5a3c76Jose R. Santos EXT4_FEATURE_RO_COMPAT_GDT_CSUM)) { 391e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall dgrp_t group; 392e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 393e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall for (group = 0; group < fs->group_desc_count; group++) { 394e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_clear(fs, group, EXT2_BG_BLOCK_UNINIT); 395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_flags_clear(fs, group, EXT2_BG_INODE_UNINIT); 396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_bg_itable_unused_set(fs, group, 0); 397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall /* The checksum will be reset later, but fix it here 398e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall * anyway to avoid printing a lot of spurious errors. */ 399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_group_desc_csum_set(fs, group); 400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->flags & EXT2_FLAG_RW) 402e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mark_super_dirty(fs); 403e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall } 404e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 405e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) && 406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall !(flags & EXT2_FLAG_SKIP_MMP) && 407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall (flags & (EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE))) { 408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall retval = ext2fs_mmp_start(fs); 409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (retval) { 410e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->flags |= EXT2_FLAG_SKIP_MMP; /* just do cleanup */ 411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall ext2fs_mmp_stop(fs); 412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall goto cleanup; 4130f5eba7501f467f757792ee449d16c9259b994fdAndreas Dilger } 4140f5eba7501f467f757792ee449d16c9259b994fdAndreas Dilger } 4150f5eba7501f467f757792ee449d16c9259b994fdAndreas Dilger 416f0257d8891c602cabc7358a5ca826444a172ccf5Theodore Ts'o fs->flags &= ~EXT2_FLAG_NOFREE_ON_ERROR; 417f0257d8891c602cabc7358a5ca826444a172ccf5Theodore Ts'o *ret_fs = fs; 418e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 4193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ocleanup: 421ab52e12a904b4a31fc3416f0ef7d959f0c38e773Theodore Ts'o if (flags & EXT2_FLAG_NOFREE_ON_ERROR) 422ab52e12a904b4a31fc3416f0ef7d959f0c38e773Theodore Ts'o *ret_fs = fs; 423ab52e12a904b4a31fc3416f0ef7d959f0c38e773Theodore Ts'o else 424ab52e12a904b4a31fc3416f0ef7d959f0c38e773Theodore Ts'o ext2fs_free(fs); 4253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 4263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4281ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o/* 4291ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o * Set/get the filesystem data I/O channel. 430efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o * 4311ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o * These functions are only valid if EXT2_FLAG_IMAGE_FILE is true. 4321ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o */ 4331ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'oerrcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io) 4341ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o{ 4351ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) 4361ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return EXT2_ET_NOT_IMAGE_FILE; 4371ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o if (old_io) { 4381ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o *old_io = (fs->image_io == fs->io) ? 0 : fs->io; 4391ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o } 4401ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return 0; 4411ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o} 4421ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o 4431ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'oerrcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io) 4441ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o{ 4451ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) 4461ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return EXT2_ET_NOT_IMAGE_FILE; 4471ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o fs->io = new_io ? new_io : fs->image_io; 4481ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return 0; 4491ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o} 4501ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o 4511ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'oerrcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io) 4521ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o{ 453e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall errcode_t err; 454e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall 4551ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o if ((fs->flags & EXT2_FLAG_IMAGE_FILE) == 0) 4561ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return EXT2_ET_NOT_IMAGE_FILE; 457e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall err = io_channel_set_blksize(new_io, fs->blocksize); 458e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (err) 459e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return err; 460e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((new_io == fs->image_io) || (new_io == fs->io)) 461e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall return 0; 462e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if ((fs->image_io != fs->io) && 463e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall fs->image_io) 464e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall io_channel_close(fs->image_io); 465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall if (fs->io) 466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall io_channel_close(fs->io); 4671ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o fs->io = fs->image_io = new_io; 468efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o fs->flags |= EXT2_FLAG_DIRTY | EXT2_FLAG_RW | 4691ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY; 4701ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o fs->flags &= ~EXT2_FLAG_IMAGE_FILE; 4711ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o return 0; 4721ad54a940c499a66241f624882f1ffa03ce56d90Theodore Ts'o} 473