Merge branch 'akpm' (patches from Andrew)
[sfrench/cifs-2.6.git] / fs / f2fs / segment.h
index 313b99040aa622c1cae1afdc3a8d200ee6e0dcc9..010f336a75730e5920d67a38d04b64cebc59bf57 100644 (file)
 #define F2FS_MIN_SEGMENTS      9 /* SB + 2 (CP + SIT + NAT) + SSA + MAIN */
 
 /* L: Logical segment # in volume, R: Relative segment # in main area */
-#define GET_L2R_SEGNO(free_i, segno)   (segno - free_i->start_segno)
-#define GET_R2L_SEGNO(free_i, segno)   (segno + free_i->start_segno)
+#define GET_L2R_SEGNO(free_i, segno)   ((segno) - (free_i)->start_segno)
+#define GET_R2L_SEGNO(free_i, segno)   ((segno) + (free_i)->start_segno)
 
-#define IS_DATASEG(t)  (t <= CURSEG_COLD_DATA)
-#define IS_NODESEG(t)  (t >= CURSEG_HOT_NODE)
+#define IS_DATASEG(t)  ((t) <= CURSEG_COLD_DATA)
+#define IS_NODESEG(t)  ((t) >= CURSEG_HOT_NODE)
 
 #define IS_CURSEG(sbi, seg)                                            \
-       ((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||      \
-        (seg == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||     \
-        (seg == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||     \
-        (seg == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||      \
-        (seg == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||     \
-        (seg == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
+       (((seg) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) ||    \
+        ((seg) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) ||   \
+        ((seg) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) ||   \
+        ((seg) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) ||    \
+        ((seg) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) ||   \
+        ((seg) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno))
 
 #define IS_CURSEC(sbi, secno)                                          \
-       ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /              \
-         sbi->segs_per_sec) || \
-        (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /             \
-         sbi->segs_per_sec) || \
-        (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /             \
-         sbi->segs_per_sec) || \
-        (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /              \
-         sbi->segs_per_sec) || \
-        (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /             \
-         sbi->segs_per_sec) || \
-        (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /             \
-         sbi->segs_per_sec))   \
+       (((secno) == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno /            \
+         (sbi)->segs_per_sec) ||       \
+        ((secno) == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno /           \
+         (sbi)->segs_per_sec) ||       \
+        ((secno) == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno /           \
+         (sbi)->segs_per_sec) ||       \
+        ((secno) == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno /            \
+         (sbi)->segs_per_sec) ||       \
+        ((secno) == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno /           \
+         (sbi)->segs_per_sec) ||       \
+        ((secno) == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno /           \
+         (sbi)->segs_per_sec)) \
 
 #define MAIN_BLKADDR(sbi)      (SM_I(sbi)->main_blkaddr)
 #define SEG0_BLKADDR(sbi)      (SM_I(sbi)->seg0_blkaddr)
 
 #define MAIN_SEGS(sbi) (SM_I(sbi)->main_segments)
-#define MAIN_SECS(sbi) (sbi->total_sections)
+#define MAIN_SECS(sbi) ((sbi)->total_sections)
 
 #define TOTAL_SEGS(sbi)        (SM_I(sbi)->segment_count)
-#define TOTAL_BLKS(sbi)        (TOTAL_SEGS(sbi) << sbi->log_blocks_per_seg)
+#define TOTAL_BLKS(sbi)        (TOTAL_SEGS(sbi) << (sbi)->log_blocks_per_seg)
 
 #define MAX_BLKADDR(sbi)       (SEG0_BLKADDR(sbi) + TOTAL_BLKS(sbi))
-#define SEGMENT_SIZE(sbi)      (1ULL << (sbi->log_blocksize +          \
-                                       sbi->log_blocks_per_seg))
+#define SEGMENT_SIZE(sbi)      (1ULL << ((sbi)->log_blocksize +        \
+                                       (sbi)->log_blocks_per_seg))
 
 #define START_BLOCK(sbi, segno)        (SEG0_BLKADDR(sbi) +                    \
-        (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg))
+        (GET_R2L_SEGNO(FREE_I(sbi), segno) << (sbi)->log_blocks_per_seg))
 
 #define NEXT_FREE_BLKADDR(sbi, curseg)                                 \
-       (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff)
+       (START_BLOCK(sbi, (curseg)->segno) + (curseg)->next_blkoff)
 
 #define GET_SEGOFF_FROM_SEG0(sbi, blk_addr)    ((blk_addr) - SEG0_BLKADDR(sbi))
 #define GET_SEGNO_FROM_SEG0(sbi, blk_addr)                             \
