Whamcloud - gitweb
LU-6722 jbd: double minimum journal size for RHEL7
[tools/e2fsprogs.git] / lib / ext2fs / ext2fs.h
index d3eb31d..e66d2fc 100644 (file)
@@ -37,7 +37,9 @@ extern "C" {
  * 1032 bytes long).
  */
 #define SUPERBLOCK_OFFSET      1024
-#define SUPERBLOCK_SIZE        1024
+#define SUPERBLOCK_SIZE                1024
+
+#define UUID_STR_SIZE 37
 
 /*
  * The last ext2fs revision level that this version of the library is
@@ -64,14 +66,20 @@ extern "C" {
 #include <ext2fs/ext3_extents.h>
 #endif /* EXT2_FLAT_INCLUDES */
 
-typedef __u32          ext2_ino_t;
-typedef __u32          blk_t;
-typedef __u64          blk64_t;
-typedef __u32          dgrp_t;
-typedef __u32          ext2_off_t;
-typedef __u64          ext2_off64_t;
-typedef __s64          e2_blkcnt_t;
-typedef __u32          ext2_dirhash_t;
+#ifdef __CHECK_ENDIAN__
+#define __bitwise __attribute__((bitwise))
+#else
+#define __bitwise
+#endif
+
+typedef __u32 __bitwise                ext2_ino_t;
+typedef __u32 __bitwise                blk_t;
+typedef __u64 __bitwise                blk64_t;
+typedef __u32 __bitwise                dgrp_t;
+typedef __u32 __bitwise                ext2_off_t;
+typedef __u64 __bitwise                ext2_off64_t;
+typedef __s64 __bitwise                e2_blkcnt_t;
+typedef __u32 __bitwise                ext2_dirhash_t;
 
 #if EXT2_FLAT_INCLUDES
 #include "com_err.h"
@@ -184,6 +192,7 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_FLAG_64BITS               0x20000
 #define EXT2_FLAG_PRINT_PROGRESS       0x40000
 #define EXT2_FLAG_DIRECT_IO            0x80000
+#define EXT2_FLAG_SKIP_MMP             0x100000
 
 /*
  * Special flag in the ext2 inode i_flag field that means that this is
@@ -193,10 +202,10 @@ typedef struct ext2_file *ext2_file_t;
 
 /*
  * Flags for mkjournal
- *
- * EXT2_MKJOURNAL_V1_SUPER     Make a (deprecated) V1 journal superblock
  */
-#define EXT2_MKJOURNAL_V1_SUPER        0x0000001
+#define EXT2_MKJOURNAL_V1_SUPER        0x0000001 /* create V1 superblock (deprecated) */
+#define EXT2_MKJOURNAL_LAZYINIT        0x0000002 /* don't zero journal inode before use*/
+#define EXT2_MKJOURNAL_NO_MNT_CHECK 0x0000004 /* don't check mount status */
 
 struct opaque_ext2_group_desc;
 
