__le32 magic;           /* file system magic number */
        __le32 checksum;        /* crc32c(super_block) */
        __le32 feature_compat;
-       __u8 blkszbits;         /* support block_size == PAGE_SIZE only */
+       __u8 blkszbits;         /* filesystem block size in bit shift */
        __u8 sb_extslots;       /* superblock size = 128 + sb_extslots * 16 */
 
        __le16 root_nid;        /* nid of root directory */
        } __packed u1;
        __le16 extra_devices;   /* # of devices besides the primary device */
        __le16 devt_slotoff;    /* startoff = devt_slotoff * devt_slotsize */
-       __u8 reserved[6];
+       __u8 dirblkbits;        /* directory block size in bit shift */
+       __u8 reserved[5];
        __le64 packed_nid;      /* nid of the special packed inode */
        __u8 reserved2[24];
 };
 
        u16 device_id_mask;     /* valid bits of device id to be used */
 
        unsigned char islotbits;        /* inode slot unit size in bit shift */
-       unsigned char blkszbits;
+       unsigned char blkszbits;        /* filesystem block size in bit shift */
 
        u32 sb_size;                    /* total superblock size */
        u32 build_time_nsec;
                                        VAL != EROFS_LOCKED_MAGIC);
 }
 
-/* we strictly follow PAGE_SIZE and no buffer head yet */
-#define LOG_BLOCK_SIZE         PAGE_SHIFT
-#define EROFS_BLKSIZ           (1 << LOG_BLOCK_SIZE)
-
-#if (EROFS_BLKSIZ % 4096 || !EROFS_BLKSIZ)
-#error erofs cannot be used in this platform
-#endif
-
 enum erofs_kmap_type {
        EROFS_NO_KMAP,          /* don't map the buffer */
        EROFS_KMAP,             /* use kmap_local_page() to map the buffer */
 
        struct erofs_sb_info *sbi;
        struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
        struct erofs_super_block *dsb;
-       unsigned int blkszbits;
        void *data;
        int ret;
 
                goto out;
        }
 
+       sbi->blkszbits  = dsb->blkszbits;
+       if (sbi->blkszbits < 9 || sbi->blkszbits > PAGE_SHIFT) {
+               erofs_err(sb, "blkszbits %u isn't supported", sbi->blkszbits);
+               goto out;
+       }
+       if (dsb->dirblkbits) {
+               erofs_err(sb, "dirblkbits %u isn't supported", dsb->dirblkbits);
+               goto out;
+       }
+
        sbi->feature_compat = le32_to_cpu(dsb->feature_compat);
        if (erofs_sb_has_sb_chksum(sbi)) {
                ret = erofs_superblock_csum_verify(sb, data);
        }
 
        ret = -EINVAL;
-       blkszbits = dsb->blkszbits;
-       /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */
-       if (blkszbits != LOG_BLOCK_SIZE) {
-               erofs_err(sb, "blkszbits %u isn't supported on this platform",
-                         blkszbits);
-               goto out;
-       }
-
        if (!check_layout_compatibility(sb, dsb))
                goto out;
 
        sbi->sb_size = 128 + dsb->sb_extslots * EROFS_SB_EXTSLOT_SIZE;
-       if (sbi->sb_size > EROFS_BLKSIZ) {
+       if (sbi->sb_size > PAGE_SIZE - EROFS_SUPER_OFFSET) {
                erofs_err(sb, "invalid sb_extslots %u (more than a fs block)",
                          sbi->sb_size);
                goto out;
 
        sbi->blkszbits = PAGE_SHIFT;
        if (erofs_is_fscache_mode(sb)) {
-               sb->s_blocksize = EROFS_BLKSIZ;
-               sb->s_blocksize_bits = LOG_BLOCK_SIZE;
+               sb->s_blocksize = PAGE_SIZE;
+               sb->s_blocksize_bits = PAGE_SHIFT;
 
                err = erofs_fscache_register_fs(sb);
                if (err)
                if (err)
                        return err;
        } else {
-               if (!sb_set_blocksize(sb, EROFS_BLKSIZ)) {
-                       erofs_err(sb, "failed to set erofs blksize");
+               if (!sb_set_blocksize(sb, PAGE_SIZE)) {
+                       errorfc(fc, "failed to set initial blksize");
                        return -EINVAL;
                }
 
        if (err)
                return err;
 
-       if (test_opt(&sbi->opt, DAX_ALWAYS)) {
-               BUILD_BUG_ON(EROFS_BLKSIZ != PAGE_SIZE);
+       if (sb->s_blocksize_bits != sbi->blkszbits) {
+               if (erofs_is_fscache_mode(sb)) {
+                       errorfc(fc, "unsupported blksize for fscache mode");
+                       return -EINVAL;
+               }
+               if (!sb_set_blocksize(sb, 1 << sbi->blkszbits)) {
+                       errorfc(fc, "failed to set erofs blksize");
+                       return -EINVAL;
+               }
+       }
 
+       if (test_opt(&sbi->opt, DAX_ALWAYS)) {
                if (!sbi->dax_dev) {
                        errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
                        clear_opt(&sbi->opt, DAX_ALWAYS);
+               } else if (sbi->blkszbits != PAGE_SHIFT) {
+                       errorfc(fc, "unsupported blocksize for DAX");
+                       clear_opt(&sbi->opt, DAX_ALWAYS);
                }
        }