-       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg)
+       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> (sbi)->log_blocks_per_seg)
 #define GET_BLKOFF_FROM_SEG0(sbi, blk_addr)                            \
-       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1))
+       (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & ((sbi)->blocks_per_seg - 1))
 
 #define GET_SEGNO(sbi, blk_addr)                                       \
-       (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ?          \
+       ((((blk_addr) == NULL_ADDR) || ((blk_addr) == NEW_ADDR)) ?      \
        NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi),                 \
                GET_SEGNO_FROM_SEG0(sbi, blk_addr)))
-#define GET_SECNO(sbi, segno)                                  \
-       ((segno) / sbi->segs_per_sec)
-#define GET_ZONENO_FROM_SEGNO(sbi, segno)                              \
-       ((segno / sbi->segs_per_sec) / sbi->secs_per_zone)
+#define BLKS_PER_SEC(sbi)                                      \
+       ((sbi)->segs_per_sec * (sbi)->blocks_per_seg)
+#define GET_SEC_FROM_SEG(sbi, segno)                           \
+       ((segno) / (sbi)->segs_per_sec)
+#define GET_SEG_FROM_SEC(sbi, secno)                           \
+       ((secno) * (sbi)->segs_per_sec)
+#define GET_ZONE_FROM_SEC(sbi, secno)                          \
+       ((secno) / (sbi)->secs_per_zone)
+#define GET_ZONE_FROM_SEG(sbi, segno)                          \
+       GET_ZONE_FROM_SEC(sbi, GET_SEC_FROM_SEG(sbi, segno))
 
 #define GET_SUM_BLOCK(sbi, segno)                              \
-       ((sbi->sm_info->ssa_blkaddr) + segno)
+       ((sbi)->sm_info->ssa_blkaddr + (segno))
 
 #define GET_SUM_TYPE(footer) ((footer)->entry_type)
-#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type)
+#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = (type))
 
 #define SIT_ENTRY_OFFSET(sit_i, segno)                                 \
-       (segno % sit_i->sents_per_block)
+       ((segno) % (sit_i)->sents_per_block)
 #define SIT_BLOCK_OFFSET(segno)                                        \
-       (segno / SIT_ENTRY_PER_BLOCK)
+       ((segno) / SIT_ENTRY_PER_BLOCK)
 #define        START_SEGNO(segno)              \
        (SIT_BLOCK_OFFSET(segno) * SIT_ENTRY_PER_BLOCK)
 #define SIT_BLK_CNT(sbi)                       \
 #define SECTOR_FROM_BLOCK(blk_addr)                                    \
        (((sector_t)blk_addr) << F2FS_LOG_SECTORS_PER_BLOCK)
 #define SECTOR_TO_BLOCK(sectors)                                       \
-       (sectors >> F2FS_LOG_SECTORS_PER_BLOCK)
+       ((sectors) >> F2FS_LOG_SECTORS_PER_BLOCK)
 
 /*
  * indicate a block allocation direction: RIGHT and LEFT.
@@ -132,7 +138,10 @@ enum {
  */
 enum {
        GC_CB = 0,
-       GC_GREEDY
+       GC_GREEDY,
+       ALLOC_NEXT,
+       FLUSH_DEVICE,
+       MAX_GC_POLICY,
 };
 
 /*
@@ -227,6 +236,8 @@ struct sit_info {
        unsigned long long mounted_time;        /* mount time */
        unsigned long long min_mtime;           /* min. modification time */
        unsigned long long max_mtime;           /* max. modification time */
+
+       unsigned int last_victim[MAX_GC_POLICY]; /* last victim segment # */
 };
 
 struct free_segmap_info {
@@ -303,17 +314,17 @@ static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi,
                                                unsigned int segno)
 {
        struct sit_info *sit_i = SIT_I(sbi);
-       return &sit_i->sec_entries[GET_SECNO(sbi, segno)];
+       return &sit_i->sec_entries[GET_SEC_FROM_SEG(sbi, segno)];
 }
 
 static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi,