@@ -207,11 +216,11 @@ struct struct_ext2_filsys {
        char *                          device_name;
        struct ext2_super_block *       super;
        unsigned int                    blocksize;
-       int                             clustersize;
+       int                             fragsize;
        dgrp_t                          group_desc_count;
        unsigned long                   desc_blocks;
        struct opaque_ext2_group_desc * group_desc;
-       int                             inode_blocks_per_group;
+       unsigned int                    inode_blocks_per_group;
        ext2fs_inode_bitmap             inode_map;
        ext2fs_block_bitmap             block_map;
        /* XXX FIXME-64: not 64-bit safe, but not used? */
@@ -229,10 +238,13 @@ struct struct_ext2_filsys {
        struct ext2_image_hdr *         image_header;
        __u32                           umask;
        time_t                          now;
+       int                             cluster_ratio_bits;
+       __u16                           default_bitmap_type;
+       __u16                           pad;
        /*
         * Reserved for future expansion
         */
-       __u32                           reserved[7];
+       __u32                           reserved[5];
 
        /*
         * Reserved for the use of the calling application.
@@ -251,6 +263,18 @@ struct struct_ext2_filsys {
        errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
                                     blk64_t *ret);
        void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
+
+       /*
+        * Buffers for Multiple mount protection(MMP) block.
+        */
+       void *mmp_buf;
+       void *mmp_cmp;
+       int mmp_fd;
+
+       /*
+        * Time at which e2fsck last updated the MMP block.
+        */
+       long mmp_last_written;
 };
 
 #if EXT2_FLAT_INCLUDES
@@ -260,6 +284,13 @@ struct struct_ext2_filsys {
 #endif
 
 /*
+ * 64-bit bitmap backend types
+ */
+#define EXT2FS_BMAP64_BITARRAY 1
+#define EXT2FS_BMAP64_RBTREE   2
+#define EXT2FS_BMAP64_AUTODIR  3
+
+/*
  * Return flags for the block iterator functions
  */
 #define BLOCK_CHANGED  1
@@ -506,6 +537,12 @@ typedef struct ext2_icount *ext2_icount_t;
 #define EXT2_CHECK_MAGIC(struct, code) \
          if ((struct)->magic != (code)) return (code)
 
+/*
+ * Flags for returning status of ext2fs_expand_extra_isize()
+ */
+#define EXT2_EXPAND_EISIZE_UNSAFE      0x0001
+#define EXT2_EXPAND_EISIZE_NEW_BLOCK   0x0002
+#define EXT2_EXPAND_EISIZE_NOSPC       0x0004
 
 /*
  * For ext2 compression support
@@ -521,7 +558,8 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT3_FEATURE_COMPAT_HAS_JOURNAL|\
                                         EXT2_FEATURE_COMPAT_RESIZE_INODE|\
                                         EXT2_FEATURE_COMPAT_DIR_INDEX|\
-                                        EXT2_FEATURE_COMPAT_EXT_ATTR)
+                                        EXT2_FEATURE_COMPAT_EXT_ATTR|\
+                                        EXT4_FEATURE_COMPAT_SPARSE_SUPER2)
 
 /* This #ifdef is temporary until compression is fully supported */
 #ifdef ENABLE_COMPRESSION
@@ -538,6 +576,9 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT3_FEATURE_INCOMPAT_RECOVER|\
                                         EXT3_FEATURE_INCOMPAT_EXTENTS|\
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG|\
+                                        EXT4_FEATURE_INCOMPAT_MMP|\
+                                        EXT4_FEATURE_INCOMPAT_EA_INODE|\
+                                        EXT4_FEATURE_INCOMPAT_DIRDATA|\
                                         EXT4_FEATURE_INCOMPAT_64BIT)
 #else
 #define EXT2_LIB_FEATURE_INCOMPAT_SUPP (EXT2_FEATURE_INCOMPAT_FILETYPE|\
@@ -546,26 +587,70 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT3_FEATURE_INCOMPAT_RECOVER|\
                                         EXT3_FEATURE_INCOMPAT_EXTENTS|\
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG|\
+                                        EXT4_FEATURE_INCOMPAT_MMP|\
+                                        EXT4_FEATURE_INCOMPAT_EA_INODE|\
+                                        EXT4_FEATURE_INCOMPAT_DIRDATA|\
                                         EXT4_FEATURE_INCOMPAT_64BIT)
 #endif
+#ifdef CONFIG_QUOTA
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP        (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
                                         EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
                                         EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
                                         EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
                                         EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
-                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM)
+                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
+                                        EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
+                                        EXT4_FEATURE_RO_COMPAT_QUOTA)
+#else
+#define EXT2_LIB_FEATURE_RO_COMPAT_SUPP        (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
+                                        EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
+                                        EXT2_FEATURE_RO_COMPAT_LARGE_FILE|\
+                                        EXT4_FEATURE_RO_COMPAT_DIR_NLINK|\
+                                        EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|\
+                                        EXT4_FEATURE_RO_COMPAT_GDT_CSUM|\
+                                        EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+#endif
 
 /*
  * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
  * to ext2fs_openfs()
  */
 #define EXT2_LIB_SOFTSUPP_INCOMPAT     (0)
