f2fs: introduce readahead mode of node pages
authorJaegeuk Kim <jaegeuk.kim@samsung.com>
Tue, 26 Feb 2013 04:10:46 +0000 (13:10 +0900)
committerJaegeuk Kim <jaegeuk.kim@samsung.com>
Mon, 18 Mar 2013 12:00:33 +0000 (21:00 +0900)
Previously, f2fs reads several node pages ahead when get_dnode_of_data is called
with RDONLY_NODE flag.
And, this flag is set by the following functions.
- get_data_block_ro
- get_lock_data_page
- do_write_data_page
- truncate_blocks
- truncate_hole

However, this readahead mechanism is initially introduced for the use of
get_data_block_ro to enhance the sequential read performance.

So, let's clarify all the cases with the additional modes as follows.

enum {
ALLOC_NODE, /* allocate a new node page if needed */
LOOKUP_NODE, /* look up a node without readahead */
LOOKUP_NODE_RA, /*
 * look up a node with readahead called
 * by get_datablock_ro.
 */
}

Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
fs/f2fs/data.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/node.c
fs/f2fs/recovery.c

index 7bd22a201125636397c0d79d15a2822e83c130f4..277966a8547ad8549efdab6be61a7a87c84c17cd 100644 (file)
@@ -183,7 +183,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
        f2fs_put_page(page, 0);
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+       err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
        if (err)
                return ERR_PTR(err);
        f2fs_put_dnode(&dn);
@@ -222,7 +222,7 @@ struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
        int err;
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+       err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
        if (err)
                return ERR_PTR(err);
        f2fs_put_dnode(&dn);
@@ -262,7 +262,7 @@ struct page *get_new_data_page(struct inode *inode, pgoff_t index,
        int err;
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, index, 0);
+       err = get_dnode_of_data(&dn, index, ALLOC_NODE);
        if (err)
                return ERR_PTR(err);
 
@@ -392,7 +392,7 @@ static int get_data_block_ro(struct inode *inode, sector_t iblock,
 
        /* When reading holes, we need its node page */
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, pgofs, RDONLY_NODE);
+       err = get_dnode_of_data(&dn, pgofs, LOOKUP_NODE_RA);
        if (err)
                return (err == -ENOENT) ? 0 : err;
 
@@ -443,7 +443,7 @@ int do_write_data_page(struct page *page)
        int err = 0;
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, page->index, RDONLY_NODE);
+       err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE);
        if (err)
                return err;
 
@@ -607,7 +607,7 @@ static int f2fs_write_begin(struct file *file, struct address_space *mapping,
        mutex_lock_op(sbi, DATA_NEW);
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, index, 0);
+       err = get_dnode_of_data(&dn, index, ALLOC_NODE);
        if (err) {
                mutex_unlock_op(sbi, DATA_NEW);
                f2fs_put_page(page, 1);
index cc2213afdcc74a99ef460f0bf8bf9b48e3d3645b..be7ae70b0b1d94d2303f06af357cc59e8f5b8436 100644 (file)
@@ -125,11 +125,15 @@ static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i)
                                         * file keeping -1 as its node offset to
                                         * distinguish from index node blocks.
                                         */
-#define RDONLY_NODE            1       /*
-                                        * specify a read-only mode when getting
-                                        * a node block. 0 is read-write mode.
-                                        * used by get_dnode_of_data().
+enum {
+       ALLOC_NODE,                     /* allocate a new node page if needed */
+       LOOKUP_NODE,                    /* look up a node without readahead */
+       LOOKUP_NODE_RA,                 /*
+                                        * look up a node with readahead called
+                                        * by get_datablock_ro.
                                         */
+};
+
 #define F2FS_LINK_MAX          32000   /* maximum link count per file */
 
 /* for in-memory extent cache entry */
index 958a46da19ae2fbae17f6a7bf25475cd061f8ad3..269645e2351912d244bcb17fe6fc1c75b400f7e1 100644 (file)
@@ -43,7 +43,7 @@ static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma,
 
        /* block allocation */
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, page->index, 0);
+       err = get_dnode_of_data(&dn, page->index, ALLOC_NODE);
        if (err) {
                mutex_unlock_op(sbi, DATA_NEW);
                goto out;
@@ -258,7 +258,7 @@ static int truncate_blocks(struct inode *inode, u64 from)
        mutex_lock_op(sbi, DATA_TRUNC);
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       err = get_dnode_of_data(&dn, free_from, RDONLY_NODE);
+       err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE);
        if (err) {
                if (err == -ENOENT)
                        goto free_next;
@@ -420,7 +420,7 @@ int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end)
 
                mutex_lock_op(sbi, DATA_TRUNC);
                set_new_dnode(&dn, inode, NULL, NULL, 0);
-               err = get_dnode_of_data(&dn, index, RDONLY_NODE);
+               err = get_dnode_of_data(&dn, index, LOOKUP_NODE);
                if (err) {
                        mutex_unlock_op(sbi, DATA_TRUNC);
                        if (err == -ENOENT)
@@ -504,7 +504,7 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
                mutex_lock_op(sbi, DATA_NEW);
 
                set_new_dnode(&dn, inode, NULL, NULL, 0);
-               ret = get_dnode_of_data(&dn, index, 0);
+               ret = get_dnode_of_data(&dn, index, ALLOC_NODE);
                if (ret) {
                        mutex_unlock_op(sbi, DATA_NEW);
                        break;
index efcada7becd5922f7443d142267c47cf75d217a5..65ec2eabb392c66ac505c3266d80d5f370e9782a 100644 (file)
@@ -384,7 +384,7 @@ got:
 /*
  * Caller should call f2fs_put_dnode(dn).
  */
-int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
+int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
        struct page *npage[4];
@@ -411,7 +411,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
        for (i = 1; i <= level; i++) {
                bool done = false;
 
-               if (!nids[i] && !ro) {
+               if (!nids[i] && mode == ALLOC_NODE) {
                        mutex_lock_op(sbi, NODE_NEW);
 
                        /* alloc new node */
@@ -434,7 +434,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int ro)
                        alloc_nid_done(sbi, nids[i]);
                        mutex_unlock_op(sbi, NODE_NEW);
                        done = true;
-               } else if (ro && i == level && level > 1) {
+               } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
                        npage[i] = get_node_page_ra(parent, offset[i - 1]);
                        if (IS_ERR(npage[i])) {
                                err = PTR_ERR(npage[i]);
index b235215ac13816feea8a960e05f40bb03b9dadf9..6b82e2034cfd391e6fd5ea3df5066ad7867a36cc 100644 (file)
@@ -247,7 +247,7 @@ static void do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
                end = start + ADDRS_PER_BLOCK;
 
        set_new_dnode(&dn, inode, NULL, NULL, 0);
-       if (get_dnode_of_data(&dn, start, 0))
+       if (get_dnode_of_data(&dn, start, ALLOC_NODE))
                return;
 
        wait_on_page_writeback(dn.node_page);