-                               unsigned int segno, int section)
+                               unsigned int segno, bool use_section)
 {
        /*
         * In order to get # of valid blocks in a section instantly from many
         * segments, f2fs manages two counting structures separately.
         */
-       if (section > 1)
+       if (use_section && sbi->segs_per_sec > 1)
                return get_sec_entry(sbi, segno)->valid_blocks;
        else
                return get_seg_entry(sbi, segno)->valid_blocks;
@@ -358,8 +369,8 @@ static inline unsigned int find_next_inuse(struct free_segmap_info *free_i,
 static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno)
 {
        struct free_segmap_info *free_i = FREE_I(sbi);
-       unsigned int secno = segno / sbi->segs_per_sec;
-       unsigned int start_segno = secno * sbi->segs_per_sec;
+       unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
+       unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
        unsigned int next;
 
        spin_lock(&free_i->segmap_lock);
@@ -379,7 +390,8 @@ static inline void __set_inuse(struct f2fs_sb_info *sbi,
                unsigned int segno)
 {
        struct free_segmap_info *free_i = FREE_I(sbi);
-       unsigned int secno = segno / sbi->segs_per_sec;
+       unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
+
        set_bit(segno, free_i->free_segmap);
        free_i->free_segments--;
        if (!test_and_set_bit(secno, free_i->free_secmap))
@@ -390,8 +402,8 @@ static inline void __set_test_and_free(struct f2fs_sb_info *sbi,
                unsigned int segno)
 {
        struct free_segmap_info *free_i = FREE_I(sbi);
-       unsigned int secno = segno / sbi->segs_per_sec;
-       unsigned int start_segno = secno * sbi->segs_per_sec;
+       unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
+       unsigned int start_segno = GET_SEG_FROM_SEC(sbi, secno);
        unsigned int next;
 
        spin_lock(&free_i->segmap_lock);
@@ -412,7 +424,8 @@ static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi,
                unsigned int segno)
 {
        struct free_segmap_info *free_i = FREE_I(sbi);
-       unsigned int secno = segno / sbi->segs_per_sec;
+       unsigned int secno = GET_SEC_FROM_SEG(sbi, segno);
+
        spin_lock(&free_i->segmap_lock);
        if (!test_and_set_bit(segno, free_i->free_segmap)) {
                free_i->free_segments--;
@@ -477,12 +490,12 @@ static inline int overprovision_segments(struct f2fs_sb_info *sbi)
 
 static inline int overprovision_sections(struct f2fs_sb_info *sbi)
 {
-       return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec;
+       return GET_SEC_FROM_SEG(sbi, (unsigned int)overprovision_segments(sbi));
 }
 
 static inline int reserved_sections(struct f2fs_sb_info *sbi)
 {
-       return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec;
+       return GET_SEC_FROM_SEG(sbi, (unsigned int)reserved_segments(sbi));
 }
 
 static inline bool need_SSR(struct f2fs_sb_info *sbi)
@@ -495,7 +508,7 @@ static inline bool need_SSR(struct f2fs_sb_info *sbi)
                return false;
 
        return free_sections(sbi) <= (node_secs + 2 * dent_secs + imeta_secs +
-                                               reserved_sections(sbi) + 1);
+                                               2 * reserved_sections(sbi));
 }
 
 static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi,
@@ -540,6 +553,7 @@ static inline int utilization(struct f2fs_sb_info *sbi)
  */
 #define DEF_MIN_IPU_UTIL       70
 #define DEF_MIN_FSYNC_BLOCKS   8
+#define DEF_MIN_HOT_BLOCKS     16
 
 enum {
        F2FS_IPU_FORCE,
@@ -547,17 +561,15 @@ enum {
        F2FS_IPU_UTIL,
        F2FS_IPU_SSR_UTIL,
        F2FS_IPU_FSYNC,
+       F2FS_IPU_ASYNC,
 };
 
-static inline bool need_inplace_update(struct inode *inode)
+static inline bool need_inplace_update_policy(struct inode *inode,
+                               struct f2fs_io_info *fio)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        unsigned int policy = SM_I(sbi)->ipu_policy;
 
-       /* IPU can be done only for the user data */
-       if (S_ISDIR(inode->i_mode) || f2fs_is_atomic_file(inode))
-               return false;
-
        if (test_opt(sbi, LFS))
                return false;
 
@@ -572,6 +584,15 @@ static inline bool need_inplace_update(struct inode *inode)
                        utilization(sbi) > SM_I(sbi)->min_ipu_util)
                return true;
 
+       /*
+        * IPU for rewrite async pages
+        */
+       if (policy & (0x1 << F2FS_IPU_ASYNC) &&
+                       fio && fio->op == REQ_OP_WRITE &&
+                       !(fio->op_flags & REQ_SYNC) &&
+                       !f2fs_encrypted_inode(inode))
+               return true;
+
        /* this is only set during fdatasync */
        if (policy & (0x1 << F2FS_IPU_FSYNC) &&
                        is_inode_flag_set(inode, FI_NEED_IPU))
@@ -720,7 +741,7 @@ static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type)
 static inline bool no_fggc_candidate(struct f2fs_sb_info *sbi,
                                                unsigned int secno)
 {
-       if (get_valid_blocks(sbi, secno, sbi->segs_per_sec) >=
+       if (get_valid_blocks(sbi, GET_SEG_FROM_SEC(sbi, secno), true) >=
                                                sbi->fggc_threshold)
                return true;
        return false;