-#define EXT2_LIB_SOFTSUPP_RO_COMPAT    (EXT4_FEATURE_RO_COMPAT_BIGALLOC)
+#define EXT2_LIB_SOFTSUPP_RO_COMPAT    (EXT4_FEATURE_RO_COMPAT_REPLICA)
+
+
+/* Translate a block number to a cluster number */
+#define EXT2FS_CLUSTER_RATIO(fs)       (1 << (fs)->cluster_ratio_bits)
+#define EXT2FS_CLUSTER_MASK(fs)                (EXT2FS_CLUSTER_RATIO(fs) - 1)
+#define EXT2FS_B2C(fs, blk)            ((blk) >> (fs)->cluster_ratio_bits)
+/* Translate a cluster number to a block number */
+#define EXT2FS_C2B(fs, cluster)                ((cluster) << (fs)->cluster_ratio_bits)
+/* Translate # of blks to # of clusters */
+#define EXT2FS_NUM_B2C(fs, blks)       (((blks) + EXT2FS_CLUSTER_MASK(fs)) >> \
+                                        (fs)->cluster_ratio_bits)
+
+#if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
+typedef struct stat64 ext2fs_struct_stat;
+#else
+typedef struct stat ext2fs_struct_stat;
+#endif
+
+/*
+ * For ext2fs_close2() and ext2fs_flush2(), this flag allows you to
+ * avoid the fsync call.
+ */
+#define EXT2_FLAG_FLUSH_NO_SYNC          1
 
 /*
  * function prototypes
  */
 
+/* The LARGE_FILE feature should be set if we have stored files 2GB+ in size */
+static inline int ext2fs_needs_large_file_feature(unsigned long long file_size)
+{
+       return file_size >= 0x80000000ULL;
+}
+
 /* alloc.c */
 extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
                                  ext2fs_inode_bitmap map, ext2_ino_t *ret);
@@ -611,6 +696,8 @@ void ext2fs_inode_alloc_stats2(ext2_filsys fs, ext2_ino_t ino,
                               int inuse, int isdir);
 void ext2fs_block_alloc_stats(ext2_filsys fs, blk_t blk, int inuse);
 void ext2fs_block_alloc_stats2(ext2_filsys fs, blk64_t blk, int inuse);
+void ext2fs_block_alloc_stats_range(ext2_filsys fs, blk64_t blk,
+                                   blk_t num, int inuse);
 
 /* alloc_tables.c */
 extern errcode_t ext2fs_allocate_tables(ext2_filsys fs);
@@ -675,6 +762,10 @@ extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
 extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
                                              const char *descr,
                                              ext2fs_block_bitmap *ret);
+extern errcode_t ext2fs_allocate_subcluster_bitmap(ext2_filsys fs,
+                                                  const char *descr,
+                                                  ext2fs_block_bitmap *ret);
+extern int ext2fs_get_bitmap_granularity(ext2fs_block_bitmap bitmap);
 extern errcode_t ext2fs_allocate_inode_bitmap(ext2_filsys fs,
                                              const char *descr,
                                              ext2fs_inode_bitmap *ret);
