f2fs: introduce macro __cp_payload
[deliverable/linux.git] / fs / f2fs / f2fs.h
index 7fa3313ab0e27381b95d48b22da8315e605ef567..7ced71b69f33a68e82fe3dfcd6370342be9c9a63 100644 (file)
@@ -50,6 +50,7 @@
 #define F2FS_MOUNT_FLUSH_MERGE         0x00000400
 #define F2FS_MOUNT_NOBARRIER           0x00000800
 #define F2FS_MOUNT_FASTBOOT            0x00001000
+#define F2FS_MOUNT_EXTENT_CACHE                0x00002000
 
 #define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option)
 #define set_opt(sbi, option)   (sbi->mount_opt.opt |= F2FS_MOUNT_##option)
@@ -216,6 +217,15 @@ static inline bool __has_cursum_space(struct f2fs_summary_block *sum, int size,
 #define F2FS_IOC_RELEASE_VOLATILE_WRITE        _IO(F2FS_IOCTL_MAGIC, 4)
 #define F2FS_IOC_ABORT_VOLATILE_WRITE  _IO(F2FS_IOCTL_MAGIC, 5)
 
+/*
+ * should be same as XFS_IOC_GOINGDOWN.
+ * Flags for going down operation used by FS_IOC_GOINGDOWN
+ */
+#define F2FS_IOC_SHUTDOWN      _IOR('X', 125, __u32)   /* Shutdown */
+#define F2FS_GOING_DOWN_FULLSYNC       0x0     /* going down with full sync */
+#define F2FS_GOING_DOWN_METASYNC       0x1     /* going down with metadata */
+#define F2FS_GOING_DOWN_NOSYNC         0x2     /* going down */
+
 #if defined(__KERNEL__) && defined(CONFIG_COMPAT)
 /*
  * ioctl commands in 32 bit emulation
@@ -273,14 +283,34 @@ enum {
 
 #define MAX_DIR_RA_PAGES       4       /* maximum ra pages of dir */
 
+/* vector size for gang look-up from extent cache that consists of radix tree */
+#define EXT_TREE_VEC_SIZE      64
+
 /* for in-memory extent cache entry */
-#define F2FS_MIN_EXTENT_LEN    16      /* minimum extent length */
+#define F2FS_MIN_EXTENT_LEN    64      /* minimum extent length */
+
+/* number of extent info in extent cache we try to shrink */
+#define EXTENT_CACHE_SHRINK_NUMBER     128
 
 struct extent_info {
-       rwlock_t ext_lock;      /* rwlock for consistency */
-       unsigned int fofs;      /* start offset in a file */
-       u32 blk_addr;           /* start block address of the extent */
-       unsigned int len;       /* length of the extent */
+       unsigned int fofs;              /* start offset in a file */
+       u32 blk;                        /* start block address of the extent */
+       unsigned int len;               /* length of the extent */
+};
+
+struct extent_node {
+       struct rb_node rb_node;         /* rb node located in rb-tree */
+       struct list_head list;          /* node in global extent list of sbi */
+       struct extent_info ei;          /* extent info */
+};
+
+struct extent_tree {
+       nid_t ino;                      /* inode number */
+       struct rb_root root;            /* root of extent info rb-tree */
+       struct extent_node *cached_en;  /* recently accessed extent node */
+       rwlock_t lock;                  /* protect extent info rb-tree */
+       atomic_t refcount;              /* reference count of rb-tree */
+       unsigned int count;             /* # of extent node in rb-tree*/
 };
 
 /*
@@ -309,6 +339,7 @@ struct f2fs_inode_info {
        nid_t i_xattr_nid;              /* node id that contains xattrs */
        unsigned long long xattr_ver;   /* cp version of xattr modification */
        struct extent_info ext;         /* in-memory extent cache entry */
+       rwlock_t ext_lock;              /* rwlock for single extent cache */
        struct inode_entry *dirty_dir;  /* the pointer of dirty dir */
 
        struct radix_tree_root inmem_root;      /* radix tree for inmem pages */
@@ -319,21 +350,44 @@ struct f2fs_inode_info {
 static inline void get_extent_info(struct extent_info *ext,
                                        struct f2fs_extent i_ext)
 {
-       write_lock(&ext->ext_lock);
        ext->fofs = le32_to_cpu(i_ext.fofs);
-       ext->blk_addr = le32_to_cpu(i_ext.blk_addr);
+       ext->blk = le32_to_cpu(i_ext.blk);
        ext->len = le32_to_cpu(i_ext.len);
-       write_unlock(&ext->ext_lock);
 }
 
 static inline void set_raw_extent(struct extent_info *ext,
                                        struct f2fs_extent *i_ext)
 {
-       read_lock(&ext->ext_lock);
        i_ext->fofs = cpu_to_le32(ext->fofs);
-       i_ext->blk_addr = cpu_to_le32(ext->blk_addr);
+       i_ext->blk = cpu_to_le32(ext->blk);
        i_ext->len = cpu_to_le32(ext->len);
-       read_unlock(&ext->ext_lock);
+}
+
+static inline void set_extent_info(struct extent_info *ei, unsigned int fofs,
+                                               u32 blk, unsigned int len)
+{
+       ei->fofs = fofs;
+       ei->blk = blk;
+       ei->len = len;
+}
+
+static inline bool __is_extent_mergeable(struct extent_info *back,
+                                               struct extent_info *front)
+{
+       return (back->fofs + back->len == front->fofs &&
+                       back->blk + back->len == front->blk);
+}
+
+static inline bool __is_back_mergeable(struct extent_info *cur,
+                                               struct extent_info *back)
+{
+       return __is_extent_mergeable(back, cur);
+}
+
+static inline bool __is_front_mergeable(struct extent_info *cur,
+                                               struct extent_info *front)
+{
+       return __is_extent_mergeable(cur, front);
 }
 
 struct f2fs_nm_info {
@@ -571,6 +625,14 @@ struct f2fs_sb_info {
        struct list_head dir_inode_list;        /* dir inode list */
        spinlock_t dir_inode_lock;              /* for dir inode list lock */
 
+       /* for extent tree cache */
+       struct radix_tree_root extent_tree_root;/* cache extent cache entries */
+       struct rw_semaphore extent_tree_lock;   /* locking extent radix tree */
+       struct list_head extent_list;           /* lru list for shrinker */
+       spinlock_t extent_lock;                 /* locking extent lru list */
+       int total_ext_tree;                     /* extent tree count */
+       atomic_t total_ext_node;                /* extent info count */
+
        /* basic filesystem units */
        unsigned int log_sectors_per_block;     /* log2 sectors per block */
        unsigned int log_blocksize;             /* log2 block size */
@@ -920,12 +982,17 @@ static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag)
        return 0;
 }
 
+static inline block_t __cp_payload(struct f2fs_sb_info *sbi)
+{
+       return le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload);
+}
+
 static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag)
 {
        struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
        int offset;
 
-       if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) {
+       if (__cp_payload(sbi) > 0) {
                if (flag == NAT_BITMAP)
                        return &ckpt->sit_nat_version_bitmap;
                else
@@ -1290,12 +1357,6 @@ static inline int f2fs_has_inline_dentry(struct inode *inode)
        return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DENTRY);
 }
 
