Support for 64KB blocksize in e2fsprogs
PATCH 1/1 Support for 64KB blocksize in e2fsprogs
Hi,
attached patch implements support for 64KB blocksize in directories in
e2fsprogs. This patch complements the kernel patches for ext2-4 I've sent yesterday. Ted, does the patch look fine?
Honza
Signature · 12 lines
Jan Kara <[email protected]> SUSE Labs, CR ----- Subject: Support for 64KB blocksize in ext2-4 directories. When block size is 64KB, we have to take care that rec_len does not overflow. Kernel stores 0xffff in case 0x10000 should be stored - perform appropriate conversion when reading from / writing to disk. Signed-off-by: Jan Kara <[email protected]>
lib/ext2fs/dirblock.c +7 -5
@@ -38,9 +38,9 @@ errcode_t ext2fs_read_dir_block2(ext2_fi dirent = (struct ext2_dir_entry *) p;#ifdef WORDS_BIGENDIAN dirent->inode =ext2fs_swab32 (dirent->inode); - dirent->rec_len =ext2fs_swab16 (dirent->rec_len); dirent->name_len =ext2fs_swab16 (dirent->name_len);#endif + dirent->rec_len =ext2fs_rec_len_from_disk (dirent->rec_len); name_len = dirent->name_len;#ifdef WORDS_BIGENDIAN if (flags &EXT2_DIRBLOCK_V2_STRUCT )
@@ -68,12 +68,15 @@ errcode_t ext2fs_read_dir_block(ext2_filerrcode_t ext2fs_write_dir_block2 (ext2_filsys fs,blk_t block, void *inbuf, int flags EXT2FS_ATTR((unused))) { -#ifdef WORDS_BIGENDIAN errcode_t retval;char *p, *end;char *buf =0 ;struct ext2_dir_entry *dirent; +#ifndef WORDS_BIGENDIAN +if (fs->blocksize <EXT2_MAX_REC_LEN ) + goto just_write; +#endif retval =ext2fs_get_mem (fs->blocksize, &buf);if (retval)return retval;
@@ -89,7 +92,7 @@ errcode_t ext2fs_write_dir_block2(ext2_f } p += dirent->rec_len; dirent->inode =ext2fs_swab32 (dirent->inode); - dirent->rec_len =ext2fs_swab16 (dirent->rec_len); + dirent->rec_len =ext2fs_rec_len_to_disk (dirent->rec_len); dirent->name_len =ext2fs_swab16 (dirent->name_len);if (flags &EXT2_DIRBLOCK_V2_STRUCT )
@@ -98,9 +101,8 @@ errcode_t ext2fs_write_dir_block2(ext2_f retval =io_channel_write_blk (fs->io, block,1 , buf);ext2fs_free_mem (&buf);return retval; -#else +just_write:return io_channel_write_blk (fs->io, block,1 , (char *) inbuf); -#endif }
lib/ext2fs/ext2_fs.h +26 -0
@@ -717,6 +717,32 @@ struct ext2_dir_entry_2 {#define EXT2_DIR_ROUND (EXT2_DIR_PAD - 1)#define EXT2_DIR_REC_LEN (name_len) (((name_len) + 8 + EXT2_DIR_ROUND) & \ ~EXT2_DIR_ROUND) +#define EXT2_MAX_REC_LEN ((1<<16)-1) + +static inline unsigned ext2fs_rec_len_from_disk (unsigned len) +{ +#ifdef WORDS_BIGENDIAN + len =ext2fs_swab16 (dlen); +#endif +if (len ==EXT2_MAX_REC_LEN ) +return 1 <<16 ; +return len; +} + +static inline unsigned ext2fs_rec_len_to_disk (unsigned len) +{ + if (len == (1 << 16)) +#ifdef WORDS_BIGENDIAN +return ext2fs_swab16 (EXT2_MAX_REC_LEN ); +#else +return EXT2_MAX_REC_LEN ; +#endif +#ifdef WORDS_BIGENDIAN +return ext2fs_swab_16 (len); +#else +return len; +#endif +}/* * This structure will be used for multiple mount protection. It will be
misc/e2image.c +2 -7
@@ -345,10 +345,7 @@ static void scramble_dir_block(ext2_fils end = buf + fs->blocksize;for (p = buf; p < end-8 ; p += rec_len) { dirent = (struct ext2_dir_entry_2 *) p; - rec_len = dirent->rec_len; -#ifdef WORDS_BIGENDIAN - rec_len =ext2fs_swab16 (rec_len); -#endif + rec_len =ext2fs_rec_len_from_disk (dirent->rec_len);#if 0 printf ("rec_len = %d, name_len = %d\n" , rec_len, dirent->name_len);#endif
@@ -358,9 +355,7 @@ static void scramble_dir_block(ext2_fils"bad rec_len (%d)\n" , (unsigned long ) blk, rec_len); rec_len = end - p; -#ifdef WORDS_BIGENDIAN - dirent->rec_len =ext2fs_swab16 (rec_len); -#endif + dirent->rec_len =ext2fs_rec_len_to_disk (rec_len);continue ; }if (dirent->name_len +8 > rec_len) {