@@ -731,6 +822,7 @@ extern errcode_t ext2fs_get_block_bitmap_range2(ext2fs_block_bitmap bmap,
 extern dgrp_t ext2fs_group_of_blk2(ext2_filsys fs, blk64_t);
 extern blk64_t ext2fs_group_first_block2(ext2_filsys fs, dgrp_t group);
 extern blk64_t ext2fs_group_last_block2(ext2_filsys fs, dgrp_t group);
+extern int ext2fs_group_blocks_count(ext2_filsys fs, dgrp_t group);
 extern blk64_t ext2fs_inode_data_blocks2(ext2_filsys fs,
                                         struct ext2_inode *inode);
 extern blk64_t ext2fs_inode_i_blocks(ext2_filsys fs,
@@ -782,8 +874,12 @@ extern void ext2fs_bg_flags_set(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
 extern void ext2fs_bg_flags_clear(ext2_filsys fs, dgrp_t group, __u16 bg_flags);
 extern __u16 ext2fs_bg_checksum(ext2_filsys fs, dgrp_t group);
 extern void ext2fs_bg_checksum_set(ext2_filsys fs, dgrp_t group, __u16 checksum);
-extern blk64_t ext2fs_file_acl_block(const struct ext2_inode *inode);
-extern void ext2fs_file_acl_block_set(struct ext2_inode *inode, blk64_t blk);
+extern blk64_t ext2fs_file_acl_block(ext2_filsys fs,
+                                    const struct ext2_inode *inode);
+extern void ext2fs_file_acl_block_set(ext2_filsys fs,
+                                     struct ext2_inode *inode, blk64_t blk);
+extern errcode_t ext2fs_inode_size_set(ext2_filsys fs, struct ext2_inode *inode,
+                                      ext2_off64_t size);
 
 /* block.c */
 extern errcode_t ext2fs_block_iterate(ext2_filsys fs,
@@ -827,6 +923,9 @@ extern errcode_t ext2fs_bmap2(ext2_filsys fs, ext2_ino_t ino,
                              struct ext2_inode *inode,
                              char *block_buf, int bmap_flags, blk64_t block,
                              int *ret_flags, blk64_t *phys_blk);
+errcode_t ext2fs_map_cluster_block(ext2_filsys fs, ext2_ino_t ino,
+                                  struct ext2_inode *inode, blk64_t lblk,
+                                  blk64_t *pblk);
 
 #if 0
 /* bmove.c */
@@ -841,8 +940,11 @@ extern errcode_t ext2fs_check_desc(ext2_filsys fs);
 
 /* closefs.c */
 extern errcode_t ext2fs_close(ext2_filsys fs);
+extern errcode_t ext2fs_close2(ext2_filsys fs, int flags);
+extern errcode_t ext2fs_close_free(ext2_filsys *fs);
 extern errcode_t ext2fs_flush(ext2_filsys fs);
-extern int ext2fs_bg_has_super(ext2_filsys fs, int group_block);
+extern errcode_t ext2fs_flush2(ext2_filsys fs, int flags);
+extern int ext2fs_bg_has_super(ext2_filsys fs, dgrp_t group_block);
 extern errcode_t ext2fs_super_and_bgd_loc2(ext2_filsys fs,
                                    dgrp_t group,
                                    blk64_t *ret_super_blk,
@@ -857,10 +959,15 @@ extern int ext2fs_super_and_bgd_loc(ext2_filsys fs,
                                    int *ret_meta_bg);
 extern void ext2fs_update_dynamic_rev(ext2_filsys fs);
 
+/* crc32c.c */
+extern __u32 ext2fs_crc32c_be(__u32 crc, unsigned char const *p, size_t len);
+extern __u32 ext2fs_crc32c_le(__u32 crc, unsigned char const *p, size_t len);
+
 /* csum.c */
 extern void ext2fs_group_desc_csum_set(ext2_filsys fs, dgrp_t group);
 extern int ext2fs_group_desc_csum_verify(ext2_filsys fs, dgrp_t group);
 extern errcode_t ext2fs_set_gdt_csum(ext2_filsys fs);
+extern __u16 ext2fs_group_desc_csum(ext2_filsys fs, dgrp_t group);
 
 /* dblist.c */
 
@@ -970,8 +1077,22 @@ extern errcode_t ext2fs_dup_handle(ext2_filsys src, ext2_filsys *dest);
 extern errcode_t ext2fs_expand_dir(ext2_filsys fs, ext2_ino_t dir);
 
 /* ext_attr.c */
+extern errcode_t ext2fs_attr_get(ext2_filsys fs, struct ext2_inode *inode,
+                                int name_index, const char *name, char *buffer,
+                                size_t buffer_size, int *easize);
+
 extern __u32 ext2fs_ext_attr_hash_entry(struct ext2_ext_attr_entry *entry,
                                        void *data);
+int ext2fs_attr_get_next_attr(struct ext2_ext_attr_entry *entry, int name_index,
+                             char *buffer, int buffer_size, int start);
+errcode_t ext2fs_attr_set(ext2_filsys fs, ext2_ino_t ino,
+                         struct ext2_inode *inode,
+                         int name_index, const char *name, const char *value,
+                         int value_len, int flags);
+extern errcode_t ext2fs_expand_extra_isize(ext2_filsys fs, ext2_ino_t ino,
+                                          struct ext2_inode_large *inode,
+                                          int new_extra_isize, int *ret,
+                                          int *needed_size);
 extern errcode_t ext2fs_read_ext_attr(ext2_filsys fs, blk_t block, void *buf);
 extern errcode_t ext2fs_read_ext_attr2(ext2_filsys fs, blk64_t block,
                                       void *buf);
@@ -996,6 +1117,7 @@ extern errcode_t ext2fs_extent_open2(ext2_filsys fs, ext2_ino_t ino,
 extern void ext2fs_extent_free(ext2_extent_handle_t handle);
 extern errcode_t ext2fs_extent_get(ext2_extent_handle_t handle,
                                   int flags, struct ext2fs_extent *extent);
+extern errcode_t ext2fs_extent_node_split(ext2_extent_handle_t handle);
 extern errcode_t ext2fs_extent_replace(ext2_extent_handle_t handle, int flags,
                                       struct ext2fs_extent *extent);
 extern errcode_t ext2fs_extent_insert(ext2_extent_handle_t handle, int flags,
@@ -1008,6 +1130,9 @@ extern errcode_t ext2fs_extent_get_info(ext2_extent_handle_t handle,
                                        struct ext2_extent_info *info);
 extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
                                    blk64_t blk);
+extern errcode_t ext2fs_extent_goto2(ext2_extent_handle_t handle,
+                                    int leaf_level, blk64_t blk);
+extern errcode_t ext2fs_extent_fix_parents(ext2_extent_handle_t handle);
 
 /* fileio.c */
 extern errcode_t ext2fs_file_open2(ext2_filsys fs, ext2_ino_t ino,
@@ -1017,6 +1142,7 @@ extern errcode_t ext2fs_file_open(ext2_filsys fs, ext2_ino_t ino,
                                  int flags, ext2_file_t *ret);
 extern ext2_filsys ext2fs_file_get_fs(ext2_file_t file);
 struct ext2_inode *ext2fs_file_get_inode(ext2_file_t file);
+extern ext2_ino_t ext2fs_file_get_inode_num(ext2_file_t file);
 extern errcode_t ext2fs_file_close(ext2_file_t file);
 extern errcode_t ext2fs_file_flush(ext2_file_t file);
 extern errcode_t ext2fs_file_read(ext2_file_t file, void *buf,
@@ -1080,8 +1206,18 @@ extern errcode_t ext2fs_set_generic_bitmap_range(ext2fs_generic_bitmap bmap,
                                                 errcode_t magic,
                                                 __u32 start, __u32 num,
                                                 void *in);
+extern errcode_t ext2fs_find_first_zero_generic_bitmap(ext2fs_generic_bitmap bitmap,
+                                                      __u32 start, __u32 end,
+                                                      __u32 *out);
+extern errcode_t ext2fs_find_first_set_generic_bitmap(ext2fs_generic_bitmap bitmap,
+                                                      __u32 start, __u32 end,
+                                                      __u32 *out);
 
 /* gen_bitmap64.c */
+
+/* Generate and print bitmap usage statistics */
+#define BMAP_STATS
+
 void ext2fs_free_generic_bmap(ext2fs_generic_bitmap bmap);
 errcode_t ext2fs_alloc_generic_bmap(ext2_filsys fs, errcode_t magic,
                                    int type, __u64 start, __u64 end,
@@ -1107,6 +1243,8 @@ errcode_t ext2fs_get_generic_bmap_range(ext2fs_generic_bitmap bmap,
 errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
                                        __u64 start, unsigned int num,
                                        void *in);
+errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
+                                          ext2fs_block_bitmap *bitmap);
 
 /* getsize.c */
 extern errcode_t ext2fs_get_device_size(const char *file, int blocksize,
@@ -1115,6 +1253,7 @@ extern errcode_t ext2fs_get_device_size2(const char *file, int blocksize,
                                        blk64_t *retblocks);
 
 /* getsectsize.c */
+extern int ext2fs_get_dio_alignment(int fd);
 errcode_t ext2fs_get_device_sectsize(const char *file, int *sectsize);
 errcode_t ext2fs_get_device_phys_sectsize(const char *file, int *sectsize);
 
@@ -1144,6 +1283,7 @@ extern errcode_t ext2fs_initialize(const char *name, int flags,
 
 /* icount.c */
 extern void ext2fs_free_icount(ext2_icount_t icount);
+extern int ext2fs_icount_is_set(ext2_icount_t icount, ext2_ino_t ino);
 extern errcode_t ext2fs_create_icount_tdb(ext2_filsys fs, char *tdb_dir,
                                          int flags, ext2_icount_t *ret);
 extern errcode_t ext2fs_create_icount2(ext2_filsys fs, int flags,
@@ -1163,6 +1303,11 @@ extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
 extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
 errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
 
+/* inline.c */
+
+extern errcode_t ext2fs_get_memalign(unsigned long size,
+                                    unsigned long align, void *ptr);
+
 /* inode.c */
 extern errcode_t ext2fs_flush_icache(ext2_filsys fs);
 extern errcode_t ext2fs_get_next_inode_full(ext2_inode_scan scan,
@@ -1214,6 +1359,10 @@ extern errcode_t ext2fs_check_mount_point(const char *device, int *mount_flags,
                                          char *mtpt, int mtlen);
 
 /* punch.c */
+/*
+ * NOTE: This function removes from an inode the blocks "start", "end", and
+ * every block in between.
+ */
 extern errcode_t ext2fs_punch(ext2_filsys fs, ext2_ino_t ino,
                              struct ext2_inode *inode,
                              char *block_buf, blk64_t start,
@@ -1244,15 +1393,18 @@ extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum
 extern errcode_t ext2fs_zero_blocks(ext2_filsys fs, blk_t blk, int num,
                                    blk_t *ret_blk, int *ret_count);
 extern errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
-                                    blk64_t *ret_blk, int *ret_count); 
+                                    blk64_t *ret_blk, int *ret_count);
 extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
-                                                 __u32 size, int flags,
+                                                 __u32 num_blocks, int flags,
                                                  char  **ret_jsb);
 extern errcode_t ext2fs_add_journal_device(ext2_filsys fs,
                                           ext2_filsys journal_dev);
-extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t size,
+extern errcode_t ext2fs_add_journal_inode(ext2_filsys fs, blk_t num_blocks,
                                          int flags);
-extern int ext2fs_default_journal_size(__u64 blocks);
+extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
+                                          blk64_t goal, int flags);
+extern int ext2fs_default_journal_size(__u64 num_blocks);
+extern int ext2fs_journal_sb_start(int blocksize);
 
 /* openfs.c */
 extern errcode_t ext2fs_open(const char *name, int flags, int superblock,
@@ -1262,6 +1414,11 @@ extern errcode_t ext2fs_open2(const char *name, const char *io_options,
                              int flags, int superblock,
                              unsigned int block_size, io_manager manager,
                              ext2_filsys *ret_fs);
+/*
+ * The dgrp_t argument to these two functions is not actually a group number
+ * but a block number offset within a group table!  Convert with the formula
+ * (group_number / groups_per_block).
+ */
 extern blk64_t ext2fs_descriptor_block_loc2(ext2_filsys fs,
                                        blk64_t group_block, dgrp_t i);
 extern blk_t ext2fs_descriptor_block_loc(ext2_filsys fs, blk_t group_block,
@@ -1280,6 +1437,20 @@ errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
 errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
                        ext2_ino_t ino, int flags);
 
+/* symlink.c */
+errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
+                        const char *name, char *target);
+
+/* mmp.c */
+errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf);
+errcode_t ext2fs_mmp_write(ext2_filsys fs, blk64_t mmp_blk, void *buf);
+errcode_t ext2fs_mmp_clear(ext2_filsys fs);
+errcode_t ext2fs_mmp_init(ext2_filsys fs);
+errcode_t ext2fs_mmp_start(ext2_filsys fs);
+errcode_t ext2fs_mmp_update(ext2_filsys fs);
+errcode_t ext2fs_mmp_stop(ext2_filsys fs);
+unsigned ext2fs_mmp_new_seq(void);
+
 /* read_bb.c */
 extern errcode_t ext2fs_read_bb_inode(ext2_filsys fs,
                                      ext2_badblocks_list *bb_list);
@@ -1315,9 +1486,17 @@ extern void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t,
                                   int bufsize);
 extern void ext2fs_swap_inode(ext2_filsys fs,struct ext2_inode *t,
                              struct ext2_inode *f, int hostorder);
+extern void ext2fs_swap_mmp(struct mmp_struct *mmp);
+
+/* unix_io.c */
+extern int ext2fs_open_file(const char *pathname, int flags, mode_t mode);
+extern int ext2fs_stat(const char *path, ext2fs_struct_stat *buf);
+extern int ext2fs_fstat(int fd, ext2fs_struct_stat *buf);
 
 /* valid_blk.c */
 extern int ext2fs_inode_has_valid_blocks(struct ext2_inode *inode);
+extern int ext2fs_inode_has_valid_blocks2(ext2_filsys fs,
+                                         struct ext2_inode *inode);
 
 /* version.c */
 extern int ext2fs_parse_version_string(const char *ver_string);
@@ -1331,9 +1510,13 @@ extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
 
 
 /* inline functions */
+#ifdef NO_INLINE_FUNCS
 extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
-extern errcode_t ext2fs_get_memalign(unsigned long size,
-                                    unsigned long align, void *ptr);
+extern errcode_t ext2fs_get_memzero(unsigned long size, void *ptr);
+extern errcode_t ext2fs_get_array(unsigned long count,
+                                 unsigned long size, void *ptr);
+extern errcode_t ext2fs_get_arrayzero(unsigned long count,
+                                     unsigned long size, void *ptr);
 extern errcode_t ext2fs_free_mem(void *ptr);
 extern errcode_t ext2fs_resize_mem(unsigned long old_size,
                                   unsigned long size, void *ptr);
@@ -1347,14 +1530,15 @@ extern void ext2fs_mark_ib_dirty(ext2_filsys fs);
 extern void ext2fs_mark_bb_dirty(ext2_filsys fs);
 extern int ext2fs_test_ib_dirty(ext2_filsys fs);
 extern int ext2fs_test_bb_dirty(ext2_filsys fs);
-extern int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
-extern int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
+extern dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk);
+extern dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino);
 extern blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group);
 extern blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group);
 extern blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
                                      struct ext2_inode *inode);
 extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b);
 extern __u64 ext2fs_div64_ceil(__u64 a, __u64 b);
+#endif
 
 /*
  * The actual inlined functions definitions themselves...
@@ -1366,17 +1550,21 @@ extern __u64 ext2fs_div64_ceil(__u64 a, __u64 b);
 #ifdef INCLUDE_INLINE_FUNCS
 #define _INLINE_ extern
 #else
+#if (__STDC_VERSION__ >= 199901L)
+#define _INLINE_ inline
+#else
 #ifdef __GNUC__
 #define _INLINE_ extern __inline__
 #else                          /* For Watcom C */
 #define _INLINE_ extern inline
-#endif
+#endif /* __GNUC__ */
+#endif /* __STDC_VERSION__ >= 199901L */
 #endif
 
 #ifndef EXT2_CUSTOM_MEMORY_ROUTINES
 #include <string.h>
 /*
- *  Allocate memory
+ *  Allocate memory.  The 'ptr' arg must point to a pointer.
  */
 _INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
 {
@@ -1389,30 +1577,41 @@ _INLINE_ errcode_t ext2fs_get_mem(unsigned long size, void *ptr)
        return 0;
 }
 
-_INLINE_ errcode_t ext2fs_get_memalign(unsigned long size,
-                                      unsigned long align, void *ptr)
+_INLINE_ errcode_t ext2fs_get_memzero(unsigned long size, void *ptr)
 {
-       errcode_t retval;
-
-       if (align == 0)
-               align = 8;
-       if (retval = posix_memalign((void **) ptr, align, size)) {
-               if (retval == ENOMEM)
-                       return EXT2_ET_NO_MEMORY;
-               return retval;
-       }
+       void *pp;
+
+       pp = malloc(size);
+       if (!pp)
+               return EXT2_ET_NO_MEMORY;
+       memset(pp, 0, size);
+       memcpy(ptr, &pp, sizeof(pp));
        return 0;
 }
 
 _INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr)
 {
        if (count && (-1UL)/count<size)
-               return EXT2_ET_NO_MEMORY; //maybe define EXT2_ET_OVERFLOW ?
+               return EXT2_ET_NO_MEMORY;
        return ext2fs_get_mem(count*size, ptr);
 }
 
