diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 22:11:44 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 22:11:44 -0400 |
commit | 64b2d1fbbfda07765dae3f601862796a61b2c451 (patch) | |
tree | 67947ede8fc007a9f0925e697a302a02bd087032 /fs/f2fs/node.c | |
parent | b1cce8032f6abe900b078d24f3c3938726528f97 (diff) | |
parent | 9ab701349247368f9d57a993b95a5bb05bb37e10 (diff) |
Merge tag 'for-f2fs-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs
Pull f2fs updates from Jaegeuk Kim:
"In this round, there is no special interesting feature, but we've
investigated a couple of tuning points with respect to the I/O flow.
Several major bug fixes and a bunch of clean-ups also have been made.
This patch-set includes the following major enhancement patches:
- enhance wait_on_page_writeback
- support SEEK_DATA and SEEK_HOLE
- enhance readahead flows
- enhance IO flushes
- support fiemap
- add some tracepoints
The other bug fixes are as follows:
- fix to support a large volume > 2TB correctly
- recovery bug fix wrt fallocated space
- fix recursive lock on xattr operations
- fix some cases on the remount flow
And, there are a bunch of cleanups"
* tag 'for-f2fs-3.16' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs: (52 commits)
f2fs: support f2fs_fiemap
f2fs: avoid not to call remove_dirty_inode
f2fs: recover fallocated space
f2fs: fix to recover data written by dio
f2fs: large volume support
f2fs: avoid crash when trace f2fs_submit_page_mbio event in ra_sum_pages
f2fs: avoid overflow when large directory feathure is enabled
f2fs: fix recursive lock by f2fs_setxattr
MAINTAINERS: add a co-maintainer from samsung for F2FS
MAINTAINERS: change the email address for f2fs
f2fs: use inode_init_owner() to simplify codes
f2fs: avoid to use slab memory in f2fs_issue_flush for efficiency
f2fs: add a tracepoint for f2fs_read_data_page
f2fs: add a tracepoint for f2fs_write_{meta,node,data}_pages
f2fs: add a tracepoint for f2fs_write_{meta,node,data}_page
f2fs: add a tracepoint for f2fs_write_end
f2fs: add a tracepoint for f2fs_write_begin
f2fs: fix checkpatch warning
f2fs: deactivate inode page if the inode is evicted
f2fs: decrease the lock granularity during write_begin
...
Diffstat (limited to 'fs/f2fs/node.c')
-rw-r--r-- | fs/f2fs/node.c | 154 |
1 files changed, 84 insertions, 70 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c index 57caa6eaf47b..9dfb9a042fd2 100644 --- a/fs/f2fs/node.c +++ b/fs/f2fs/node.c | |||
@@ -26,20 +26,26 @@ | |||
26 | static struct kmem_cache *nat_entry_slab; | 26 | static struct kmem_cache *nat_entry_slab; |
27 | static struct kmem_cache *free_nid_slab; | 27 | static struct kmem_cache *free_nid_slab; |
28 | 28 | ||
29 | static inline bool available_free_memory(struct f2fs_nm_info *nm_i, int type) | 29 | bool available_free_memory(struct f2fs_sb_info *sbi, int type) |
30 | { | 30 | { |
31 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
31 | struct sysinfo val; | 32 | struct sysinfo val; |
32 | unsigned long mem_size = 0; | 33 | unsigned long mem_size = 0; |
34 | bool res = false; | ||
33 | 35 | ||
34 | si_meminfo(&val); | 36 | si_meminfo(&val); |
35 | if (type == FREE_NIDS) | 37 | /* give 25%, 25%, 50% memory for each components respectively */ |
36 | mem_size = nm_i->fcnt * sizeof(struct free_nid); | 38 | if (type == FREE_NIDS) { |
37 | else if (type == NAT_ENTRIES) | 39 | mem_size = (nm_i->fcnt * sizeof(struct free_nid)) >> 12; |
38 | mem_size += nm_i->nat_cnt * sizeof(struct nat_entry); | 40 | res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 2); |
39 | mem_size >>= 12; | 41 | } else if (type == NAT_ENTRIES) { |
40 | 42 | mem_size = (nm_i->nat_cnt * sizeof(struct nat_entry)) >> 12; | |
41 | /* give 50:50 memory for free nids and nat caches respectively */ | 43 | res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 2); |
42 | return (mem_size < ((val.totalram * nm_i->ram_thresh) >> 11)); | 44 | } else if (type == DIRTY_DENTS) { |
45 | mem_size = get_pages(sbi, F2FS_DIRTY_DENTS); | ||
46 | res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 1); | ||
47 | } | ||
48 | return res; | ||
43 | } | 49 | } |
44 | 50 | ||
45 | static void clear_node_page_dirty(struct page *page) | 51 | static void clear_node_page_dirty(struct page *page) |
@@ -147,6 +153,18 @@ bool fsync_mark_done(struct f2fs_sb_info *sbi, nid_t nid) | |||
147 | return fsync_done; | 153 | return fsync_done; |
148 | } | 154 | } |
149 | 155 | ||
156 | void fsync_mark_clear(struct f2fs_sb_info *sbi, nid_t nid) | ||
157 | { | ||
158 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
159 | struct nat_entry *e; | ||
160 | |||
161 | write_lock(&nm_i->nat_tree_lock); | ||
162 | e = __lookup_nat_cache(nm_i, nid); | ||
163 | if (e) | ||
164 | e->fsync_done = false; | ||
165 | write_unlock(&nm_i->nat_tree_lock); | ||
166 | } | ||
167 | |||
150 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) | 168 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) |
151 | { | 169 | { |
152 | struct nat_entry *new; | 170 | struct nat_entry *new; |
@@ -179,9 +197,7 @@ retry: | |||
179 | write_unlock(&nm_i->nat_tree_lock); | 197 | write_unlock(&nm_i->nat_tree_lock); |
180 | goto retry; | 198 | goto retry; |
181 | } | 199 | } |
182 | nat_set_blkaddr(e, le32_to_cpu(ne->block_addr)); | 200 | node_info_from_raw_nat(&e->ni, ne); |
183 | nat_set_ino(e, le32_to_cpu(ne->ino)); | ||
184 | nat_set_version(e, ne->version); | ||
185 | } | 201 | } |
186 | write_unlock(&nm_i->nat_tree_lock); | 202 | write_unlock(&nm_i->nat_tree_lock); |
187 | } | 203 | } |
@@ -243,7 +259,7 @@ int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) | |||
243 | { | 259 | { |
244 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 260 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
245 | 261 | ||
246 | if (available_free_memory(nm_i, NAT_ENTRIES)) | 262 | if (available_free_memory(sbi, NAT_ENTRIES)) |
247 | return 0; | 263 | return 0; |
248 | 264 | ||
249 | write_lock(&nm_i->nat_tree_lock); | 265 | write_lock(&nm_i->nat_tree_lock); |
@@ -849,8 +865,7 @@ struct page *new_node_page(struct dnode_of_data *dn, | |||
849 | if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))) | 865 | if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))) |
850 | return ERR_PTR(-EPERM); | 866 | return ERR_PTR(-EPERM); |
851 | 867 | ||
852 | page = grab_cache_page_write_begin(NODE_MAPPING(sbi), | 868 | page = grab_cache_page(NODE_MAPPING(sbi), dn->nid); |
853 | dn->nid, AOP_FLAG_NOFS); | ||
854 | if (!page) | 869 | if (!page) |
855 | return ERR_PTR(-ENOMEM); | 870 | return ERR_PTR(-ENOMEM); |
856 | 871 | ||
@@ -867,6 +882,7 @@ struct page *new_node_page(struct dnode_of_data *dn, | |||
867 | new_ni.ino = dn->inode->i_ino; | 882 | new_ni.ino = dn->inode->i_ino; |
868 | set_node_addr(sbi, &new_ni, NEW_ADDR, false); | 883 | set_node_addr(sbi, &new_ni, NEW_ADDR, false); |
869 | 884 | ||
885 | f2fs_wait_on_page_writeback(page, NODE); | ||
870 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); | 886 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); |
871 | set_cold_node(dn->inode, page); | 887 | set_cold_node(dn->inode, page); |
872 | SetPageUptodate(page); | 888 | SetPageUptodate(page); |
@@ -946,8 +962,7 @@ struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) | |||
946 | struct page *page; | 962 | struct page *page; |
947 | int err; | 963 | int err; |
948 | repeat: | 964 | repeat: |
949 | page = grab_cache_page_write_begin(NODE_MAPPING(sbi), | 965 | page = grab_cache_page(NODE_MAPPING(sbi), nid); |
950 | nid, AOP_FLAG_NOFS); | ||
951 | if (!page) | 966 | if (!page) |
952 | return ERR_PTR(-ENOMEM); | 967 | return ERR_PTR(-ENOMEM); |
953 | 968 | ||
@@ -1194,6 +1209,8 @@ static int f2fs_write_node_page(struct page *page, | |||
1194 | .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, | 1209 | .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, |
1195 | }; | 1210 | }; |
1196 | 1211 | ||
1212 | trace_f2fs_writepage(page, NODE); | ||
1213 | |||
1197 | if (unlikely(sbi->por_doing)) | 1214 | if (unlikely(sbi->por_doing)) |
1198 | goto redirty_out; | 1215 | goto redirty_out; |
1199 | 1216 | ||
@@ -1225,10 +1242,7 @@ static int f2fs_write_node_page(struct page *page, | |||
1225 | return 0; | 1242 | return 0; |
1226 | 1243 | ||
1227 | redirty_out: | 1244 | redirty_out: |
1228 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1245 | redirty_page_for_writepage(wbc, page); |
1229 | wbc->pages_skipped++; | ||
1230 | account_page_redirty(page); | ||
1231 | set_page_dirty(page); | ||
1232 | return AOP_WRITEPAGE_ACTIVATE; | 1246 | return AOP_WRITEPAGE_ACTIVATE; |
1233 | } | 1247 | } |
1234 | 1248 | ||
@@ -1238,6 +1252,8 @@ static int f2fs_write_node_pages(struct address_space *mapping, | |||
1238 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 1252 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
1239 | long diff; | 1253 | long diff; |
1240 | 1254 | ||
1255 | trace_f2fs_writepages(mapping->host, wbc, NODE); | ||
1256 | |||
1241 | /* balancing f2fs's metadata in background */ | 1257 | /* balancing f2fs's metadata in background */ |
1242 | f2fs_balance_fs_bg(sbi); | 1258 | f2fs_balance_fs_bg(sbi); |
1243 | 1259 | ||
@@ -1313,13 +1329,14 @@ static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i, | |||
1313 | radix_tree_delete(&nm_i->free_nid_root, i->nid); | 1329 | radix_tree_delete(&nm_i->free_nid_root, i->nid); |
1314 | } | 1330 | } |
1315 | 1331 | ||
1316 | static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build) | 1332 | static int add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) |
1317 | { | 1333 | { |
1334 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
1318 | struct free_nid *i; | 1335 | struct free_nid *i; |
1319 | struct nat_entry *ne; | 1336 | struct nat_entry *ne; |
1320 | bool allocated = false; | 1337 | bool allocated = false; |
1321 | 1338 | ||
1322 | if (!available_free_memory(nm_i, FREE_NIDS)) | 1339 | if (!available_free_memory(sbi, FREE_NIDS)) |
1323 | return -1; | 1340 | return -1; |
1324 | 1341 | ||
1325 | /* 0 nid should not be used */ | 1342 | /* 0 nid should not be used */ |
@@ -1372,9 +1389,10 @@ static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) | |||
1372 | kmem_cache_free(free_nid_slab, i); | 1389 | kmem_cache_free(free_nid_slab, i); |
1373 | } | 1390 | } |
1374 | 1391 | ||
1375 | static void scan_nat_page(struct f2fs_nm_info *nm_i, | 1392 | static void scan_nat_page(struct f2fs_sb_info *sbi, |
1376 | struct page *nat_page, nid_t start_nid) | 1393 | struct page *nat_page, nid_t start_nid) |
1377 | { | 1394 | { |
1395 | struct f2fs_nm_info *nm_i = NM_I(sbi); | ||
1378 | struct f2fs_nat_block *nat_blk = page_address(nat_page); | 1396 | struct f2fs_nat_block *nat_blk = page_address(nat_page); |
1379 | block_t blk_addr; | 1397 | block_t blk_addr; |
1380 | int i; | 1398 | int i; |
@@ -1389,7 +1407,7 @@ static void scan_nat_page(struct f2fs_nm_info *nm_i, | |||
1389 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); | 1407 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); |
1390 | f2fs_bug_on(blk_addr == NEW_ADDR); | 1408 | f2fs_bug_on(blk_addr == NEW_ADDR); |
1391 | if (blk_addr == NULL_ADDR) { | 1409 | if (blk_addr == NULL_ADDR) { |
1392 | if (add_free_nid(nm_i, start_nid, true) < 0) | 1410 | if (add_free_nid(sbi, start_nid, true) < 0) |
1393 | break; | 1411 | break; |
1394 | } | 1412 | } |
1395 | } | 1413 | } |
@@ -1413,7 +1431,7 @@ static void build_free_nids(struct f2fs_sb_info *sbi) | |||
1413 | while (1) { | 1431 | while (1) { |
1414 | struct page *page = get_current_nat_page(sbi, nid); | 1432 | struct page *page = get_current_nat_page(sbi, nid); |
1415 | 1433 | ||
1416 | scan_nat_page(nm_i, page, nid); | 1434 | scan_nat_page(sbi, page, nid); |
1417 | f2fs_put_page(page, 1); | 1435 | f2fs_put_page(page, 1); |
1418 | 1436 | ||
1419 | nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); | 1437 | nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); |
@@ -1433,7 +1451,7 @@ static void build_free_nids(struct f2fs_sb_info *sbi) | |||
1433 | block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr); | 1451 | block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr); |
1434 | nid = le32_to_cpu(nid_in_journal(sum, i)); | 1452 | nid = le32_to_cpu(nid_in_journal(sum, i)); |
1435 | if (addr == NULL_ADDR) | 1453 | if (addr == NULL_ADDR) |
1436 | add_free_nid(nm_i, nid, true); | 1454 | add_free_nid(sbi, nid, true); |
1437 | else | 1455 | else |
1438 | remove_free_nid(nm_i, nid); | 1456 | remove_free_nid(nm_i, nid); |
1439 | } | 1457 | } |
@@ -1450,7 +1468,7 @@ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) | |||
1450 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1468 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1451 | struct free_nid *i = NULL; | 1469 | struct free_nid *i = NULL; |
1452 | retry: | 1470 | retry: |
1453 | if (unlikely(sbi->total_valid_node_count + 1 >= nm_i->max_nid)) | 1471 | if (unlikely(sbi->total_valid_node_count + 1 > nm_i->available_nids)) |
1454 | return false; | 1472 | return false; |
1455 | 1473 | ||
1456 | spin_lock(&nm_i->free_nid_list_lock); | 1474 | spin_lock(&nm_i->free_nid_list_lock); |
@@ -1510,7 +1528,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) | |||
1510 | spin_lock(&nm_i->free_nid_list_lock); | 1528 | spin_lock(&nm_i->free_nid_list_lock); |
1511 | i = __lookup_free_nid_list(nm_i, nid); | 1529 | i = __lookup_free_nid_list(nm_i, nid); |
1512 | f2fs_bug_on(!i || i->state != NID_ALLOC); | 1530 | f2fs_bug_on(!i || i->state != NID_ALLOC); |
1513 | if (!available_free_memory(nm_i, FREE_NIDS)) { | 1531 | if (!available_free_memory(sbi, FREE_NIDS)) { |
1514 | __del_from_free_nid_list(nm_i, i); | 1532 | __del_from_free_nid_list(nm_i, i); |
1515 | need_free = true; | 1533 | need_free = true; |
1516 | } else { | 1534 | } else { |
@@ -1532,7 +1550,7 @@ void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, | |||
1532 | clear_node_page_dirty(page); | 1550 | clear_node_page_dirty(page); |
1533 | } | 1551 | } |
1534 | 1552 | ||
1535 | void recover_inline_xattr(struct inode *inode, struct page *page) | 1553 | static void recover_inline_xattr(struct inode *inode, struct page *page) |
1536 | { | 1554 | { |
1537 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 1555 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
1538 | void *src_addr, *dst_addr; | 1556 | void *src_addr, *dst_addr; |
@@ -1557,6 +1575,7 @@ void recover_inline_xattr(struct inode *inode, struct page *page) | |||
1557 | src_addr = inline_xattr_addr(page); | 1575 | src_addr = inline_xattr_addr(page); |
1558 | inline_size = inline_xattr_size(inode); | 1576 | inline_size = inline_xattr_size(inode); |
1559 | 1577 | ||
1578 | f2fs_wait_on_page_writeback(ipage, NODE); | ||
1560 | memcpy(dst_addr, src_addr, inline_size); | 1579 | memcpy(dst_addr, src_addr, inline_size); |
1561 | 1580 | ||
1562 | update_inode(inode, ipage); | 1581 | update_inode(inode, ipage); |
@@ -1612,6 +1631,11 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1612 | struct node_info old_ni, new_ni; | 1631 | struct node_info old_ni, new_ni; |
1613 | struct page *ipage; | 1632 | struct page *ipage; |
1614 | 1633 | ||
1634 | get_node_info(sbi, ino, &old_ni); | ||
1635 | |||
1636 | if (unlikely(old_ni.blk_addr != NULL_ADDR)) | ||
1637 | return -EINVAL; | ||
1638 | |||
1615 | ipage = grab_cache_page(NODE_MAPPING(sbi), ino); | 1639 | ipage = grab_cache_page(NODE_MAPPING(sbi), ino); |
1616 | if (!ipage) | 1640 | if (!ipage) |
1617 | return -ENOMEM; | 1641 | return -ENOMEM; |
@@ -1619,7 +1643,6 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1619 | /* Should not use this inode from free nid list */ | 1643 | /* Should not use this inode from free nid list */ |
1620 | remove_free_nid(NM_I(sbi), ino); | 1644 | remove_free_nid(NM_I(sbi), ino); |
1621 | 1645 | ||
1622 | get_node_info(sbi, ino, &old_ni); | ||
1623 | SetPageUptodate(ipage); | 1646 | SetPageUptodate(ipage); |
1624 | fill_node_footer(ipage, ino, ino, 0, true); | 1647 | fill_node_footer(ipage, ino, ino, 0, true); |
1625 | 1648 | ||
@@ -1645,35 +1668,29 @@ int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | |||
1645 | 1668 | ||
1646 | /* | 1669 | /* |
1647 | * ra_sum_pages() merge contiguous pages into one bio and submit. | 1670 | * ra_sum_pages() merge contiguous pages into one bio and submit. |
1648 | * these pre-readed pages are linked in pages list. | 1671 | * these pre-readed pages are alloced in bd_inode's mapping tree. |
1649 | */ | 1672 | */ |
1650 | static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages, | 1673 | static int ra_sum_pages(struct f2fs_sb_info *sbi, struct page **pages, |
1651 | int start, int nrpages) | 1674 | int start, int nrpages) |
1652 | { | 1675 | { |
1653 | struct page *page; | 1676 | struct inode *inode = sbi->sb->s_bdev->bd_inode; |
1654 | int page_idx = start; | 1677 | struct address_space *mapping = inode->i_mapping; |
1678 | int i, page_idx = start; | ||
1655 | struct f2fs_io_info fio = { | 1679 | struct f2fs_io_info fio = { |
1656 | .type = META, | 1680 | .type = META, |
1657 | .rw = READ_SYNC | REQ_META | REQ_PRIO | 1681 | .rw = READ_SYNC | REQ_META | REQ_PRIO |
1658 | }; | 1682 | }; |
1659 | 1683 | ||
1660 | for (; page_idx < start + nrpages; page_idx++) { | 1684 | for (i = 0; page_idx < start + nrpages; page_idx++, i++) { |
1661 | /* alloc temporal page for read node summary info*/ | 1685 | /* alloc page in bd_inode for reading node summary info */ |
1662 | page = alloc_page(GFP_F2FS_ZERO); | 1686 | pages[i] = grab_cache_page(mapping, page_idx); |
1663 | if (!page) | 1687 | if (!pages[i]) |
1664 | break; | 1688 | break; |
1665 | 1689 | f2fs_submit_page_mbio(sbi, pages[i], page_idx, &fio); | |
1666 | lock_page(page); | ||
1667 | page->index = page_idx; | ||
1668 | list_add_tail(&page->lru, pages); | ||
1669 | } | 1690 | } |
1670 | 1691 | ||
1671 | list_for_each_entry(page, pages, lru) | ||
1672 | f2fs_submit_page_mbio(sbi, page, page->index, &fio); | ||
1673 | |||
1674 | f2fs_submit_merged_bio(sbi, META, READ); | 1692 | f2fs_submit_merged_bio(sbi, META, READ); |
1675 | 1693 | return i; | |
1676 | return page_idx - start; | ||
1677 | } | 1694 | } |
1678 | 1695 | ||
1679 | int restore_node_summary(struct f2fs_sb_info *sbi, | 1696 | int restore_node_summary(struct f2fs_sb_info *sbi, |
@@ -1681,11 +1698,11 @@ int restore_node_summary(struct f2fs_sb_info *sbi, | |||
1681 | { | 1698 | { |
1682 | struct f2fs_node *rn; | 1699 | struct f2fs_node *rn; |
1683 | struct f2fs_summary *sum_entry; | 1700 | struct f2fs_summary *sum_entry; |
1684 | struct page *page, *tmp; | 1701 | struct inode *inode = sbi->sb->s_bdev->bd_inode; |
1685 | block_t addr; | 1702 | block_t addr; |
1686 | int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); | 1703 | int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
1687 | int i, last_offset, nrpages, err = 0; | 1704 | struct page *pages[bio_blocks]; |
1688 | LIST_HEAD(page_list); | 1705 | int i, idx, last_offset, nrpages, err = 0; |
1689 | 1706 | ||
1690 | /* scan the node segment */ | 1707 | /* scan the node segment */ |
1691 | last_offset = sbi->blocks_per_seg; | 1708 | last_offset = sbi->blocks_per_seg; |
@@ -1696,29 +1713,31 @@ int restore_node_summary(struct f2fs_sb_info *sbi, | |||
1696 | nrpages = min(last_offset - i, bio_blocks); | 1713 | nrpages = min(last_offset - i, bio_blocks); |
1697 | 1714 | ||
1698 | /* read ahead node pages */ | 1715 | /* read ahead node pages */ |
1699 | nrpages = ra_sum_pages(sbi, &page_list, addr, nrpages); | 1716 | nrpages = ra_sum_pages(sbi, pages, addr, nrpages); |
1700 | if (!nrpages) | 1717 | if (!nrpages) |
1701 | return -ENOMEM; | 1718 | return -ENOMEM; |
1702 | 1719 | ||
1703 | list_for_each_entry_safe(page, tmp, &page_list, lru) { | 1720 | for (idx = 0; idx < nrpages; idx++) { |
1704 | if (err) | 1721 | if (err) |
1705 | goto skip; | 1722 | goto skip; |
1706 | 1723 | ||
1707 | lock_page(page); | 1724 | lock_page(pages[idx]); |
1708 | if (unlikely(!PageUptodate(page))) { | 1725 | if (unlikely(!PageUptodate(pages[idx]))) { |
1709 | err = -EIO; | 1726 | err = -EIO; |
1710 | } else { | 1727 | } else { |
1711 | rn = F2FS_NODE(page); | 1728 | rn = F2FS_NODE(pages[idx]); |
1712 | sum_entry->nid = rn->footer.nid; | 1729 | sum_entry->nid = rn->footer.nid; |
1713 | sum_entry->version = 0; | 1730 | sum_entry->version = 0; |
1714 | sum_entry->ofs_in_node = 0; | 1731 | sum_entry->ofs_in_node = 0; |
1715 | sum_entry++; | 1732 | sum_entry++; |
1716 | } | 1733 | } |
1717 | unlock_page(page); | 1734 | unlock_page(pages[idx]); |
1718 | skip: | 1735 | skip: |
1719 | list_del(&page->lru); | 1736 | page_cache_release(pages[idx]); |
1720 | __free_pages(page, 0); | ||
1721 | } | 1737 | } |
1738 | |||
1739 | invalidate_mapping_pages(inode->i_mapping, addr, | ||
1740 | addr + nrpages); | ||
1722 | } | 1741 | } |
1723 | return err; | 1742 | return err; |
1724 | } | 1743 | } |
@@ -1756,9 +1775,7 @@ retry: | |||
1756 | write_unlock(&nm_i->nat_tree_lock); | 1775 | write_unlock(&nm_i->nat_tree_lock); |
1757 | goto retry; | 1776 | goto retry; |
1758 | } | 1777 | } |
1759 | nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr)); | 1778 | node_info_from_raw_nat(&ne->ni, &raw_ne); |
1760 | nat_set_ino(ne, le32_to_cpu(raw_ne.ino)); | ||
1761 | nat_set_version(ne, raw_ne.version); | ||
1762 | __set_nat_cache_dirty(nm_i, ne); | 1779 | __set_nat_cache_dirty(nm_i, ne); |
1763 | write_unlock(&nm_i->nat_tree_lock); | 1780 | write_unlock(&nm_i->nat_tree_lock); |
1764 | } | 1781 | } |
@@ -1791,7 +1808,6 @@ void flush_nat_entries(struct f2fs_sb_info *sbi) | |||
1791 | nid_t nid; | 1808 | nid_t nid; |
1792 | struct f2fs_nat_entry raw_ne; | 1809 | struct f2fs_nat_entry raw_ne; |
1793 | int offset = -1; | 1810 | int offset = -1; |
1794 | block_t new_blkaddr; | ||
1795 | 1811 | ||
1796 | if (nat_get_blkaddr(ne) == NEW_ADDR) | 1812 | if (nat_get_blkaddr(ne) == NEW_ADDR) |
1797 | continue; | 1813 | continue; |
@@ -1827,11 +1843,7 @@ to_nat_page: | |||
1827 | f2fs_bug_on(!nat_blk); | 1843 | f2fs_bug_on(!nat_blk); |
1828 | raw_ne = nat_blk->entries[nid - start_nid]; | 1844 | raw_ne = nat_blk->entries[nid - start_nid]; |
1829 | flush_now: | 1845 | flush_now: |
1830 | new_blkaddr = nat_get_blkaddr(ne); | 1846 | raw_nat_from_node_info(&raw_ne, &ne->ni); |
1831 | |||
1832 | raw_ne.ino = cpu_to_le32(nat_get_ino(ne)); | ||
1833 | raw_ne.block_addr = cpu_to_le32(new_blkaddr); | ||
1834 | raw_ne.version = nat_get_version(ne); | ||
1835 | 1847 | ||
1836 | if (offset < 0) { | 1848 | if (offset < 0) { |
1837 | nat_blk->entries[nid - start_nid] = raw_ne; | 1849 | nat_blk->entries[nid - start_nid] = raw_ne; |
@@ -1841,7 +1853,7 @@ flush_now: | |||
1841 | } | 1853 | } |
1842 | 1854 | ||
1843 | if (nat_get_blkaddr(ne) == NULL_ADDR && | 1855 | if (nat_get_blkaddr(ne) == NULL_ADDR && |
1844 | add_free_nid(NM_I(sbi), nid, false) <= 0) { | 1856 | add_free_nid(sbi, nid, false) <= 0) { |
1845 | write_lock(&nm_i->nat_tree_lock); | 1857 | write_lock(&nm_i->nat_tree_lock); |
1846 | __del_from_nat_cache(nm_i, ne); | 1858 | __del_from_nat_cache(nm_i, ne); |
1847 | write_unlock(&nm_i->nat_tree_lock); | 1859 | write_unlock(&nm_i->nat_tree_lock); |
@@ -1869,8 +1881,10 @@ static int init_node_manager(struct f2fs_sb_info *sbi) | |||
1869 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; | 1881 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; |
1870 | nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); | 1882 | nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); |
1871 | 1883 | ||
1884 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; | ||
1885 | |||
1872 | /* not used nids: 0, node, meta, (and root counted as valid node) */ | 1886 | /* not used nids: 0, node, meta, (and root counted as valid node) */ |
1873 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks - 3; | 1887 | nm_i->available_nids = nm_i->max_nid - 3; |
1874 | nm_i->fcnt = 0; | 1888 | nm_i->fcnt = 0; |
1875 | nm_i->nat_cnt = 0; | 1889 | nm_i->nat_cnt = 0; |
1876 | nm_i->ram_thresh = DEF_RAM_THRESHOLD; | 1890 | nm_i->ram_thresh = DEF_RAM_THRESHOLD; |