Whamcloud - gitweb
LU-15002 mke2fs: set free blocks accurately for groups has GDT
[tools/e2fsprogs.git] / lib / ext2fs / ext2fs.h
index 86d860f..877130e 100644 (file)
 #define EXT2FS_ATTR(x)
 #endif
 
+#ifndef __nonstring
+#ifdef __has_attribute
+#if __has_attribute(__nonstring__)
+#define __nonstring                    __attribute__((__nonstring__))
+#else
+#define __nonstring
+#endif /* __has_attribute(__nonstring__) */
+#else
+# define __nonstring
+#endif /* __has_attribute */
+#endif /* __nonstring */
+
+#ifdef CONFIG_TDB
+#define EXT2FS_NO_TDB_UNUSED
+#else
+#define EXT2FS_NO_TDB_UNUSED   EXT2FS_ATTR((unused))
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -54,6 +72,7 @@ extern "C" {
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <errno.h>
 
 #if EXT2_FLAT_INCLUDES
@@ -70,8 +89,8 @@ 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 __s32 __bitwise                ext2_off_t;
+typedef __s64 __bitwise                ext2_off64_t;
 typedef __s64 __bitwise                e2_blkcnt_t;
 typedef __u32 __bitwise                ext2_dirhash_t;
 
@@ -87,6 +106,8 @@ typedef __u32 __bitwise              ext2_dirhash_t;
 #include <ext2fs/ext2_ext_attr.h>
 #endif
 
+#include "hashmap.h"
+
 /*
  * Portability help for Microsoft Visual C++
  */
@@ -102,9 +123,14 @@ typedef struct struct_ext2_filsys *ext2_filsys;
 #define EXT2FS_UNMARK_ERROR    1
 #define EXT2FS_TEST_ERROR      2
 
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_generic_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_inode_bitmap;
-typedef struct ext2fs_struct_generic_bitmap *ext2fs_block_bitmap;
+struct ext2fs_struct_generic_bitmap_base {
+       errcode_t               magic;
+       ext2_filsys             fs;
+};
+
+typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_generic_bitmap;
+typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_inode_bitmap;
+typedef struct ext2fs_struct_generic_bitmap_base *ext2fs_block_bitmap;
 
 #define EXT2_FIRST_INODE(s)    EXT2_FIRST_INO(s)
 
@@ -188,6 +214,12 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_FLAG_DIRECT_IO            0x80000
 #define EXT2_FLAG_SKIP_MMP             0x100000
 #define EXT2_FLAG_IGNORE_CSUM_ERRORS   0x200000
+#define EXT2_FLAG_SHARE_DUP            0x400000
+#define EXT2_FLAG_IGNORE_SB_ERRORS     0x800000
+#define EXT2_FLAG_BBITMAP_TAIL_PROBLEM 0x1000000
+#define EXT2_FLAG_IBITMAP_TAIL_PROBLEM 0x2000000
+#define EXT2_FLAG_THREADS              0x4000000
+#define EXT2_FLAG_IGNORE_SWAP_DIRENT   0x8000000
 
 /*
  * Special flag in the ext2 inode i_flag field that means that this is
@@ -202,6 +234,13 @@ typedef struct ext2_file *ext2_file_t;
 #define EXT2_MKJOURNAL_LAZYINIT        0x0000002 /* don't zero journal inode before use*/
 #define EXT2_MKJOURNAL_NO_MNT_CHECK 0x0000004 /* don't check mount status */
 
+/*
+ * Normal journal area size to fast commit area size ratio. This is used to
+ * set default size of fast commit area.
+ */
+#define EXT2_JOURNAL_TO_FC_BLKS_RATIO          64
+
+struct blk_alloc_ctx;
 struct opaque_ext2_group_desc;
 
 struct struct_ext2_filsys {
@@ -235,7 +274,7 @@ struct struct_ext2_filsys {
        time_t                          now;
        int                             cluster_ratio_bits;
        __u16                           default_bitmap_type;
-       __u16                           pad;
+       __u16                           fs_num_threads;
        /*
         * Reserved for future expansion
         */
@@ -257,6 +296,8 @@ struct struct_ext2_filsys {
         */
        errcode_t (*get_alloc_block)(ext2_filsys fs, blk64_t goal,
                                     blk64_t *ret);
+       errcode_t (*get_alloc_block2)(ext2_filsys fs, blk64_t goal,
+                                     blk64_t *ret, struct blk_alloc_ctx *ctx);
        void (*block_alloc_stats)(ext2_filsys fs, blk64_t blk, int inuse);
 
        /*
@@ -285,6 +326,11 @@ struct struct_ext2_filsys {
                               blk64_t len, blk64_t *pblk, blk64_t *plen);
        void (*block_alloc_stats_range)(ext2_filsys fs, blk64_t blk, blk_t num,
                                        int inuse);
+
+       /* hashmap for SHA of data blocks */
+       struct ext2fs_hashmap* block_sha_map;
+
+       const struct ext2fs_nls_table *encoding;
 };
 
 #if EXT2_FLAT_INCLUDES
@@ -309,9 +355,9 @@ struct struct_ext2_filsys {
 #define BLOCK_INLINE_DATA_CHANGED      8
 
 /*
- * Block interate flags
+ * Block iterate flags
  *
- * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the interator
+ * BLOCK_FLAG_APPEND, or BLOCK_FLAG_HOLE, indicates that the iterator
  * function should be called on blocks where the block number is zero.
  * This is used by ext2fs_expand_dir() to be able to add a new block
  * to an inode.  It can also be used for programs that want to be able
@@ -319,7 +365,7 @@ struct struct_ext2_filsys {
  *
  * BLOCK_FLAG_DEPTH_TRAVERSE indicates that the iterator function for
  * the indirect, doubly indirect, etc. blocks should be called after
- * all of the blocks containined in the indirect blocks are processed.
+ * all of the blocks contained in the indirect blocks are processed.
  * This is useful if you are going to be deallocating blocks from an
  * inode.
  *
@@ -348,6 +394,17 @@ struct struct_ext2_filsys {
 #define BLOCK_COUNT_TIND       (-3)
 #define BLOCK_COUNT_TRANSLATOR (-4)
 
+#define BLOCK_ALLOC_UNKNOWN    0
+#define BLOCK_ALLOC_DATA       1
+#define BLOCK_ALLOC_METADATA   2
+
+struct blk_alloc_ctx {
+       ext2_ino_t              ino;
+       struct ext2_inode       *inode;
+       blk64_t                 lblk;
+       int                     flags;
+};
+
 #if 0
 /*
  * Flags for ext2fs_move_blocks
@@ -402,7 +459,7 @@ typedef struct ext2_extent_path *ext2_extent_path_t;
 /*
  * Flags used by ext2fs_extent_delete()
  */
-#define EXT2_EXTENT_DELETE_KEEP_EMPTY  0x001 /* keep node if last extnt gone */
+#define EXT2_EXTENT_DELETE_KEEP_EMPTY  0x001 /* keep node if last extent gone */
 
 /*
  * Flags used by ext2fs_extent_set_bmap()
@@ -475,6 +532,7 @@ typedef struct ext2_struct_inode_scan *ext2_inode_scan;
 #define EXT2_MF_READONLY       4
 #define EXT2_MF_SWAP           8
 #define EXT2_MF_BUSY           16
+#define EXT2_MF_EXTFS          32
 
 /*
  * Ext2/linux mode flags.  We define them here so that we don't need
@@ -525,6 +583,7 @@ typedef struct ext2_struct_inode_scan *ext2_inode_scan;
  * ext2_icount_t abstraction
  */
 #define EXT2_ICOUNT_OPT_INCREMENT      0x01
+#define EXT2_ICOUNT_OPT_FULLMAP                0x02
 
 typedef struct ext2_icount *ext2_icount_t;
 
@@ -542,6 +601,16 @@ typedef struct ext2_icount *ext2_icount_t;
 #define BMAP_RET_UNINIT        0x0001
 
 /*
+ * Flags for ext2fs_read_inode2
+ */
+#define READ_INODE_NOCSUM      0x0001
+
+/*
+ * Flags for ext2fs_write_inode2
+ */
+#define WRITE_INODE_NOCSUM     0x0001
+
+/*
  * Flags for imager.c functions
  */
 #define IMAGER_FLAG_INODEMAP   1
@@ -555,6 +624,13 @@ typedef struct ext2_icount *ext2_icount_t;
          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
+
+/*
  * Features supported by this version of the library
  */
 #define EXT2_LIB_FEATURE_COMPAT_SUPP   (EXT2_FEATURE_COMPAT_DIR_PREALLOC|\
@@ -563,7 +639,10 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT2_FEATURE_COMPAT_RESIZE_INODE|\
                                         EXT2_FEATURE_COMPAT_DIR_INDEX|\
                                         EXT2_FEATURE_COMPAT_EXT_ATTR|\
-                                        EXT4_FEATURE_COMPAT_SPARSE_SUPER2)
+                                        EXT4_FEATURE_COMPAT_SPARSE_SUPER2|\
+                                        EXT4_FEATURE_COMPAT_FAST_COMMIT|\
+                                        EXT4_FEATURE_COMPAT_STABLE_INODES|\
+                                        EXT4_FEATURE_COMPAT_ORPHAN_FILE)
 
 #ifdef CONFIG_MMP
 #define EXT4_LIB_INCOMPAT_MMP          EXT4_FEATURE_INCOMPAT_MMP
@@ -577,10 +656,15 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT3_FEATURE_INCOMPAT_RECOVER|\
                                         EXT3_FEATURE_INCOMPAT_EXTENTS|\
                                         EXT4_FEATURE_INCOMPAT_FLEX_BG|\
+                                        EXT4_FEATURE_INCOMPAT_EA_INODE|\
+                                        EXT4_FEATURE_INCOMPAT_DIRDATA|\
                                         EXT4_LIB_INCOMPAT_MMP|\
                                         EXT4_FEATURE_INCOMPAT_64BIT|\
                                         EXT4_FEATURE_INCOMPAT_INLINE_DATA|\
-                                        EXT4_FEATURE_INCOMPAT_ENCRYPT)
+                                        EXT4_FEATURE_INCOMPAT_ENCRYPT|\
+                                        EXT4_FEATURE_INCOMPAT_CASEFOLD|\
+                                        EXT4_FEATURE_INCOMPAT_CSUM_SEED|\
+                                        EXT4_FEATURE_INCOMPAT_LARGEDIR)
 
 #define EXT2_LIB_FEATURE_RO_COMPAT_SUPP        (EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|\
                                         EXT4_FEATURE_RO_COMPAT_HUGE_FILE|\
