summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Cross <ccross@android.com>2013-02-04 00:44:55 -0800
committerColin Cross <ccross@android.com>2013-02-04 15:33:50 -0800
commit56497f28bd20001dd5f931208e8d948cf2f81b2f (patch)
tree00a35e7640dd9b44d6a63fc86633ae7eb8d05cec
parent682a27cbce4935a6598c42a248855eb5878c1115 (diff)
downloadextras-56497f28bd20001dd5f931208e8d948cf2f81b2f.tar.gz
ext4_utils: mark uninitialized inode tables in block groups
Block groups that have no used inodes have their inode table left uninitialized, unless -t is specified, in which case they are explicitly zeroed. When they are uninitialized, writing a sparse ext4 image over existing data can cause e2fsck to confuse the uninitialized data for lost inodes. Set the EXT4_BG_INODE_UNINIT flags on block groups that have no used inodes. This flag requires the block group checksum feature to be enabled, so also enable the checksum feature in the superblock and compute the checksum for the block group. Since zeroing the inode tables is now useless, remove the code for it and deprecate the -t command line option. Change-Id: I4927c1d866d051547cf0dadc8c8703ded0163925
-rw-r--r--ext4_utils/Android.mk3
-rw-r--r--ext4_utils/allocate.c26
-rw-r--r--ext4_utils/allocate.h1
-rw-r--r--ext4_utils/crc16.c58
-rw-r--r--ext4_utils/ext4_utils.c11
-rw-r--r--ext4_utils/ext4_utils.h9
-rw-r--r--ext4_utils/make_ext4fs.c12
-rw-r--r--ext4_utils/make_ext4fs_main.c7
8 files changed, 94 insertions, 33 deletions
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk
index 1fef7353..6eba3b17 100644
--- a/ext4_utils/Android.mk
+++ b/ext4_utils/Android.mk
@@ -12,7 +12,8 @@ libext4_utils_src_files := \
indirect.c \
uuid.c \
sha1.c \
- wipe.c
+ wipe.c \
+ crc16.c
#
# -- All host/targets including windows
diff --git a/ext4_utils/allocate.c b/ext4_utils/allocate.c
index adf91baf..3229abe0 100644
--- a/ext4_utils/allocate.c
+++ b/ext4_utils/allocate.c
@@ -56,6 +56,7 @@ struct block_group_info {
u32 first_free_block;
u32 free_inodes;
u32 first_free_inode;
+ u16 flags;
u16 used_dirs;
};
@@ -157,24 +158,8 @@ static void allocate_bg_inode_table(struct block_group_info *bg)
sparse_file_add_data(info.sparse_file, bg->inode_table,
aux_info.inode_table_blocks * info.block_size, block);
-}
-
-void init_unused_inode_tables(void)
-{
- unsigned int i;
- u32 block;
- struct block_group_info *bg;
- for (i = 0; i < aux_info.groups; i++) {
- if (!aux_info.bgs[i].inode_table) {
- bg = &aux_info.bgs[i];
- block = bg->first_block + 2;
- if (bg->has_superblock)
- block += aux_info.bg_desc_blocks + info.bg_desc_reserve_blocks + 1;
- sparse_file_add_fill(info.sparse_file, 0,
- aux_info.inode_table_blocks * info.block_size, block);
- }
- }
+ bg->flags &= ~EXT4_BG_INODE_UNINIT;
}
static int bitmap_set_bit(u8 *bitmap, u32 bit)
@@ -297,6 +282,7 @@ static void init_bg(struct block_group_info *bg, unsigned int i)
bg->first_free_block = 0;
bg->free_inodes = info.inodes_per_group;
bg->first_free_inode = 1;
+ bg->flags = EXT4_BG_INODE_UNINIT;
if (reserve_blocks(bg, bg->first_free_block, bg->header_blocks) < 0)
error("failed to reserve %u blocks in block group %u\n", bg->header_blocks, i);
@@ -744,6 +730,12 @@ u16 get_directories(int bg)
return aux_info.bgs[bg].used_dirs;
}
+/* Returns the flags for a block group */
+u16 get_bg_flags(int bg)
+{
+ return aux_info.bgs[bg].flags;
+}
+
/* Frees the memory used by a linked list of allocation regions */
void free_alloc(struct block_allocation *alloc)
{
diff --git a/ext4_utils/allocate.h b/ext4_utils/allocate.h
index fb6e0f75..0575e846 100644
--- a/ext4_utils/allocate.h
+++ b/ext4_utils/allocate.h
@@ -41,6 +41,7 @@ u32 get_free_inodes(u32 bg);
u32 reserve_inodes(int bg, u32 inodes);
void add_directory(u32 inode);
u16 get_directories(int bg);
+u16 get_bg_flags(int bg);
void init_unused_inode_tables(void);
u32 allocate_inode();
void free_alloc(struct block_allocation *alloc);
diff --git a/ext4_utils/crc16.c b/ext4_utils/crc16.c
new file mode 100644
index 00000000..25758121
--- /dev/null
+++ b/ext4_utils/crc16.c
@@ -0,0 +1,58 @@
+/*-
+ * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
+ * code or tables extracted from it, as desired without restriction.
+ */
+
+/* CRC32 code derived from work by Gary S. Brown. */
+
+/* Code taken from FreeBSD 8 */
+
+/* Converted to crc16 */
+
+#include "ext4_utils.h"
+
+static u16 crc16_tab[] = {
+ 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
+ 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
+ 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
+ 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
+ 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
+ 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
+ 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
+ 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
+ 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
+ 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
+ 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
+ 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
+ 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
+ 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
+ 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
+ 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
+ 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
+ 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
+ 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
+ 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
+ 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
+ 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
+ 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
+ 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
+ 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
+ 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
+ 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
+ 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
+ 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
+ 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
+ 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
+ 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,
+};
+
+u16 ext4_crc16(u16 crc_in, const void *buf, int size)
+{
+ const u8 *p = buf;
+ u16 crc = crc_in;
+
+ while (size--)
+ crc = crc16_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
+
+ return crc;
+}
diff --git a/ext4_utils/ext4_utils.c b/ext4_utils/ext4_utils.c
index 43b44806..4b87c6e4 100644
--- a/ext4_utils/ext4_utils.c
+++ b/ext4_utils/ext4_utils.c
@@ -25,6 +25,7 @@
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <stddef.h>
#include <string.h>
#ifdef USE_MINGW
@@ -362,11 +363,12 @@ void ext4_create_journal_inode()
block group */
void ext4_update_free()
{
- unsigned int i;
+ u32 i;
for (i = 0; i < aux_info.groups; i++) {
u32 bg_free_blocks = get_free_blocks(i);
u32 bg_free_inodes = get_free_inodes(i);
+ u16 crc;
aux_info.bg_desc[i].bg_free_blocks_count = bg_free_blocks;
aux_info.sb->s_free_blocks_count_lo += bg_free_blocks;
@@ -375,6 +377,13 @@ void ext4_update_free()
aux_info.sb->s_free_inodes_count += bg_free_inodes;
aux_info.bg_desc[i].bg_used_dirs_count += get_directories(i);
+
+ aux_info.bg_desc[i].bg_flags = get_bg_flags(i);
+
+ crc = ext4_crc16(~0, aux_info.sb->s_uuid, sizeof(aux_info.sb->s_uuid));
+ crc = ext4_crc16(crc, &i, sizeof(i));
+ crc = ext4_crc16(crc, &aux_info.bg_desc[i], offsetof(struct ext2_group_desc, bg_checksum));
+ aux_info.bg_desc[i].bg_checksum = crc;
}
}
diff --git a/ext4_utils/ext4_utils.h b/ext4_utils/ext4_utils.h
index 26952c0d..0d0b6bc9 100644
--- a/ext4_utils/ext4_utils.h
+++ b/ext4_utils/ext4_utils.h
@@ -99,8 +99,10 @@ struct ext2_group_desc {
__le16 bg_free_blocks_count;
__le16 bg_free_inodes_count;
__le16 bg_used_dirs_count;
- __le16 bg_pad;
- __le32 bg_reserved[3];
+ __le16 bg_flags;
+ __le32 bg_reserved[2];
+ __le16 bg_reserved16;
+ __le16 bg_checksum;
};
struct fs_info {
@@ -166,6 +168,7 @@ void ext4_queue_sb(void);
u64 get_file_size(int fd);
u64 parse_num(const char *arg);
void ext4_parse_sb(struct ext4_super_block *sb);
+u16 ext4_crc16(u16 crc_in, const void *buf, int size);
typedef void (*fs_config_func_t)(const char *path, int dir, unsigned *uid, unsigned *gid,
unsigned *mode);
@@ -174,7 +177,7 @@ struct selabel_handle;
int make_ext4fs_internal(int fd, const char *directory,
const char *mountpoint, fs_config_func_t fs_config_func, int gzip,
- int sparse, int crc, int wipe, int init_itabs,
+ int sparse, int crc, int wipe,
struct selabel_handle *sehnd, int verbose);
#ifdef __cplusplus
diff --git a/ext4_utils/make_ext4fs.c b/ext4_utils/make_ext4fs.c
index f62fee9f..b2d14263 100644
--- a/ext4_utils/make_ext4fs.c
+++ b/ext4_utils/make_ext4fs.c
@@ -361,7 +361,7 @@ int make_ext4fs_sparse_fd(int fd, long long len,
reset_ext4fs_info();
info.len = len;
- return make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 1, 0, 0, 0, sehnd, 0);
+ return make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 1, 0, 0, sehnd, 0);
}
int make_ext4fs(const char *filename, long long len,
@@ -379,7 +379,7 @@ int make_ext4fs(const char *filename, long long len,
return EXIT_FAILURE;
}
- status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, 0, sehnd, 0);
+ status = make_ext4fs_internal(fd, NULL, mountpoint, NULL, 0, 0, 0, 1, sehnd, 0);
close(fd);
return status;
@@ -444,7 +444,7 @@ static char *canonicalize_rel_slashes(const char *str)
int make_ext4fs_internal(int fd, const char *_directory,
const char *_mountpoint, fs_config_func_t fs_config_func, int gzip,
- int sparse, int crc, int wipe, int init_itabs,
+ int sparse, int crc, int wipe,
struct selabel_handle *sehnd, int verbose)
{
u32 root_inode_num;
@@ -507,7 +507,8 @@ int make_ext4fs_internal(int fd, const char *_directory,
info.feat_ro_compat |=
EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER |
- EXT4_FEATURE_RO_COMPAT_LARGE_FILE;
+ EXT4_FEATURE_RO_COMPAT_LARGE_FILE |
+ EXT4_FEATURE_RO_COMPAT_GDT_CSUM;
info.feat_incompat |=
EXT4_FEATURE_INCOMPAT_EXTENTS |
@@ -580,9 +581,6 @@ int make_ext4fs_internal(int fd, const char *_directory,
ext4_update_free();
- if (init_itabs)
- init_unused_inode_tables();
-
ext4_queue_sb();
printf("Created filesystem with %d/%d inodes and %d/%d blocks\n",
diff --git a/ext4_utils/make_ext4fs_main.c b/ext4_utils/make_ext4fs_main.c
index 739c4a16..b6c740d2 100644
--- a/ext4_utils/make_ext4fs_main.c
+++ b/ext4_utils/make_ext4fs_main.c
@@ -53,7 +53,7 @@ static void usage(char *path)
fprintf(stderr, " [ -g <blocks per group> ] [ -i <inodes> ] [ -I <inode size> ]\n");
fprintf(stderr, " [ -L <label> ] [ -f ] [ -a <android mountpoint> ]\n");
fprintf(stderr, " [ -S file_contexts ]\n");
- fprintf(stderr, " [ -z | -s ] [ -t ] [ -w ] [ -c ] [ -J ] [ -v ]\n");
+ fprintf(stderr, " [ -z | -s ] [ -w ] [ -c ] [ -J ] [ -v ]\n");
fprintf(stderr, " <filename> [<directory>]\n");
}
@@ -68,7 +68,6 @@ int main(int argc, char **argv)
int sparse = 0;
int crc = 0;
int wipe = 0;
- int init_itabs = 0;
int fd;
int exitcode;
int verbose = 0;
@@ -129,7 +128,7 @@ int main(int argc, char **argv)
sparse = 1;
break;
case 't':
- init_itabs = 1;
+ fprintf(stderr, "Warning: -t (initialize inode tables) is deprecated\n");
break;
case 'S':
#ifndef USE_MINGW
@@ -202,7 +201,7 @@ int main(int argc, char **argv)
}
exitcode = make_ext4fs_internal(fd, directory, mountpoint, fs_config_func, gzip,
- sparse, crc, wipe, init_itabs, sehnd, verbose);
+ sparse, crc, wipe, sehnd, verbose);
close(fd);
return exitcode;