Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-2.6-microblaze.git] / fs / ext4 / ext4.h
index f9a692c..254d1c2 100644 (file)
@@ -27,7 +27,6 @@
 #include <linux/seqlock.h>
 #include <linux/mutex.h>
 #include <linux/timer.h>
-#include <linux/version.h>
 #include <linux/wait.h>
 #include <linux/sched/signal.h>
 #include <linux/blockgroup_lock.h>
@@ -492,7 +491,7 @@ struct flex_groups {
 
 /* Flags which are mutually exclusive to DAX */
 #define EXT4_DAX_MUT_EXCL (EXT4_VERITY_FL | EXT4_ENCRYPT_FL |\
-                          EXT4_JOURNAL_DATA_FL)
+                          EXT4_JOURNAL_DATA_FL | EXT4_INLINE_DATA_FL)
 
 /* Mask out flags that are inappropriate for the given type of inode. */
 static inline __u32 ext4_mask_flags(umode_t mode, __u32 flags)
@@ -964,6 +963,7 @@ do {                                                                               \
 #endif /* defined(__KERNEL__) || defined(__linux__) */
 
 #include "extents_status.h"
+#include "fast_commit.h"
 
 /*
  * Lock subclasses for i_data_sem in the ext4_inode_info structure.
@@ -1021,6 +1021,31 @@ struct ext4_inode_info {
 
        struct list_head i_orphan;      /* unlinked but open inodes */
 
+       /* Fast commit related info */
+
+       struct list_head i_fc_list;     /*
+                                        * inodes that need fast commit
+                                        * protected by sbi->s_fc_lock.
+                                        */
+
+       /* Fast commit subtid when this inode was committed */
+       unsigned int i_fc_committed_subtid;
+
+       /* Start of lblk range that needs to be committed in this fast commit */
+       ext4_lblk_t i_fc_lblk_start;
+
+       /* End of lblk range that needs to be committed in this fast commit */
+       ext4_lblk_t i_fc_lblk_len;
+
+       /* Number of ongoing updates on this inode */
+       atomic_t  i_fc_updates;
+
+       /* Fast commit wait queue for this inode */
+       wait_queue_head_t i_fc_wait;
+
+       /* Protect concurrent accesses on i_fc_lblk_start, i_fc_lblk_len */
+       struct mutex i_fc_lock;
+
        /*
         * i_disksize keeps track of what the inode size is ON DISK, not
         * in memory.  During truncate, i_size is set to the new size by
@@ -1141,6 +1166,11 @@ struct ext4_inode_info {
 #define        EXT4_VALID_FS                   0x0001  /* Unmounted cleanly */
 #define        EXT4_ERROR_FS                   0x0002  /* Errors detected */
 #define        EXT4_ORPHAN_FS                  0x0004  /* Orphans being recovered */
+#define EXT4_FC_INELIGIBLE             0x0008  /* Fast commit ineligible */
+#define EXT4_FC_COMMITTING             0x0010  /* File system underoing a fast
+                                                * commit.
+                                                */
+#define EXT4_FC_REPLAY                 0x0020  /* Fast commit replay ongoing */
 
 /*
  * Misc. filesystem flags
@@ -1214,6 +1244,8 @@ struct ext4_inode_info {
 #define EXT4_MOUNT2_EXPLICIT_JOURNAL_CHECKSUM  0x00000008 /* User explicitly
                                                specified journal checksum */
 
+#define EXT4_MOUNT2_JOURNAL_FAST_COMMIT        0x00000010 /* Journal fast commit */
+
 #define clear_opt(sb, opt)             EXT4_SB(sb)->s_mount_opt &= \
                                                ~EXT4_MOUNT_##opt
 #define set_opt(sb, opt)               EXT4_SB(sb)->s_mount_opt |= \
@@ -1481,14 +1513,14 @@ struct ext4_sb_info {
        unsigned long s_commit_interval;
        u32 s_max_batch_time;
        u32 s_min_batch_time;
-       struct block_device *journal_bdev;
+       struct block_device *s_journal_bdev;
 #ifdef CONFIG_QUOTA
        /* Names of quota files with journalled quota */
        char __rcu *s_qf_names[EXT4_MAXQUOTAS];
        int s_jquota_fmt;                       /* Format of quota to use */
 #endif
        unsigned int s_want_extra_isize; /* New inodes should reserve # bytes */
-       struct ext4_system_blocks __rcu *system_blks;
+       struct ext4_system_blocks __rcu *s_system_blks;
 
 #ifdef EXTENTS_STATS
        /* ext4 extents stats */
@@ -1611,6 +1643,34 @@ struct ext4_sb_info {
        /* Record the errseq of the backing block device */
        errseq_t s_bdev_wb_err;
        spinlock_t s_bdev_wb_lock;
+
+       /* Ext4 fast commit stuff */
+       atomic_t s_fc_subtid;
+       atomic_t s_fc_ineligible_updates;
+       /*
+        * After commit starts, the main queue gets locked, and the further
+        * updates get added in the staging queue.
+        */
+#define FC_Q_MAIN      0
+#define FC_Q_STAGING   1
+       struct list_head s_fc_q[2];     /* Inodes staged for fast commit
+                                        * that have data changes in them.
+                                        */
+       struct list_head s_fc_dentry_q[2];      /* directory entry updates */
+       unsigned int s_fc_bytes;
+       /*
+        * Main fast commit lock. This lock protects accesses to the
+        * following fields:
+        * ei->i_fc_list, s_fc_dentry_q, s_fc_q, s_fc_bytes, s_fc_bh.
+        */
+       spinlock_t s_fc_lock;
+       struct buffer_head *s_fc_bh;
+       struct ext4_fc_stats s_fc_stats;
+       u64 s_fc_avg_commit_time;
+#ifdef CONFIG_EXT4_DEBUG
+       int s_fc_debug_max_replay;
+#endif
+       struct ext4_fc_replay_state s_fc_replay_state;
 };
 
 static inline struct ext4_sb_info *EXT4_SB(struct super_block *sb)
@@ -1721,6 +1781,7 @@ enum {
        EXT4_STATE_EXT_PRECACHED,       /* extents have been precached */
        EXT4_STATE_LUSTRE_EA_INODE,     /* Lustre-style ea_inode */
        EXT4_STATE_VERITY_IN_PROGRESS,  /* building fs-verity Merkle tree */
+       EXT4_STATE_FC_COMMITTING,       /* Fast commit ongoing */
 };
 
 #define EXT4_INODE_BIT_FNS(name, field, offset)                                \
@@ -1814,6 +1875,7 @@ static inline bool ext4_verity_in_progress(struct inode *inode)
 #define EXT4_FEATURE_COMPAT_RESIZE_INODE       0x0010
 #define EXT4_FEATURE_COMPAT_DIR_INDEX          0x0020
 #define EXT4_FEATURE_COMPAT_SPARSE_SUPER2      0x0200
+#define EXT4_FEATURE_COMPAT_FAST_COMMIT                0x0400
 #define EXT4_FEATURE_COMPAT_STABLE_INODES      0x0800
 
 #define EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER    0x0001
@@ -1916,6 +1978,7 @@ EXT4_FEATURE_COMPAT_FUNCS(xattr,          EXT_ATTR)
 EXT4_FEATURE_COMPAT_FUNCS(resize_inode,                RESIZE_INODE)
 EXT4_FEATURE_COMPAT_FUNCS(dir_index,           DIR_INDEX)
 EXT4_FEATURE_COMPAT_FUNCS(sparse_super2,       SPARSE_SUPER2)
+EXT4_FEATURE_COMPAT_FUNCS(fast_commit,         FAST_COMMIT)
 EXT4_FEATURE_COMPAT_FUNCS(stable_inodes,       STABLE_INODES)
 
 EXT4_FEATURE_RO_COMPAT_FUNCS(sparse_super,     SPARSE_SUPER)
@@ -2650,6 +2713,7 @@ extern int ext4fs_dirhash(const struct inode *dir, const char *name, int len,
                          struct dx_hash_info *hinfo);
 
 /* ialloc.c */
+extern int ext4_mark_inode_used(struct super_block *sb, int ino);
 extern struct inode *__ext4_new_inode(handle_t *, struct inode *, umode_t,
                                      const struct qstr *qstr, __u32 goal,
                                      uid_t *owner, __u32 i_flags,
@@ -2675,6 +2739,27 @@ extern int ext4_init_inode_table(struct super_block *sb,
                                 ext4_group_t group, int barrier);
 extern void ext4_end_bitmap_read(struct buffer_head *bh, int uptodate);
 
+/* fast_commit.c */
+int ext4_fc_info_show(struct seq_file *seq, void *v);
+void ext4_fc_init(struct super_block *sb, journal_t *journal);
+void ext4_fc_init_inode(struct inode *inode);
+void ext4_fc_track_range(struct inode *inode, ext4_lblk_t start,
+                        ext4_lblk_t end);
+void ext4_fc_track_unlink(struct inode *inode, struct dentry *dentry);
+void ext4_fc_track_link(struct inode *inode, struct dentry *dentry);
+void ext4_fc_track_create(struct inode *inode, struct dentry *dentry);
+void ext4_fc_track_inode(struct inode *inode);
+void ext4_fc_mark_ineligible(struct super_block *sb, int reason);
+void ext4_fc_start_ineligible(struct super_block *sb, int reason);
+void ext4_fc_stop_ineligible(struct super_block *sb);
+void ext4_fc_start_update(struct inode *inode);
+void ext4_fc_stop_update(struct inode *inode);
+void ext4_fc_del(struct inode *inode);
+bool ext4_fc_replay_check_excluded(struct super_block *sb, ext4_fsblk_t block);
+void ext4_fc_replay_cleanup(struct super_block *sb);
+int ext4_fc_commit(journal_t *journal, tid_t commit_tid);
+int __init ext4_fc_init_dentry_cache(void);
+
 /* mballoc.c */
 extern const struct seq_operations ext4_mb_seq_groups_ops;
 extern long ext4_mb_stats;
@@ -2704,8 +2789,12 @@ extern int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
                                ext4_fsblk_t block, unsigned long count);
 extern int ext4_trim_fs(struct super_block *, struct fstrim_range *);
 extern void ext4_process_freed_data(struct super_block *sb, tid_t commit_tid);
+extern void ext4_mb_mark_bb(struct super_block *sb, ext4_fsblk_t block,
+                      int len, int state);
 
 /* inode.c */
+void ext4_inode_csum_set(struct inode *inode, struct ext4_inode *raw,
+                        struct ext4_inode_info *ei);
 int ext4_inode_is_fast_symlink(struct inode *inode);
 struct buffer_head *ext4_getblk(handle_t *, struct inode *, ext4_lblk_t, int);
 struct buffer_head *ext4_bread(handle_t *, struct inode *, ext4_lblk_t, int);
@@ -2752,6 +2841,8 @@ extern int  ext4_sync_inode(handle_t *, struct inode *);
 extern void ext4_dirty_inode(struct inode *, int);
 extern int ext4_change_inode_journal_flag(struct inode *, int);
 extern int ext4_get_inode_loc(struct inode *, struct ext4_iloc *);
+extern int ext4_get_fc_inode_loc(struct super_block *sb, unsigned long ino,
+                         struct ext4_iloc *iloc);
 extern int ext4_inode_attach_jinode(struct inode *inode);
 extern int ext4_can_truncate(struct inode *inode);
 extern int ext4_truncate(struct inode *);
@@ -2785,12 +2876,15 @@ extern int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
 /* ioctl.c */
 extern long ext4_ioctl(struct file *, unsigned int, unsigned long);
 extern long ext4_compat_ioctl(struct file *, unsigned int, unsigned long);
+extern void ext4_reset_inode_seed(struct inode *inode);
 
 /* migrate.c */
 extern int ext4_ext_migrate(struct inode *);
 extern int ext4_ind_migrate(struct inode *inode);
 
 /* namei.c */
+extern int ext4_init_new_dir(handle_t *handle, struct inode *dir,
+                            struct inode *inode);
 extern int ext4_dirblock_csum_verify(struct inode *inode,
                                     struct buffer_head *bh);
 extern int ext4_orphan_add(handle_t *, struct inode *);
@@ -2824,6 +2918,14 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
 /* super.c */
 extern struct buffer_head *ext4_sb_bread(struct super_block *sb,
                                         sector_t block, int op_flags);
+extern struct buffer_head *ext4_sb_bread_unmovable(struct super_block *sb,
+                                                  sector_t block);
+extern void ext4_read_bh_nowait(struct buffer_head *bh, int op_flags,
+                               bh_end_io_t *end_io);
+extern int ext4_read_bh(struct buffer_head *bh, int op_flags,
+                       bh_end_io_t *end_io);
+extern int ext4_read_bh_lock(struct buffer_head *bh, int op_flags, bool wait);
+extern void ext4_sb_breadahead_unmovable(struct super_block *sb, sector_t block);
 extern int ext4_seq_options_show(struct seq_file *seq, void *offset);
 extern int ext4_calculate_overhead(struct super_block *sb);
 extern void ext4_superblock_csum_set(struct super_block *sb);
@@ -3012,22 +3114,24 @@ static inline int ext4_has_group_desc_csum(struct super_block *sb)
        return ext4_has_feature_gdt_csum(sb) || ext4_has_metadata_csum(sb);
 }
 
+#define ext4_read_incompat_64bit_val(es, name) \
+       (((es)->s_feature_incompat & cpu_to_le32(EXT4_FEATURE_INCOMPAT_64BIT) \
+               ? (ext4_fsblk_t)le32_to_cpu(es->name##_hi) << 32 : 0) | \
+               le32_to_cpu(es->name##_lo))
+
 static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es)
 {
-       return ((ext4_fsblk_t)le32_to_cpu(es->s_blocks_count_hi) << 32) |
-               le32_to_cpu(es->s_blocks_count_lo);
+       return ext4_read_incompat_64bit_val(es, s_blocks_count);
 }
 
 static inline ext4_fsblk_t ext4_r_blocks_count(struct ext4_super_block *es)
 {
-       return ((ext4_fsblk_t)le32_to_cpu(es->s_r_blocks_count_hi) << 32) |
-               le32_to_cpu(es->s_r_blocks_count_lo);
+       return ext4_read_incompat_64bit_val(es, s_r_blocks_count);
 }
 
 static inline ext4_fsblk_t ext4_free_blocks_count(struct ext4_super_block *es)
 {
-       return ((ext4_fsblk_t)le32_to_cpu(es->s_free_blocks_count_hi) << 32) |
-               le32_to_cpu(es->s_free_blocks_count_lo);
+       return ext4_read_incompat_64bit_val(es, s_free_blocks_count);
 }
 
 static inline void ext4_blocks_count_set(struct ext4_super_block *es,
@@ -3153,6 +3257,9 @@ int ext4_update_disksize_before_punch(struct inode *inode, loff_t offset,
 
 struct ext4_group_info {
        unsigned long   bb_state;
+#ifdef AGGRESSIVE_CHECK
+       unsigned long   bb_check_counter;
+#endif
        struct rb_root  bb_free_root;
        ext4_grpblk_t   bb_first_free;  /* first free block */
        ext4_grpblk_t   bb_free;        /* total free blocks */
@@ -3357,6 +3464,10 @@ extern int ext4_handle_dirty_dirblock(handle_t *handle, struct inode *inode,
 extern int ext4_ci_compare(const struct inode *parent,
                           const struct qstr *fname,
                           const struct qstr *entry, bool quick);
+extern int __ext4_unlink(struct inode *dir, const struct qstr *d_name,
+                        struct inode *inode);
+extern int __ext4_link(struct inode *dir, struct inode *inode,
+                      struct dentry *dentry);
 
 #define S_SHIFT 12
 static const unsigned char ext4_type_by_mode[(S_IFMT >> S_SHIFT) + 1] = {
@@ -3457,6 +3568,11 @@ extern int ext4_clu_mapped(struct inode *inode, ext4_lblk_t lclu);
 extern int ext4_datasem_ensure_credits(handle_t *handle, struct inode *inode,
                                       int check_cred, int restart_cred,
                                       int revoke_cred);
+extern void ext4_ext_replay_shrink_inode(struct inode *inode, ext4_lblk_t end);
+extern int ext4_ext_replay_set_iblocks(struct inode *inode);
+extern int ext4_ext_replay_update_ex(struct inode *inode, ext4_lblk_t start,
+               int len, int unwritten, ext4_fsblk_t pblk);
+extern int ext4_ext_clear_bb(struct inode *inode);
 
 
 /* move_extent.c */