@@ -591,7 +675,11 @@ typedef struct ext2_icount *ext2_icount_t;
                                         EXT4_FEATURE_RO_COMPAT_BIGALLOC|\
                                         EXT4_FEATURE_RO_COMPAT_QUOTA|\
                                         EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\
-                                        EXT4_FEATURE_RO_COMPAT_READONLY)
+                                        EXT4_FEATURE_RO_COMPAT_READONLY |\
+                                        EXT4_FEATURE_RO_COMPAT_PROJECT |\
+                                        EXT4_FEATURE_RO_COMPAT_SHARED_BLOCKS |\
+                                        EXT4_FEATURE_RO_COMPAT_VERITY |\
+                                        EXT4_FEATURE_RO_COMPAT_ORPHAN_PRESENT)
 
 /*
  * These features are only allowed if EXT2_FLAG_SOFTSUPP_FEATURES is passed
@@ -631,13 +719,20 @@ struct ext2_xattr_handle;
 #define XATTR_CHANGED  2
 
 /*
+ * flags for ext2fs_rw_bitmaps()
+ */
+#define EXT2FS_BITMAPS_WRITE           0x0001
+#define EXT2FS_BITMAPS_BLOCK           0x0002
+#define EXT2FS_BITMAPS_INODE           0x0004
+#define EXT2FS_BITMAPS_VALID_FLAGS     0x0007
+
+/*
  * function prototypes
  */
 static inline int ext2fs_has_group_desc_csum(ext2_filsys fs)
 {
-       return EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-                       EXT4_FEATURE_RO_COMPAT_GDT_CSUM |
-                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM);
+       return ext2fs_has_feature_metadata_csum(fs->super) ||
+              ext2fs_has_feature_gdt_csum(fs->super);
 }
 
 /* The LARGE_FILE feature should be set if we have stored files 2GB+ in size */
