diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-03-08 07:29:23 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-03-20 05:30:06 -0400 |
commit | 393ff91f57c87d48ffed30878be6e3e486d3a00a (patch) | |
tree | c80fe33bcf8546ebce9ab6fc043b99889e67536f /fs/f2fs/node.c | |
parent | 25c0a6e529b56ca010e1f46239edd07c1b484b63 (diff) |
f2fs: reduce unncessary locking pages during read
This patch reduces redundant locking and unlocking pages during read operations.
In f2fs_readpage, let's use wait_on_page_locked() instead of lock_page.
And then, when we need to modify any data finally, let's lock the page so that
we can avoid lock contention.
[readpage rule]
- The f2fs_readpage returns unlocked page, or released page too in error cases.
- Its caller should handle read error, -EIO, after locking the page, which
indicates read completion.
- Its caller should check PageUptodate after grab_cache_page.
Signed-off-by: Changman Lee <cm224.lee@samsung.com>
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/node.c')
-rw-r--r-- | fs/f2fs/node.c | 58 |
1 files changed, 35 insertions, 23 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index a3cb1ff34f8e..9e6ed6708fa8 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -100,10 +100,13 @@ static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) | |||
100 | page = grab_cache_page(mapping, index); | 100 | page = grab_cache_page(mapping, index); |
101 | if (!page) | 101 | if (!page) |
102 | continue; | 102 | continue; |
103 | if (f2fs_readpage(sbi, page, index, READ)) { | 103 | if (PageUptodate(page)) { |
104 | f2fs_put_page(page, 1); | 104 | f2fs_put_page(page, 1); |
105 | continue; | 105 | continue; |
106 | } | 106 | } |
107 | if (f2fs_readpage(sbi, page, index, READ)) | ||
108 | continue; | ||
109 | |||
107 | f2fs_put_page(page, 0); | 110 | f2fs_put_page(page, 0); |
108 | } | 111 | } |
109 | } | 112 | } |
@@ -851,8 +854,16 @@ static int read_node_page(struct page *page, int type) | |||
851 | 854 | ||
852 | get_node_info(sbi, page->index, &ni); | 855 | get_node_info(sbi, page->index, &ni); |
853 | 856 | ||
854 | if (ni.blk_addr == NULL_ADDR) | 857 | if (ni.blk_addr == NULL_ADDR) { |
858 | f2fs_put_page(page, 1); | ||
855 | return -ENOENT; | 859 | return -ENOENT; |
860 | } | ||
861 | |||
862 | if (PageUptodate(page)) { | ||
863 | unlock_page(page); | ||
864 | return 0; | ||
865 | } | ||
866 | |||
856 | return f2fs_readpage(sbi, page, ni.blk_addr, type); | 867 | return f2fs_readpage(sbi, page, ni.blk_addr, type); |
857 | } | 868 | } |
858 | 869 | ||
@@ -865,19 +876,18 @@ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) | |||
865 | struct page *apage; | 876 | struct page *apage; |
866 | 877 | ||
867 | apage = find_get_page(mapping, nid); | 878 | apage = find_get_page(mapping, nid); |
868 | if (apage && PageUptodate(apage)) | 879 | if (apage && PageUptodate(apage)) { |
869 | goto release_out; | 880 | f2fs_put_page(apage, 0); |
881 | return; | ||
882 | } | ||
870 | f2fs_put_page(apage, 0); | 883 | f2fs_put_page(apage, 0); |
871 | 884 | ||
872 | apage = grab_cache_page(mapping, nid); | 885 | apage = grab_cache_page(mapping, nid); |
873 | if (!apage) | 886 | if (!apage) |
874 | return; | 887 | return; |
875 | 888 | ||
876 | if (read_node_page(apage, READA)) | 889 | if (read_node_page(apage, READA) == 0) |
877 | unlock_page(apage); | 890 | f2fs_put_page(apage, 0); |
878 | |||
879 | release_out: | ||
880 | f2fs_put_page(apage, 0); | ||
881 | return; | 891 | return; |
882 | } | 892 | } |
883 | 893 | ||
@@ -892,11 +902,14 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) | |||
892 | return ERR_PTR(-ENOMEM); | 902 | return ERR_PTR(-ENOMEM); |
893 | 903 | ||
894 | err = read_node_page(page, READ_SYNC); | 904 | err = read_node_page(page, READ_SYNC); |
895 | if (err) { | 905 | if (err) |
896 | f2fs_put_page(page, 1); | ||
897 | return ERR_PTR(err); | 906 | return ERR_PTR(err); |
898 | } | ||
899 | 907 | ||
908 | lock_page(page); | ||
909 | if (!PageUptodate(page)) { | ||
910 | f2fs_put_page(page, 1); | ||
911 | return ERR_PTR(-EIO); | ||
912 | } | ||
900 | BUG_ON(nid != nid_of_node(page)); | 913 | BUG_ON(nid != nid_of_node(page)); |
901 | mark_page_accessed(page); | 914 | mark_page_accessed(page); |
902 | return page; | 915 | return page; |
@@ -928,11 +941,8 @@ repeat: | |||
928 | goto page_hit; | 941 | goto page_hit; |
929 | 942 | ||
930 | err = read_node_page(page, READ_SYNC); | 943 | err = read_node_page(page, READ_SYNC); |
931 | unlock_page(page); | 944 | if (err) |
932 | if (err) { | ||
933 | f2fs_put_page(page, 0); | ||
934 | return ERR_PTR(err); | 945 | return ERR_PTR(err); |
935 | } | ||
936 | 946 | ||
937 | /* Then, try readahead for siblings of the desired node */ | 947 | /* Then, try readahead for siblings of the desired node */ |
938 | end = start + MAX_RA_NODE; | 948 | end = start + MAX_RA_NODE; |
@@ -957,6 +967,7 @@ page_hit: | |||
957 | f2fs_put_page(page, 1); | 967 | f2fs_put_page(page, 1); |
958 | goto repeat; | 968 | goto repeat; |
959 | } | 969 | } |
970 | mark_page_accessed(page); | ||
960 | return page; | 971 | return page; |
961 | } | 972 | } |
962 | 973 | ||
@@ -1473,23 +1484,24 @@ int restore_node_summary(struct f2fs_sb_info *sbi, | |||
1473 | sum_entry = &sum->entries[0]; | 1484 | sum_entry = &sum->entries[0]; |
1474 | 1485 | ||
1475 | for (i = 0; i < last_offset; i++, sum_entry++) { | 1486 | for (i = 0; i < last_offset; i++, sum_entry++) { |
1487 | /* | ||
1488 | * In order to read next node page, | ||
1489 | * we must clear PageUptodate flag. | ||
1490 | */ | ||
1491 | ClearPageUptodate(page); | ||
1492 | |||
1476 | if (f2fs_readpage(sbi, page, addr, READ_SYNC)) | 1493 | if (f2fs_readpage(sbi, page, addr, READ_SYNC)) |
1477 | goto out; | 1494 | goto out; |
1478 | 1495 | ||
1496 | lock_page(page); | ||
1479 | rn = (struct f2fs_node *)page_address(page); | 1497 | rn = (struct f2fs_node *)page_address(page); |
1480 | sum_entry->nid = rn->footer.nid; | 1498 | sum_entry->nid = rn->footer.nid; |
1481 | sum_entry->version = 0; | 1499 | sum_entry->version = 0; |
1482 | sum_entry->ofs_in_node = 0; | 1500 | sum_entry->ofs_in_node = 0; |
1483 | addr++; | 1501 | addr++; |
1484 | |||
1485 | /* | ||
1486 | * In order to read next node page, | ||
1487 | * we must clear PageUptodate flag. | ||
1488 | */ | ||
1489 | ClearPageUptodate(page); | ||
1490 | } | 1502 | } |
1491 | out: | ||
1492 | unlock_page(page); | 1503 | unlock_page(page); |
1504 | out: | ||
1493 | __free_pages(page, 0); | 1505 | __free_pages(page, 0); |
1494 | return 0; | 1506 | return 0; |
1495 | } | 1507 | } |