f2fs: apply write hints to select the type of segment for direct write
authorHyunchul Lee <cheol.lee@lge.com>
Tue, 28 Nov 2017 00:23:00 +0000 (09:23 +0900)
committerJaegeuk Kim <jaegeuk@kernel.org>
Sat, 27 Jan 2018 21:29:21 +0000 (13:29 -0800)
When blocks are allocated for direct write, select the type of
segment using the kiocb hint. But if an inode has FI_NO_ALLOC,
use the inode hint.

Signed-off-by: Hyunchul Lee <cheol.lee@lge.com>
Reviewed-by: Chao Yu <yuchao0@huawei.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c

index ff86ecb7d02198bc273f6580a6fa7376be560afd..7f8bf9629a24c8e0bb892cfa88809642675b8ebf 100644 (file)
@@ -783,7 +783,7 @@ got_it:
        return page;
 }
 
-static int __allocate_data_block(struct dnode_of_data *dn)
+static int __allocate_data_block(struct dnode_of_data *dn, int seg_type)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
        struct f2fs_summary sum;
@@ -808,7 +808,7 @@ alloc:
        set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version);
 
        allocate_data_block(sbi, NULL, dn->data_blkaddr, &dn->data_blkaddr,
-                                       &sum, CURSEG_WARM_DATA, NULL, false);
+                                       &sum, seg_type, NULL, false);
        set_data_blkaddr(dn);
 
        /* update i_size */
@@ -851,12 +851,15 @@ int f2fs_preallocate_blocks(struct kiocb *iocb, struct iov_iter *from)
                map.m_len = 0;
 
        map.m_next_pgofs = NULL;
+       map.m_seg_type = NO_CHECK_TYPE;
 
-       if (iocb->ki_flags & IOCB_DIRECT)
+       if (iocb->ki_flags & IOCB_DIRECT) {
+               map.m_seg_type = rw_hint_to_seg_type(iocb->ki_hint);
                return f2fs_map_blocks(inode, &map, 1,
                        __force_buffered_io(inode, WRITE) ?
                                F2FS_GET_BLOCK_PRE_AIO :
                                F2FS_GET_BLOCK_PRE_DIO);
+       }
        if (iocb->ki_pos + iov_iter_count(from) > MAX_INLINE_DATA(inode)) {
                err = f2fs_convert_inline_inode(inode);
                if (err)
@@ -966,7 +969,8 @@ next_block:
                                        last_ofs_in_node = dn.ofs_in_node;
                                }
                        } else {
-                               err = __allocate_data_block(&dn);
+                               err = __allocate_data_block(&dn,
+                                                       map->m_seg_type);
                                if (!err)
                                        set_inode_flag(inode, FI_APPEND_WRITE);
                        }
@@ -1059,7 +1063,7 @@ out:
 
 static int __get_data_block(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh, int create, int flag,
-                       pgoff_t *next_pgofs)
+                       pgoff_t *next_pgofs, int seg_type)
 {
        struct f2fs_map_blocks map;
        int err;
@@ -1067,6 +1071,7 @@ static int __get_data_block(struct inode *inode, sector_t iblock,
        map.m_lblk = iblock;
        map.m_len = bh->b_size >> inode->i_blkbits;
        map.m_next_pgofs = next_pgofs;
+       map.m_seg_type = seg_type;
 
        err = f2fs_map_blocks(inode, &map, create, flag);
        if (!err) {
@@ -1082,14 +1087,17 @@ static int get_data_block(struct inode *inode, sector_t iblock,
                        pgoff_t *next_pgofs)
 {
        return __get_data_block(inode, iblock, bh_result, create,
-                                                       flag, next_pgofs);
+                                                       flag, next_pgofs,
+                                                       NO_CHECK_TYPE);
 }
 
 static int get_data_block_dio(struct inode *inode, sector_t iblock,
                        struct buffer_head *bh_result, int create)
 {
        return __get_data_block(inode, iblock, bh_result, create,
-                                               F2FS_GET_BLOCK_DEFAULT, NULL);
+                                               F2FS_GET_BLOCK_DEFAULT, NULL,
+                                               rw_hint_to_seg_type(
+                                                       inode->i_write_hint));
 }
 
 static int get_data_block_bmap(struct inode *inode, sector_t iblock,
@@ -1100,7 +1108,8 @@ static int get_data_block_bmap(struct inode *inode, sector_t iblock,
                return -EFBIG;
 
        return __get_data_block(inode, iblock, bh_result, create,
-                                               F2FS_GET_BLOCK_BMAP, NULL);
+                                               F2FS_GET_BLOCK_BMAP, NULL,
+                                               NO_CHECK_TYPE);
 }
 
 static inline sector_t logical_to_blk(struct inode *inode, loff_t offset)
@@ -1219,6 +1228,7 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
        map.m_len = 0;
        map.m_flags = 0;
        map.m_next_pgofs = NULL;
+       map.m_seg_type = NO_CHECK_TYPE;
 
        for (; nr_pages; nr_pages--) {
                if (pages) {
index 4acdca4369d5376a6de8e5125283e1d06cb02373..5c421738d818a5fdec8e3c8bda98c6cef49cada8 100644 (file)
@@ -542,6 +542,7 @@ struct f2fs_map_blocks {
        unsigned int m_len;
        unsigned int m_flags;
        pgoff_t *m_next_pgofs;          /* point next possible non-hole pgofs */
+       int m_seg_type;
 };
 
 /* for flag in get_data_block */
@@ -2674,6 +2675,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi);
 void destroy_segment_manager(struct f2fs_sb_info *sbi);
 int __init create_segment_manager_caches(void);
 void destroy_segment_manager_caches(void);
+int rw_hint_to_seg_type(enum rw_hint hint);
 
 /*
  * checkpoint.c
index ec7f2c5043f5b45f46fa2aeb2a7a28ef1d1c4255..e55180f71e18ba34a839952d155c57c5a547f6f4 100644 (file)
@@ -1417,7 +1417,8 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
                                        loff_t len, int mode)
 {
        struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
-       struct f2fs_map_blocks map = { .m_next_pgofs = NULL };
+       struct f2fs_map_blocks map = { .m_next_pgofs = NULL,
+                                       .m_seg_type = NO_CHECK_TYPE };
        pgoff_t pg_end;
        loff_t new_size = i_size_read(inode);
        loff_t off_end;
@@ -2065,7 +2066,8 @@ static int f2fs_defragment_range(struct f2fs_sb_info *sbi,
                                        struct f2fs_defragment *range)
 {
        struct inode *inode = file_inode(filp);
-       struct f2fs_map_blocks map = { .m_next_pgofs = NULL };
+       struct f2fs_map_blocks map = { .m_next_pgofs = NULL,
+                                       .m_seg_type = NO_CHECK_TYPE };
        struct extent_info ei = {0,0,0};
        pgoff_t pg_start, pg_end;
        unsigned int blk_per_seg = sbi->blocks_per_seg;