-static inline void *inline_dentry_addr(struct page *page)
-{
-       struct f2fs_inode *ri = F2FS_INODE(page);
-       return (void *)&(ri->i_addr[1]);
-}
-
 static inline void f2fs_dentry_kunmap(struct inode *dir, struct page *page)
 {
        if (!f2fs_has_inline_dentry(dir))
@@ -1382,6 +1443,8 @@ ino_t f2fs_inode_by_name(struct inode *, struct qstr *);
 void f2fs_set_link(struct inode *, struct f2fs_dir_entry *,
                                struct page *, struct inode *);
 int update_dent_inode(struct inode *, const struct qstr *);
+void f2fs_update_dentry(struct inode *, struct f2fs_dentry_ptr *,
+                       const struct qstr *, f2fs_hash_t , unsigned int);
 int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *);
 void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *,
                                                        struct inode *);
@@ -1521,12 +1584,17 @@ void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *,
                                                struct f2fs_io_info *);
 int reserve_new_block(struct dnode_of_data *);
 int f2fs_reserve_block(struct dnode_of_data *, pgoff_t);
-void update_extent_cache(struct dnode_of_data *);
+void f2fs_shrink_extent_tree(struct f2fs_sb_info *, int);
+void f2fs_destroy_extent_tree(struct inode *);
+void f2fs_update_extent_cache(struct dnode_of_data *);
 struct page *find_data_page(struct inode *, pgoff_t, bool);
 struct page *get_lock_data_page(struct inode *, pgoff_t);
 struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool);
 int do_write_data_page(struct page *, struct f2fs_io_info *);
 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64);
+void init_extent_cache_info(struct f2fs_sb_info *);
+int __init create_extent_cache(void);
+void destroy_extent_cache(void);
 void f2fs_invalidate_page(struct page *, unsigned int, unsigned int);
 int f2fs_release_page(struct page *, gfp_t);
 
@@ -1554,7 +1622,7 @@ struct f2fs_stat_info {
        struct f2fs_sb_info *sbi;
        int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs;
        int main_area_segs, main_area_sections, main_area_zones;
-       int hit_ext, total_ext;
+       int hit_ext, total_ext, ext_tree, ext_node;
        int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta;
        int nats, dirty_nats, sits, dirty_sits, fnids;
        int total_count, utilization;
This page took 0.037112 seconds and 5 git commands to generate.