+_INLINE_ errcode_t ext2fs_get_arrayzero(unsigned long count,
+                                       unsigned long size, void *ptr)
+{
+       void *pp;
+
+       if (count && (-1UL)/count<size)
+               return EXT2_ET_NO_MEMORY;
+       pp = calloc(count, size);
+       if (!pp)
+               return EXT2_ET_NO_MEMORY;
+       memcpy(ptr, &pp, sizeof(pp));
+       return 0;
+}
+
 /*
- * Free memory
+ * Free memory.  The 'ptr' arg must point to a pointer.
  */
 _INLINE_ errcode_t ext2fs_free_mem(void *ptr)
 {
@@ -1426,7 +1625,7 @@ _INLINE_ errcode_t ext2fs_free_mem(void *ptr)
 }
 
 /*
- *  Resize memory
+ *  Resize memory.  The 'ptr' arg must point to a pointer.
  */
 _INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_size,
                                     unsigned long size, void *ptr)
@@ -1527,14 +1726,14 @@ _INLINE_ int ext2fs_test_bb_dirty(ext2_filsys fs)
 /*
  * Return the group # of a block
  */
-_INLINE_ int ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
+_INLINE_ dgrp_t ext2fs_group_of_blk(ext2_filsys fs, blk_t blk)
 {
        return ext2fs_group_of_blk2(fs, blk);
 }
 /*
  * Return the group # of an inode number
  */