@@ -647,12 +742,16 @@ static inline int ext2fs_needs_large_file_feature(unsigned long long file_size)
 }
 
 /* alloc.c */
+extern void ext2fs_clear_block_uninit(ext2_filsys fs, dgrp_t group);
 extern errcode_t ext2fs_new_inode(ext2_filsys fs, ext2_ino_t dir, int mode,
                                  ext2fs_inode_bitmap map, ext2_ino_t *ret);
 extern errcode_t ext2fs_new_block(ext2_filsys fs, blk_t goal,
                                  ext2fs_block_bitmap map, blk_t *ret);
 extern errcode_t ext2fs_new_block2(ext2_filsys fs, blk64_t goal,
                                   ext2fs_block_bitmap map, blk64_t *ret);
+extern errcode_t ext2fs_new_block3(ext2_filsys fs, blk64_t goal,
+                                  ext2fs_block_bitmap map, blk64_t *ret,
+                                  struct blk_alloc_ctx *ctx);
 extern errcode_t ext2fs_get_free_blocks(ext2_filsys fs, blk_t start,
                                        blk_t finish, int num,
                                        ext2fs_block_bitmap map,
@@ -665,6 +764,10 @@ extern errcode_t ext2fs_alloc_block(ext2_filsys fs, blk_t goal,
                                    char *block_buf, blk_t *ret);
 extern errcode_t ext2fs_alloc_block2(ext2_filsys fs, blk64_t goal,
                                     char *block_buf, blk64_t *ret);
+extern errcode_t ext2fs_alloc_block3(ext2_filsys fs, blk64_t goal,
+                                    char *block_buf, blk64_t *ret,
+                                    struct blk_alloc_ctx *ctx);
+
 extern void ext2fs_set_alloc_block_callback(ext2_filsys fs,
                                            errcode_t (*func)(ext2_filsys fs,
                                                              blk64_t goal,
@@ -700,6 +803,10 @@ errcode_t ext2fs_alloc_range(ext2_filsys fs, int flags, blk64_t goal,
 extern int ext2fs_reserve_super_and_bgd(ext2_filsys fs,
                                        dgrp_t group,
                                        ext2fs_block_bitmap bmap);
+extern errcode_t ext2fs_reserve_super_and_bgd2(ext2_filsys fs,
+                                              dgrp_t group,
+                                              ext2fs_block_bitmap bmap,
+                                              blk_t *desc_blocks);
 extern void ext2fs_set_block_alloc_stats_callback(ext2_filsys fs,
                                                  void (*func)(ext2_filsys fs,
                                                               blk64_t blk,
@@ -750,6 +857,8 @@ extern int ext2fs_badblocks_list_iterate(ext2_badblocks_iterate iter,
 extern void ext2fs_badblocks_list_iterate_end(ext2_badblocks_iterate iter);
 extern errcode_t ext2fs_badblocks_copy(ext2_badblocks_list src,
                                       ext2_badblocks_list *dest);
+extern errcode_t ext2fs_badblocks_merge(ext2_badblocks_list src,
+                                       ext2_badblocks_list dest);
 extern int ext2fs_badblocks_equal(ext2_badblocks_list bb1,
                                  ext2_badblocks_list bb2);
 extern int ext2fs_u32_list_count(ext2_u32_list bb);
@@ -773,10 +882,10 @@ extern void ext2fs_free_block_bitmap(ext2fs_block_bitmap bitmap);
 extern void ext2fs_free_inode_bitmap(ext2fs_inode_bitmap bitmap);
 extern errcode_t ext2fs_copy_bitmap(ext2fs_generic_bitmap src,
                                    ext2fs_generic_bitmap *dest);
-extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
-extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
-extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
+errcode_t ext2fs_merge_bitmap(ext2fs_generic_bitmap src,
+                             ext2fs_generic_bitmap dest,
+                             ext2fs_generic_bitmap dup,
+                             ext2fs_generic_bitmap dup_allowed);
 extern errcode_t ext2fs_allocate_block_bitmap(ext2_filsys fs,
                                              const char *descr,
                                              ext2fs_block_bitmap *ret);
@@ -795,8 +904,6 @@ extern errcode_t ext2fs_fudge_block_bitmap_end2(ext2fs_block_bitmap bitmap,
                                         blk64_t end, blk64_t *oend);
 extern void ext2fs_clear_inode_bitmap(ext2fs_inode_bitmap bitmap);
 extern void ext2fs_clear_block_bitmap(ext2fs_block_bitmap bitmap);
-extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
-extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
 extern errcode_t ext2fs_resize_inode_bitmap(__u32 new_end, __u32 new_real_end,
                                            ext2fs_inode_bitmap bmap);
 extern errcode_t ext2fs_resize_inode_bitmap2(__u64 new_end,
@@ -846,7 +953,9 @@ 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,
-                                        struct ext2_inode *inode);
+                                    struct ext2_inode *inode);
+extern blk64_t ext2fs_get_stat_i_blocks(ext2_filsys fs,
+                                       struct ext2_inode *inode);
 extern blk64_t ext2fs_blocks_count(struct ext2_super_block *super);
 extern void ext2fs_blocks_count_set(struct ext2_super_block *super,
                                    blk64_t blk);
@@ -986,6 +1095,7 @@ extern __u32 ext2fs_crc32_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_init_csum_seed(ext2_filsys fs);
 extern errcode_t ext2fs_mmp_csum_set(ext2_filsys fs, struct mmp_struct *mmp);
 extern int ext2fs_mmp_csum_verify(ext2_filsys, struct mmp_struct *mmp);
 extern int ext2fs_verify_csum_type(ext2_filsys fs, struct ext2_super_block *sb);
@@ -1017,6 +1127,9 @@ extern errcode_t ext2fs_get_dx_countlimit(ext2_filsys fs,
                                          struct ext2_dir_entry *dirent,
                                          struct ext2_dx_countlimit **cc,
                                          int *offset);
+extern errcode_t ext2fs_dx_csum(ext2_filsys fs, ext2_ino_t inum,
+                               struct ext2_dir_entry *dirent,
+                               __u32 *crc, struct ext2_dx_tail **ret_t);
 extern errcode_t ext2fs_extent_block_csum_set(ext2_filsys fs,
                                              ext2_ino_t inum,
                                              struct ext3_extent_header *eh);
@@ -1046,6 +1159,7 @@ extern errcode_t ext2fs_add_dir_block(ext2_dblist dblist, ext2_ino_t ino,
                                      blk_t blk, int blockcnt);
 extern errcode_t ext2fs_add_dir_block2(ext2_dblist dblist, ext2_ino_t ino,
                                       blk64_t blk, e2_blkcnt_t blockcnt);
+extern errcode_t ext2fs_merge_dblist(ext2_dblist src, ext2_dblist dest);
 extern void ext2fs_dblist_sort(ext2_dblist dblist,
                               EXT2_QSORT_TYPE (*sortfunc)(const void *,
                                                           const void *));
@@ -1125,6 +1239,12 @@ extern errcode_t ext2fs_dirhash(int version, const char *name, int len,
                                ext2_dirhash_t *ret_hash,
                                ext2_dirhash_t *ret_minor_hash);
 
+extern errcode_t ext2fs_dirhash2(int version, const char *name, int len,
+                                const struct ext2fs_nls_table *charset,
+                                int hash_flags,
+                                const __u32 *seed,
+                                ext2_dirhash_t *ret_hash,
+                                ext2_dirhash_t *ret_minor_hash);
 
 /* dir_iterate.c */
 extern errcode_t ext2fs_get_rec_len(ext2_filsys fs,
@@ -1163,8 +1283,31 @@ 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);
+extern __u32 ext2fs_ext_attr_hash_entry_signed(struct ext2_ext_attr_entry *entry,
+                                              void *data);
+extern errcode_t ext2fs_ext_attr_hash_entry2(ext2_filsys fs,
+                                            struct ext2_ext_attr_entry *entry,
+                                            void *data, __u32 *hash);
+extern errcode_t ext2fs_ext_attr_hash_entry3(ext2_filsys fs,
+                                            struct ext2_ext_attr_entry *entry,
+                                            void *data, __u32 *hash,
+                                            __u32 *signed_hash);
+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);
@@ -1188,9 +1331,12 @@ extern errcode_t ext2fs_adjust_ea_refcount3(ext2_filsys fs, blk64_t blk,
                                           ext2_ino_t inum);
 errcode_t ext2fs_xattrs_write(struct ext2_xattr_handle *handle);
 errcode_t ext2fs_xattrs_read(struct ext2_xattr_handle *handle);
+errcode_t ext2fs_xattrs_read_inode(struct ext2_xattr_handle *handle,
+                                  struct ext2_inode_large *inode);
 errcode_t ext2fs_xattrs_iterate(struct ext2_xattr_handle *h,
                                int (*func)(char *name, char *value,
-                                           size_t value_len, void *data),
+                                           size_t value_len,
+                                           ext2_ino_t inode_num, void *data),
                                void *data);
 errcode_t ext2fs_xattr_get(struct ext2_xattr_handle *h, const char *key,
                           void **value, size_t *value_len);
@@ -1208,6 +1354,15 @@ errcode_t ext2fs_free_ext_attr(ext2_filsys fs, ext2_ino_t ino,
 errcode_t ext2fs_xattrs_count(struct ext2_xattr_handle *handle, size_t *count);
 errcode_t ext2fs_xattr_inode_max_size(ext2_filsys fs, ext2_ino_t ino,
                                      size_t *size);
+#define XATTR_HANDLE_FLAG_RAW  0x0001
+errcode_t ext2fs_xattrs_flags(struct ext2_xattr_handle *handle,
+                             unsigned int *new_flags, unsigned int *old_flags);
+extern void ext2fs_ext_attr_block_rehash(struct ext2_ext_attr_header *header,
+                                        struct ext2_ext_attr_entry *end);
+extern __u32 ext2fs_get_ea_inode_hash(struct ext2_inode *inode);
+extern void ext2fs_set_ea_inode_hash(struct ext2_inode *inode, __u32 hash);
+extern __u64 ext2fs_get_ea_inode_ref(struct ext2_inode *inode);
+extern void ext2fs_set_ea_inode_ref(struct ext2_inode *inode, __u64 ref_count);
 
 /* extent.c */
 extern errcode_t ext2fs_extent_header_verify(void *ptr, int size);
@@ -1235,7 +1390,13 @@ extern errcode_t ext2fs_extent_goto(ext2_extent_handle_t handle,
 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);
-size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern size_t ext2fs_max_extent_depth(ext2_extent_handle_t handle);
+extern errcode_t ext2fs_fix_extents_checksums(ext2_filsys fs, ext2_ino_t ino,
+                                             struct ext2_inode *inode);
+extern errcode_t ext2fs_count_blocks(ext2_filsys fs, ext2_ino_t ino,
+                                    struct ext2_inode *inode, blk64_t *ret_count);
+extern errcode_t ext2fs_decode_extent(struct ext2fs_extent *to, void *from,
+                                     int len);
 
 /* fallocate.c */
 #define EXT2_FALLOCATE_ZERO_BLOCKS     (0x1)
@@ -1343,6 +1504,10 @@ void ext2fs_set_generic_bmap_padding(ext2fs_generic_bitmap bmap);
 errcode_t ext2fs_resize_generic_bmap(ext2fs_generic_bitmap bmap,
                                     __u64 new_end,
                                     __u64 new_real_end);
+errcode_t ext2fs_merge_generic_bmap(ext2fs_generic_bitmap gen_src,
+                                    ext2fs_generic_bitmap gen_dest,
+                                   ext2fs_generic_bitmap gen_dup,
+                                   ext2fs_generic_bitmap dup_allowed);
 errcode_t ext2fs_compare_generic_bmap(errcode_t neq,
                                      ext2fs_generic_bitmap bm1,
                                      ext2fs_generic_bitmap bm2);
@@ -1354,6 +1519,12 @@ errcode_t ext2fs_set_generic_bmap_range(ext2fs_generic_bitmap bmap,
                                        void *in);
 errcode_t ext2fs_convert_subcluster_bitmap(ext2_filsys fs,
                                           ext2fs_block_bitmap *bitmap);
+errcode_t ext2fs_count_used_clusters(ext2_filsys fs, blk64_t start,
+                                    blk64_t end, blk64_t *out);
+errcode_t ext2fs_count_used_blocks(ext2_filsys fs, blk64_t start,
+                                  blk64_t end, blk64_t *out);
+extern unsigned int ext2fs_list_backups(ext2_filsys fs, unsigned int *three,
+                               unsigned int *five, unsigned int *seven);
 
 /* get_num_dirs.c */
 extern errcode_t ext2fs_get_num_dirs(ext2_filsys fs, ext2_ino_t *ret_num_dirs);
@@ -1392,9 +1563,13 @@ errcode_t ext2fs_write_ind_block(ext2_filsys fs, blk_t blk, void *buf);
 extern errcode_t ext2fs_initialize(const char *name, int flags,
                                   struct ext2_super_block *param,
                                   io_manager manager, ext2_filsys *ret_fs);
+extern errcode_t ext2fs_calculate_summary_stats(ext2_filsys fs, int super_only);
+extern void ext2fs_set_iops_group(ext2_filsys fs, blk64_t *array, int count);
+extern void ext2fs_clear_iops_group(ext2_filsys fs, blk64_t *array, int count);
 
 /* 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,
@@ -1411,6 +1586,7 @@ extern errcode_t ext2fs_icount_decrement(ext2_icount_t icount, ext2_ino_t ino,
                                         __u16 *ret);
 extern errcode_t ext2fs_icount_store(ext2_icount_t icount, ext2_ino_t ino,
                                     __u16 count);
+extern errcode_t ext2fs_icount_merge(ext2_icount_t src, ext2_icount_t dest);
 extern ext2_ino_t ext2fs_get_icount_size(ext2_icount_t icount);
 errcode_t ext2fs_icount_validate(ext2_icount_t icount, FILE *);
 
@@ -1459,13 +1635,19 @@ extern int ext2fs_inode_scan_flags(ext2_inode_scan scan, int set_flags,
 extern errcode_t ext2fs_read_inode_full(ext2_filsys fs, ext2_ino_t ino,
                                        struct ext2_inode * inode,
                                        int bufsize);
-extern errcode_t ext2fs_read_inode (ext2_filsys fs, ext2_ino_t ino,
+extern errcode_t ext2fs_read_inode(ext2_filsys fs, ext2_ino_t ino,
                            struct ext2_inode * inode);
+extern errcode_t ext2fs_read_inode2(ext2_filsys fs, ext2_ino_t ino,
+                                   struct ext2_inode * inode,
+                                   int bufsize, int flags);
 extern errcode_t ext2fs_write_inode_full(ext2_filsys fs, ext2_ino_t ino,
                                         struct ext2_inode * inode,
                                         int bufsize);
 extern errcode_t ext2fs_write_inode(ext2_filsys fs, ext2_ino_t ino,
                            struct ext2_inode * inode);
+extern errcode_t ext2fs_write_inode2(ext2_filsys fs, ext2_ino_t ino,
+                                    struct ext2_inode * inode,
+                                    int bufsize, int flags);
 extern errcode_t ext2fs_write_new_inode(ext2_filsys fs, ext2_ino_t ino,
                            struct ext2_inode * inode);
 extern errcode_t ext2fs_get_blocks(ext2_filsys fs, ext2_ino_t ino, blk_t *blocks);
@@ -1513,11 +1695,25 @@ extern errcode_t ext2fs_new_dir_block(ext2_filsys fs, ext2_ino_t dir_ino,
 extern errcode_t ext2fs_new_dir_inline_data(ext2_filsys fs, ext2_ino_t dir_ino,
                                ext2_ino_t parent_ino, __u32 *iblock);
 
+/* nls_utf8.c */
+extern const struct ext2fs_nls_table *ext2fs_load_nls_table(int encoding);
+extern int ext2fs_check_encoded_name(const struct ext2fs_nls_table *table,
+                                    char *s, size_t len, char **pos);
+extern int ext2fs_casefold_cmp(const struct ext2fs_nls_table *table,
+                              const unsigned char *str1, size_t len1,
+                              const unsigned char *str2, size_t len2);
+
 /* mkdir.c */
 extern errcode_t ext2fs_mkdir(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t inum,
                              const char *name);
 
 /* mkjournal.c */
+struct ext2fs_journal_params {
+       blk_t num_journal_blocks;
+       blk_t num_fc_blocks;
+};
+extern errcode_t ext2fs_get_journal_params(
+               struct ext2fs_journal_params *params, ext2_filsys fs);
 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,
@@ -1525,12 +1721,18 @@ extern errcode_t ext2fs_zero_blocks2(ext2_filsys fs, blk64_t blk, int num,
 extern errcode_t ext2fs_create_journal_superblock(ext2_filsys fs,
                                                  __u32 num_blocks, int flags,
                                                  char  **ret_jsb);
+extern errcode_t ext2fs_create_journal_superblock2(ext2_filsys fs,
+                                                 struct ext2fs_journal_params *params,
+                                                 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 num_blocks,
                                          int flags);
 extern errcode_t ext2fs_add_journal_inode2(ext2_filsys fs, blk_t num_blocks,
                                           blk64_t goal, int flags);
+extern errcode_t ext2fs_add_journal_inode3(ext2_filsys fs,
+                                   struct ext2fs_journal_params *params,
+                                   blk64_t goal, int flags);
 extern int ext2fs_default_journal_size(__u64 num_blocks);
 extern int ext2fs_journal_sb_start(int blocksize);
 
@@ -1542,6 +1744,9 @@ 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);
+errcode_t ext2fs_open_channel(ext2_filsys fs, const char *io_options,
+                             io_manager manager, int flags,
+                             int blocksize);
 /*
  * 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
@@ -1555,11 +1760,28 @@ errcode_t ext2fs_get_data_io(ext2_filsys fs, io_channel *old_io);
 errcode_t ext2fs_set_data_io(ext2_filsys fs, io_channel new_io);
 errcode_t ext2fs_rewrite_to_io(ext2_filsys fs, io_channel new_io);
 
+/* orphan.c */
+extern errcode_t ext2fs_create_orphan_file(ext2_filsys fs, blk_t num_blocks);
+extern errcode_t ext2fs_truncate_orphan_file(ext2_filsys fs);
+extern e2_blkcnt_t ext2fs_default_orphan_file_blocks(ext2_filsys fs);
+extern __u32 ext2fs_do_orphan_file_block_csum(ext2_filsys fs, ext2_ino_t ino,
+                                             __u32 gen, blk64_t blk,
+                                             char *buf);
+extern errcode_t ext2fs_orphan_file_block_csum_set(ext2_filsys fs,
+                                                  ext2_ino_t ino, blk64_t blk,
+                                                  char *buf);
+extern int ext2fs_orphan_file_block_csum_verify(ext2_filsys fs, ext2_ino_t ino,
+                                               blk64_t blk, char *buf);
+
 /* get_pathname.c */
 extern errcode_t ext2fs_get_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino,
                               char **name);
 
 /* link.c */
+#define EXT2FS_UNLINK_FORCE            0x1     /* Forcefully unlink even if
+                                                * the inode number doesn't
+                                                * match the dirent
+                                                */
 errcode_t ext2fs_link(ext2_filsys fs, ext2_ino_t dir, const char *name,
                      ext2_ino_t ino, int flags);
 errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
@@ -1568,6 +1790,7 @@ errcode_t ext2fs_unlink(ext2_filsys fs, ext2_ino_t dir, const char *name,
 /* symlink.c */
 errcode_t ext2fs_symlink(ext2_filsys fs, ext2_ino_t parent, ext2_ino_t ino,
                         const char *name, const char *target);
+int ext2fs_is_fast_symlink(struct ext2_inode *inode);
 
 /* mmp.c */
 errcode_t ext2fs_mmp_read(ext2_filsys fs, blk64_t mmp_blk, void *buf);
@@ -1600,6 +1823,15 @@ extern errcode_t ext2fs_read_bb_FILE(ext2_filsys fs, FILE *f,
 /* res_gdt.c */
 extern errcode_t ext2fs_create_resize_inode(ext2_filsys fs);
 
+/* rw_bitmaps.c */
+extern errcode_t ext2fs_rw_bitmaps(ext2_filsys fs, int flags, int num_threads);
+extern errcode_t ext2fs_read_bitmaps(ext2_filsys fs);
+extern errcode_t ext2fs_read_inode_bitmap (ext2_filsys fs);
+extern errcode_t ext2fs_read_block_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_write_bitmaps(ext2_filsys fs);
+extern errcode_t ext2fs_write_inode_bitmap(ext2_filsys fs);
+extern errcode_t ext2fs_write_block_bitmap (ext2_filsys fs);
+
 /*sha256.c */
 #define EXT2FS_SHA256_LENGTH 32
 #if 0
@@ -1658,7 +1890,6 @@ extern errcode_t ext2fs_write_bb_FILE(ext2_badblocks_list bb_list,
 
 /* inline functions */
 #ifdef NO_INLINE_FUNCS
-extern void ext2fs_init_csum_seed(ext2_filsys fs);
 extern errcode_t ext2fs_get_mem(unsigned long size, void *ptr);
 extern errcode_t ext2fs_get_memzero(unsigned long size, void *ptr);
 extern errcode_t ext2fs_get_array(unsigned long count,
@@ -1668,6 +1899,8 @@ extern errcode_t ext2fs_get_arrayzero(unsigned long count,
 extern errcode_t ext2fs_free_mem(void *ptr);
 extern errcode_t ext2fs_resize_mem(unsigned long old_size,
                                   unsigned long size, void *ptr);
+extern errcode_t ext2fs_resize_array(unsigned long old_count, unsigned long count,
+                                    unsigned long size, void *ptr);
 extern void ext2fs_mark_super_dirty(ext2_filsys fs);
 extern void ext2fs_mark_changed(ext2_filsys fs);
 extern int ext2fs_test_changed(ext2_filsys fs);
@@ -1684,13 +1917,18 @@ 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 int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks);
 extern unsigned int ext2fs_div_ceil(unsigned int a, unsigned int b);
 extern __u64 ext2fs_div64_ceil(__u64 a, __u64 b);
 extern int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry);
 extern void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len);
 extern int ext2fs_dirent_file_type(const struct ext2_dir_entry *entry);
 extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type);
-
+extern struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode);
+extern const struct ext2_inode *ext2fs_const_inode(const struct ext2_inode_large * large_inode);
+extern int ext2fs_inodes_per_orphan_block(ext2_filsys fs);
+extern struct ext4_orphan_block_tail *ext2fs_orphan_block_tail(ext2_filsys fs,
+                                                              char *buf);
 #endif
 
 /*
@@ -1714,16 +1952,6 @@ extern void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type);
 #endif /* __STDC_VERSION__ >= 199901L */
 #endif
 
-_INLINE_ void ext2fs_init_csum_seed(ext2_filsys fs)
-{
-       if (!EXT2_HAS_RO_COMPAT_FEATURE(fs->super,
-                                       EXT4_FEATURE_RO_COMPAT_METADATA_CSUM))
-               return;
-
-       fs->csum_seed = ext2fs_crc32c_le(~0, fs->super->s_uuid,
-                                        sizeof(fs->super->s_uuid));
-}
-
 #ifndef EXT2_CUSTOM_MEMORY_ROUTINES
 #include <string.h>
 /*
@@ -1752,7 +1980,8 @@ _INLINE_ errcode_t ext2fs_get_memzero(unsigned long size, void *ptr)
        return 0;
 }
 
-_INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, void *ptr)
+_INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size,
+                                   void *ptr)
 {
        if (count && (~0UL)/count < size)
                return EXT2_ET_NO_MEMORY;
@@ -1762,15 +1991,10 @@ _INLINE_ errcode_t ext2fs_get_array(unsigned long count, unsigned long size, voi
 _INLINE_ errcode_t ext2fs_get_arrayzero(unsigned long count,
                                        unsigned long size, void *ptr)
 {
-       void *pp;
-
        if (count && (~0UL)/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;
+
+       return ext2fs_get_memzero((size_t)count * size, ptr);
 }
 
 /*
@@ -1804,6 +2028,36 @@ _INLINE_ errcode_t ext2fs_resize_mem(unsigned long EXT2FS_ATTR((unused)) old_siz
        memcpy(ptr, &p, sizeof(p));
        return 0;
 }
+
+/*
+ *  Resize array.  The 'ptr' arg must point to a pointer.
+ */
+_INLINE_ errcode_t ext2fs_resize_array(unsigned long size,
+                                      unsigned long old_count,
+                                      unsigned long count, void *ptr)
+{
+       unsigned long old_size;
+       errcode_t retval;
+
+       if (count && (~0UL)/count < size)
+               return EXT2_ET_NO_MEMORY;
+
+       size *= count;
+       old_size = size * old_count;
+       retval = ext2fs_resize_mem(old_size, size, ptr);
+       if (retval)
+               return retval;
+
+       if (size > old_size) {
+               void *p;
+
+               memcpy(&p, ptr, sizeof(p));
+               memset((char *)p + old_size, 0, size - old_size);
+               memcpy(ptr, &p, sizeof(p));
+       }
+
+       return 0;
+}
 #endif /* Custom memory routines */
 
 /*
@@ -1923,6 +2177,36 @@ _INLINE_ blk_t ext2fs_inode_data_blocks(ext2_filsys fs,
        return (blk_t) ext2fs_inode_data_blocks2(fs, inode);
 }
 
+_INLINE_ int ext2fs_htree_intnode_maxrecs(ext2_filsys fs, int blocks)
+{
+       int csum_size = 0;
+
+       if ((EXT2_SB(fs->super)->s_feature_ro_compat &
+            EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) != 0)
+               csum_size = sizeof(struct ext2_dx_tail);
+       return blocks * ((fs->blocksize - (8 + csum_size)) /
+                                               sizeof(struct ext2_dx_entry));
+}
+
+_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_NAME_LEN(1) +
+                                                   EXT2_DIR_NAME_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;
+}
+
 /*
  * This is an efficient, overflow safe way of calculating ceil((1.0 * a) / b)
  */
@@ -1942,7 +2226,7 @@ _INLINE_ __u64 ext2fs_div64_ceil(__u64 a, __u64 b)
 
 _INLINE_ int ext2fs_dirent_name_len(const struct ext2_dir_entry *entry)
 {
-       return entry->name_len & 0xff;
+       return entry->name_len & EXT2_NAME_LEN;
 }
 
 _INLINE_ void ext2fs_dirent_set_name_len(struct ext2_dir_entry *entry, int len)
@@ -1960,9 +2244,47 @@ _INLINE_ void ext2fs_dirent_set_file_type(struct ext2_dir_entry *entry, int type
        entry->name_len = (entry->name_len & 0xff) | (type << 8);
 }
 
+_INLINE_ struct ext2_inode *ext2fs_inode(struct ext2_inode_large * large_inode)
+{
+       /* It is always safe to convert large inode to a small inode */
+       return (struct ext2_inode *) large_inode;
+}
+
+_INLINE_ const struct ext2_inode *
+ext2fs_const_inode(const struct ext2_inode_large * large_inode)
+{
+       /* It is always safe to convert large inode to a small inode */
+       return (const struct ext2_inode *) large_inode;
+}
+
+_INLINE_ int ext2fs_inodes_per_orphan_block(ext2_filsys fs)
+{
+       return (fs->blocksize - sizeof(struct ext4_orphan_block_tail)) /
+               sizeof(__u32);
+}
+
+_INLINE_ struct ext4_orphan_block_tail *
+ext2fs_orphan_block_tail(ext2_filsys fs, char *buf)
+{
+       return (struct ext4_orphan_block_tail *)(buf + fs->blocksize -
+               sizeof(struct ext4_orphan_block_tail));
+}
+
 #undef _INLINE_
 #endif
 
+/* htree levels for ext4 */
+#define EXT4_HTREE_LEVEL_COMPAT 2
+#define EXT4_HTREE_LEVEL       3
+
+static inline unsigned int ext2_dir_htree_level(ext2_filsys fs)
+{
+       if (ext2fs_has_feature_largedir(fs->super))
+               return EXT4_HTREE_LEVEL;
+
+       return EXT4_HTREE_LEVEL_COMPAT;
+}
+
 #ifdef __cplusplus
 }
 #endif