]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - fs/ext4/ext4.h
ext4: Use bitops to read/modify i_flags in struct ext4_inode_info
[mirror_ubuntu-bionic-kernel.git] / fs / ext4 / ext4.h
index bf938cf7c5f0f273330dc02223e5ddc88dc28b86..74414884580c94ea57ff3648fe75f5f2b68855a9 100644 (file)
 #endif
 
 #define EXT4_ERROR_INODE(inode, fmt, a...) \
-       ext4_error_inode(__func__, (inode), (fmt), ## a);
+       ext4_error_inode(__func__, (inode), (fmt), ## a)
 
 #define EXT4_ERROR_FILE(file, fmt, a...)       \
-       ext4_error_file(__func__, (file), (fmt), ## a);
+       ext4_error_file(__func__, (file), (fmt), ## a)
 
 /* data type for block offset of block group */
 typedef int ext4_grpblk_t;
@@ -125,6 +125,29 @@ struct ext4_allocation_request {
        unsigned int flags;
 };
 
+/*
+ * Logical to physical block mapping, used by ext4_map_blocks()
+ *
+ * This structure is used to pass requests into ext4_map_blocks() as
+ * well as to store the information returned by ext4_map_blocks().  It
+ * takes less room on the stack than a struct buffer_head.
+ */
+#define EXT4_MAP_NEW           (1 << BH_New)
+#define EXT4_MAP_MAPPED                (1 << BH_Mapped)
+#define EXT4_MAP_UNWRITTEN     (1 << BH_Unwritten)
+#define EXT4_MAP_BOUNDARY      (1 << BH_Boundary)
+#define EXT4_MAP_UNINIT                (1 << BH_Uninit)
+#define EXT4_MAP_FLAGS         (EXT4_MAP_NEW | EXT4_MAP_MAPPED |\
+                                EXT4_MAP_UNWRITTEN | EXT4_MAP_BOUNDARY |\
+                                EXT4_MAP_UNINIT)
+
+struct ext4_map_blocks {
+       ext4_fsblk_t m_pblk;
+       ext4_lblk_t m_lblk;
+       unsigned int m_len;
+       unsigned int m_flags;
+};
+
 /*
  * For delayed allocation tracking
  */
@@ -321,6 +344,83 @@ static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
                return flags & EXT4_OTHER_FLMASK;
 }
 
+/*
+ * Inode flags used for atomic set/get
+ */
+enum {
+       EXT4_INODE_SECRM        = 0,    /* Secure deletion */
+       EXT4_INODE_UNRM         = 1,    /* Undelete */
+       EXT4_INODE_COMPR        = 2,    /* Compress file */
+       EXT4_INODE_SYNC         = 3,    /* Synchronous updates */
+       EXT4_INODE_IMMUTABLE    = 4,    /* Immutable file */
+       EXT4_INODE_APPEND       = 5,    /* writes to file may only append */
+       EXT4_INODE_NODUMP       = 6,    /* do not dump file */
+       EXT4_INODE_NOATIME      = 7,    /* do not update atime */
+/* Reserved for compression usage... */
+       EXT4_INODE_DIRTY        = 8,
+       EXT4_INODE_COMPRBLK     = 9,    /* One or more compressed clusters */
+       EXT4_INODE_NOCOMPR      = 10,   /* Don't compress */
+       EXT4_INODE_ECOMPR       = 11,   /* Compression error */
+/* End compression flags --- maybe not all used */
+       EXT4_INODE_INDEX        = 12,   /* hash-indexed directory */
+       EXT4_INODE_IMAGIC       = 13,   /* AFS directory */
+       EXT4_INODE_JOURNAL_DATA = 14,   /* file data should be journaled */
+       EXT4_INODE_NOTAIL       = 15,   /* file tail should not be merged */
+       EXT4_INODE_DIRSYNC      = 16,   /* dirsync behaviour (directories only) */
+       EXT4_INODE_TOPDIR       = 17,   /* Top of directory hierarchies*/
+       EXT4_INODE_HUGE_FILE    = 18,   /* Set to each huge file */
+       EXT4_INODE_EXTENTS      = 19,   /* Inode uses extents */
+       EXT4_INODE_EA_INODE     = 21,   /* Inode used for large EA */
+       EXT4_INODE_EOFBLOCKS    = 22,   /* Blocks allocated beyond EOF */
+       EXT4_INODE_RESERVED     = 31,   /* reserved for ext4 lib */
+};
+
+#define TEST_FLAG_VALUE(FLAG) (EXT4_##FLAG##_FL == (1 << EXT4_INODE_##FLAG))
+#define CHECK_FLAG_VALUE(FLAG) if (!TEST_FLAG_VALUE(FLAG)) { \
+       printk(KERN_EMERG "EXT4 flag fail: " #FLAG ": %d %d\n", \
+               EXT4_##FLAG##_FL, EXT4_INODE_##FLAG); BUG_ON(1); }
+
+/*
+ * Since it's pretty easy to mix up bit numbers and hex values, and we
+ * can't do a compile-time test for ENUM values, we use a run-time
+ * test to make sure that EXT4_XXX_FL is consistent with respect to
+ * EXT4_INODE_XXX.  If all is well the printk and BUG_ON will all drop
+ * out so it won't cost any extra space in the compiled kernel image.
+ * But it's important that these values are the same, since we are
+ * using EXT4_INODE_XXX to test for the flag values, but EXT4_XX_FL
+ * must be consistent with the values of FS_XXX_FL defined in
+ * include/linux/fs.h and the on-disk values found in ext2, ext3, and
+ * ext4 filesystems, and of course the values defined in e2fsprogs.
+ *
+ * It's not paranoia if the Murphy's Law really *is* out to get you.  :-)
+ */
+static inline void ext4_check_flag_values(void)
+{
+       CHECK_FLAG_VALUE(SECRM);
+       CHECK_FLAG_VALUE(UNRM);
+       CHECK_FLAG_VALUE(COMPR);
+       CHECK_FLAG_VALUE(SYNC);
+       CHECK_FLAG_VALUE(IMMUTABLE);
+       CHECK_FLAG_VALUE(APPEND);
+       CHECK_FLAG_VALUE(NODUMP);
+       CHECK_FLAG_VALUE(NOATIME);
+       CHECK_FLAG_VALUE(DIRTY);
+       CHECK_FLAG_VALUE(COMPRBLK);
+       CHECK_FLAG_VALUE(NOCOMPR);
+       CHECK_FLAG_VALUE(ECOMPR);
+       CHECK_FLAG_VALUE(INDEX);
+       CHECK_FLAG_VALUE(IMAGIC);
+       CHECK_FLAG_VALUE(JOURNAL_DATA);
+       CHECK_FLAG_VALUE(NOTAIL);
+       CHECK_FLAG_VALUE(DIRSYNC);
+       CHECK_FLAG_VALUE(TOPDIR);
+       CHECK_FLAG_VALUE(HUGE_FILE);
+       CHECK_FLAG_VALUE(EXTENTS);
+       CHECK_FLAG_VALUE(EA_INODE);
+       CHECK_FLAG_VALUE(EOFBLOCKS);
+       CHECK_FLAG_VALUE(RESERVED);
+}
+
 /* Used to pass group descriptor data when online resize is done */
 struct ext4_new_group_input {
        __u32 group;            /* Group number for this data */
@@ -616,9 +716,8 @@ struct ext4_ext_cache {
  */
 struct ext4_inode_info {
        __le32  i_data[15];     /* unconverted */
-       __u32   i_flags;
-       ext4_fsblk_t    i_file_acl;
        __u32   i_dtime;
+       ext4_fsblk_t    i_file_acl;
 
        /*
         * i_block_group is the number of the block group which contains
@@ -629,6 +728,7 @@ struct ext4_inode_info {
         */
        ext4_group_t    i_block_group;
        unsigned long   i_state_flags;          /* Dynamic state flags */
+       unsigned long   i_flags;
 
        ext4_lblk_t             i_dir_start_lookup;
 #ifdef CONFIG_EXT4_FS_XATTR
@@ -1064,20 +1164,22 @@ enum {
        EXT4_STATE_DIO_UNWRITTEN,       /* need convert on dio done*/
 };
 
-static inline int ext4_test_inode_state(struct inode *inode, int bit)
-{
-       return test_bit(bit, &EXT4_I(inode)->i_state_flags);
-}
-
-static inline void ext4_set_inode_state(struct inode *inode, int bit)
-{
-       set_bit(bit, &EXT4_I(inode)->i_state_flags);
+#define EXT4_INODE_BIT_FNS(name, field)                                        \
+static inline int ext4_test_inode_##name(struct inode *inode, int bit) \
+{                                                                      \
+       return test_bit(bit, &EXT4_I(inode)->i_##field);                \
+}                                                                      \
+static inline void ext4_set_inode_##name(struct inode *inode, int bit) \
+{                                                                      \
+       set_bit(bit, &EXT4_I(inode)->i_##field);                        \
+}                                                                      \
+static inline void ext4_clear_inode_##name(struct inode *inode, int bit) \
+{                                                                      \
+       clear_bit(bit, &EXT4_I(inode)->i_##field);                      \
 }
 
-static inline void ext4_clear_inode_state(struct inode *inode, int bit)
-{
-       clear_bit(bit, &EXT4_I(inode)->i_state_flags);
-}
+EXT4_INODE_BIT_FNS(flag, flags)
+EXT4_INODE_BIT_FNS(state, state_flags)
 #else
 /* Assume that user mode programs are passing in an ext4fs superblock, not
  * a kernel struct super_block.  This will allow us to call the feature-test
@@ -1264,7 +1366,7 @@ struct ext4_dir_entry_2 {
 
 #define is_dx(dir) (EXT4_HAS_COMPAT_FEATURE(dir->i_sb, \
                                      EXT4_FEATURE_COMPAT_DIR_INDEX) && \
-                     (EXT4_I(dir)->i_flags & EXT4_INDEX_FL))
+                   ext4_test_inode_flag((dir), EXT4_INODE_INDEX))
 #define EXT4_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT4_LINK_MAX)
 #define EXT4_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
 
@@ -1678,6 +1780,7 @@ struct ext4_group_info {
        ext4_grpblk_t   bb_first_free;  /* first free block */
        ext4_grpblk_t   bb_free;        /* total free blocks */
        ext4_grpblk_t   bb_fragments;   /* nr of freespace fragments */
+       ext4_grpblk_t   bb_largest_free_order;/* order of largest frag in BG */
        struct          list_head bb_prealloc_list;
 #ifdef DOUBLE_CHECK
        void            *bb_bitmap;
@@ -1772,9 +1875,8 @@ extern int ext4_ext_tree_init(handle_t *handle, struct inode *);
 extern int ext4_ext_writepage_trans_blocks(struct inode *, int);
 extern int ext4_ext_index_trans_blocks(struct inode *inode, int nrblocks,
                                       int chunk);
-extern int ext4_ext_get_blocks(handle_t *handle, struct inode *inode,
-                              ext4_lblk_t iblock, unsigned int max_blocks,
-                              struct buffer_head *bh_result, int flags);
+extern int ext4_ext_map_blocks(handle_t *handle, struct inode *inode,
+                              struct ext4_map_blocks *map, int flags);
 extern void ext4_ext_truncate(struct inode *);
 extern void ext4_ext_init(struct super_block *);
 extern void ext4_ext_release(struct super_block *);
@@ -1782,6 +1884,8 @@ extern long ext4_fallocate(struct inode *inode, int mode, loff_t offset,
                          loff_t len);
 extern int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset,
                          ssize_t len);
+extern int ext4_map_blocks(handle_t *handle, struct inode *inode,
+                          struct ext4_map_blocks *map, int flags);
 extern int ext4_get_blocks(handle_t *handle, struct inode *inode,
                           sector_t block, unsigned int max_blocks,
                           struct buffer_head *bh, int flags);