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

-- 
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]>

diff --git a/lib/ext2fs/dirblock.c b/lib/ext2fs/dirblock.c
index fb20fa0..628bf93 100644
--- a/lib/ext2fs/dirblock.c
+++ b/lib/ext2fs/dirblock.c
@@ -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_fil
 errcode_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
 }
 
 
diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h
index a316665..2041f0f 100644
--- a/lib/ext2fs/ext2_fs.h
+++ b/lib/ext2fs/ext2_fs.h
@@ -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
diff --git a/misc/e2image.c b/misc/e2image.c
index 1fbb267..4e2c9fb 100644
--- a/misc/e2image.c
+++ b/misc/e2image.c
@@ -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) {
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to