-_INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
+_INLINE_ dgrp_t ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
 {
        return (ino - 1) / fs->super->s_inodes_per_group;
 }
@@ -1544,7 +1743,7 @@ _INLINE_ int ext2fs_group_of_ino(ext2_filsys fs, ext2_ino_t ino)
  */
 _INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group)
 {
-       return ext2fs_group_first_block2(fs, group);
+       return (blk_t) ext2fs_group_first_block2(fs, group);
 }
 
 /*
@@ -1552,13 +1751,32 @@ _INLINE_ blk_t ext2fs_group_first_block(ext2_filsys fs, dgrp_t group)
  */
 _INLINE_ blk_t ext2fs_group_last_block(ext2_filsys fs, dgrp_t group)
 {
-       return ext2fs_group_last_block2(fs, group);
+       return (blk_t) ext2fs_group_last_block2(fs, group);
 }
 
 _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
                                        struct ext2_inode *inode)
 {
-       return ext2fs_inode_data_blocks2(fs, inode);
+       return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
+}
+
+_INLINE_ struct ext2_dx_root_info *get_ext2_dx_root_info(ext2_filsys fs,
+                                                        char *buf)
+{
+       struct ext2_dir_entry *de = (struct ext2_dir_entry *)buf;
+
+       if (!(fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_DIRDATA))
+               return (struct ext2_dx_root_info *)(buf +
+                                                   __EXT2_DIR_REC_LEN(1) +
+                                                   __EXT2_DIR_REC_LEN(2));
+
+       /* get dotdot first */
+       de = (struct ext2_dir_entry *)((char *)de + de->rec_len);
+
+       /* dx root info is after dotdot entry */
+       de = (struct ext2_dir_entry *)((char *)de + EXT2_DIR_REC_LEN(de));
+
+       return (struct ext2_dx_root_info *)de;
 }
 
 /*