]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/f2fs/node.c
f2fs: increase pages_skipped when skipping writepages
[karo-tx-linux.git] / fs / f2fs / node.c
index 8c1411060e7ec513b8c7fff0ce1a9493cea75376..7cc146bcbfed1df06fc6c481e4cdecdb5a4f401e 100644 (file)
@@ -836,7 +836,7 @@ struct page *new_node_page(struct dnode_of_data *dn,
        SetPageUptodate(page);
        set_page_dirty(page);
 
-       if (ofs == XATTR_NODE_OFFSET)
+       if (f2fs_has_xattr_block(ofs))
                F2FS_I(dn->inode)->i_xattr_nid = dn->nid;
 
        dn->node_page = page;
@@ -1198,12 +1198,6 @@ redirty_out:
        return AOP_WRITEPAGE_ACTIVATE;
 }
 
-/*
- * It is very important to gather dirty pages and write at once, so that we can
- * submit a big bio without interfering other data writes.
- * Be default, 512 pages (2MB) * 3 node types, is more reasonable.
- */
-#define COLLECT_DIRTY_NODES    1536
 static int f2fs_write_node_pages(struct address_space *mapping,
                            struct writeback_control *wbc)
 {
@@ -1214,8 +1208,8 @@ static int f2fs_write_node_pages(struct address_space *mapping,
        f2fs_balance_fs_bg(sbi);
 
        /* collect a number of dirty node pages and write together */
-       if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
-               return 0;
+       if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE))
+               goto skip_write;
 
        /* if mounting is failed, skip writing node pages */
        wbc->nr_to_write = 3 * max_hw_blocks(sbi);
@@ -1224,6 +1218,10 @@ static int f2fs_write_node_pages(struct address_space *mapping,
        wbc->nr_to_write = nr_to_write - (3 * max_hw_blocks(sbi) -
                                                wbc->nr_to_write);
        return 0;
+
+skip_write:
+       wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES);
+       return 0;
 }
 
 static int f2fs_set_node_page_dirty(struct page *page)
@@ -1493,6 +1491,37 @@ void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
        clear_node_page_dirty(page);
 }
 
+void recover_inline_xattr(struct inode *inode, struct page *page)
+{
+       struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
+       void *src_addr, *dst_addr;
+       size_t inline_size;
+       struct page *ipage;
+       struct f2fs_inode *ri;
+
+       if (!f2fs_has_inline_xattr(inode))
+               return;
+
+       if (!IS_INODE(page))
+               return;
+
+       ri = F2FS_INODE(page);
+       if (!(ri->i_inline & F2FS_INLINE_XATTR))
+               return;
+
+       ipage = get_node_page(sbi, inode->i_ino);
+       f2fs_bug_on(IS_ERR(ipage));
+
+       dst_addr = inline_xattr_addr(ipage);
+       src_addr = inline_xattr_addr(page);
+       inline_size = inline_xattr_size(inode);
+
+       memcpy(dst_addr, src_addr, inline_size);
+
+       update_inode(inode, ipage);
+       f2fs_put_page(ipage, 1);
+}
+
 bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
 {
        struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
@@ -1500,7 +1529,9 @@ bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
        nid_t new_xnid = nid_of_node(page);
        struct node_info ni;
 
-       if (ofs_of_node(page) != XATTR_NODE_OFFSET)
+       recover_inline_xattr(inode, page);
+
+       if (!f2fs_has_xattr_block(ofs_of_node(page)))
                return false;
 
        /* 1: invalidate the previous xattr nid */
@@ -1588,15 +1619,8 @@ static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages,
        for (; page_idx < start + nrpages; page_idx++) {
                /* alloc temporal page for read node summary info*/
                page = alloc_page(GFP_F2FS_ZERO);
-               if (!page) {
-                       struct page *tmp;
-                       list_for_each_entry_safe(page, tmp, pages, lru) {
-                               list_del(&page->lru);
-                               unlock_page(page);
-                               __free_pages(page, 0);
-                       }
-                       return -ENOMEM;
-               }
+               if (!page)
+                       break;
 
                lock_page(page);
                page->index = page_idx;
@@ -1607,7 +1631,8 @@ static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages,
                f2fs_submit_page_mbio(sbi, page, page->index, &fio);
 
        f2fs_submit_merged_bio(sbi, META, READ);
-       return 0;
+
+       return page_idx - start;
 }
 
 int restore_node_summary(struct f2fs_sb_info *sbi,
@@ -1626,15 +1651,17 @@ int restore_node_summary(struct f2fs_sb_info *sbi,
        addr = START_BLOCK(sbi, segno);
        sum_entry = &sum->entries[0];
 
-       for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
+       for (i = 0; !err && i < last_offset; i += nrpages, addr += nrpages) {
                nrpages = min(last_offset - i, bio_blocks);
 
                /* read ahead node pages */
-               err = ra_sum_pages(sbi, &page_list, addr, nrpages);
-               if (err)
-                       return err;
+               nrpages = ra_sum_pages(sbi, &page_list, addr, nrpages);
+               if (!nrpages)
+                       return -ENOMEM;
 
                list_for_each_entry_safe(page, tmp, &page_list, lru) {
+                       if (err)
+                               goto skip;
 
                        lock_page(page);
                        if (unlikely(!PageUptodate(page))) {
@@ -1646,9 +1673,9 @@ int restore_node_summary(struct f2fs_sb_info *sbi,
                                sum_entry->ofs_in_node = 0;
                                sum_entry++;
                        }
-
-                       list_del(&page->lru);
                        unlock_page(page);
+skip:
+                       list_del(&page->lru);
                        __free_pages(page, 0);
                }
        }
@@ -1875,11 +1902,9 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
        while ((found = __gang_lookup_nat_cache(nm_i,
                                        nid, NATVEC_SIZE, natvec))) {
                unsigned idx;
-               for (idx = 0; idx < found; idx++) {
-                       struct nat_entry *e = natvec[idx];
-                       nid = nat_get_nid(e) + 1;
-                       __del_from_nat_cache(nm_i, e);
-               }
+               nid = nat_get_nid(natvec[found - 1]) + 1;
+               for (idx = 0; idx < found; idx++)
+                       __del_from_nat_cache(nm_i, natvec[idx]);
        }
        f2fs_bug_on(nm_i->nat_cnt);
        write_unlock(&nm_i->nat_tree_lock);
@@ -1892,12 +1917,12 @@ void destroy_node_manager(struct f2fs_sb_info *sbi)
 int __init create_node_manager_caches(void)
 {
        nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
-                       sizeof(struct nat_entry), NULL);
+                       sizeof(struct nat_entry));
        if (!nat_entry_slab)
                return -ENOMEM;
 
        free_nid_slab = f2fs_kmem_cache_create("free_nid",
-                       sizeof(struct free_nid), NULL);
+                       sizeof(struct free_nid));
        if (!free_nid_slab) {
                kmem_cache_destroy(nat_entry_slab);
                return -ENOMEM;