2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* fs/f2fs/node.c
|
|
|
|
*
|
|
|
|
* Copyright (c) 2012 Samsung Electronics Co., Ltd.
|
|
|
|
* http://www.samsung.com/
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*/
|
|
|
|
#include <linux/fs.h>
|
|
|
|
#include <linux/f2fs_fs.h>
|
|
|
|
#include <linux/mpage.h>
|
|
|
|
#include <linux/backing-dev.h>
|
|
|
|
#include <linux/blkdev.h>
|
|
|
|
#include <linux/pagevec.h>
|
|
|
|
#include <linux/swap.h>
|
|
|
|
|
|
|
|
#include "f2fs.h"
|
|
|
|
#include "node.h"
|
|
|
|
#include "segment.h"
|
2013-04-19 16:28:52 +00:00
|
|
|
#include <trace/events/f2fs.h>
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
static struct kmem_cache *nat_entry_slab;
|
|
|
|
static struct kmem_cache *free_nid_slab;
|
|
|
|
|
|
|
|
static void clear_node_page_dirty(struct page *page)
|
|
|
|
{
|
|
|
|
struct address_space *mapping = page->mapping;
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
|
|
|
|
unsigned int long flags;
|
|
|
|
|
|
|
|
if (PageDirty(page)) {
|
|
|
|
spin_lock_irqsave(&mapping->tree_lock, flags);
|
|
|
|
radix_tree_tag_clear(&mapping->page_tree,
|
|
|
|
page_index(page),
|
|
|
|
PAGECACHE_TAG_DIRTY);
|
|
|
|
spin_unlock_irqrestore(&mapping->tree_lock, flags);
|
|
|
|
|
|
|
|
clear_page_dirty_for_io(page);
|
|
|
|
dec_page_count(sbi, F2FS_DIRTY_NODES);
|
|
|
|
}
|
|
|
|
ClearPageUptodate(page);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
|
|
|
pgoff_t index = current_nat_addr(sbi, nid);
|
|
|
|
return get_meta_page(sbi, index);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
|
|
|
struct page *src_page;
|
|
|
|
struct page *dst_page;
|
|
|
|
pgoff_t src_off;
|
|
|
|
pgoff_t dst_off;
|
|
|
|
void *src_addr;
|
|
|
|
void *dst_addr;
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
|
|
|
|
src_off = current_nat_addr(sbi, nid);
|
|
|
|
dst_off = next_nat_addr(sbi, src_off);
|
|
|
|
|
|
|
|
/* get current nat block page with lock */
|
|
|
|
src_page = get_meta_page(sbi, src_off);
|
|
|
|
|
|
|
|
/* Dirty src_page means that it is already the new target NAT page. */
|
|
|
|
if (PageDirty(src_page))
|
|
|
|
return src_page;
|
|
|
|
|
|
|
|
dst_page = grab_meta_page(sbi, dst_off);
|
|
|
|
|
|
|
|
src_addr = page_address(src_page);
|
|
|
|
dst_addr = page_address(dst_page);
|
|
|
|
memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE);
|
|
|
|
set_page_dirty(dst_page);
|
|
|
|
f2fs_put_page(src_page, 1);
|
|
|
|
|
|
|
|
set_to_next_nat(nm_i, nid);
|
|
|
|
|
|
|
|
return dst_page;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n)
|
|
|
|
{
|
|
|
|
return radix_tree_lookup(&nm_i->nat_root, n);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i,
|
|
|
|
nid_t start, unsigned int nr, struct nat_entry **ep)
|
|
|
|
{
|
|
|
|
return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e)
|
|
|
|
{
|
|
|
|
list_del(&e->list);
|
|
|
|
radix_tree_delete(&nm_i->nat_root, nat_get_nid(e));
|
|
|
|
nm_i->nat_cnt--;
|
|
|
|
kmem_cache_free(nat_entry_slab, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct nat_entry *e;
|
|
|
|
int is_cp = 1;
|
|
|
|
|
|
|
|
read_lock(&nm_i->nat_tree_lock);
|
|
|
|
e = __lookup_nat_cache(nm_i, nid);
|
|
|
|
if (e && !e->checkpointed)
|
|
|
|
is_cp = 0;
|
|
|
|
read_unlock(&nm_i->nat_tree_lock);
|
|
|
|
return is_cp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid)
|
|
|
|
{
|
|
|
|
struct nat_entry *new;
|
|
|
|
|
|
|
|
new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC);
|
|
|
|
if (!new)
|
|
|
|
return NULL;
|
|
|
|
if (radix_tree_insert(&nm_i->nat_root, nid, new)) {
|
|
|
|
kmem_cache_free(nat_entry_slab, new);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
memset(new, 0, sizeof(struct nat_entry));
|
|
|
|
nat_set_nid(new, nid);
|
|
|
|
list_add_tail(&new->list, &nm_i->nat_entries);
|
|
|
|
nm_i->nat_cnt++;
|
|
|
|
return new;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid,
|
|
|
|
struct f2fs_nat_entry *ne)
|
|
|
|
{
|
|
|
|
struct nat_entry *e;
|
|
|
|
retry:
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
e = __lookup_nat_cache(nm_i, nid);
|
|
|
|
if (!e) {
|
|
|
|
e = grab_nat_entry(nm_i, nid);
|
|
|
|
if (!e) {
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
nat_set_blkaddr(e, le32_to_cpu(ne->block_addr));
|
|
|
|
nat_set_ino(e, le32_to_cpu(ne->ino));
|
|
|
|
nat_set_version(e, ne->version);
|
|
|
|
e->checkpointed = true;
|
|
|
|
}
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
|
|
|
|
block_t new_blkaddr)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct nat_entry *e;
|
|
|
|
retry:
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
e = __lookup_nat_cache(nm_i, ni->nid);
|
|
|
|
if (!e) {
|
|
|
|
e = grab_nat_entry(nm_i, ni->nid);
|
|
|
|
if (!e) {
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
e->ni = *ni;
|
|
|
|
e->checkpointed = true;
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(ni->blk_addr == NEW_ADDR);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
} else if (new_blkaddr == NEW_ADDR) {
|
|
|
|
/*
|
|
|
|
* when nid is reallocated,
|
|
|
|
* previous nat entry can be remained in nat cache.
|
|
|
|
* So, reinitialize it with new information.
|
|
|
|
*/
|
|
|
|
e->ni = *ni;
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(ni->blk_addr != NULL_ADDR);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (new_blkaddr == NEW_ADDR)
|
|
|
|
e->checkpointed = false;
|
|
|
|
|
|
|
|
/* sanity check */
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nat_get_blkaddr(e) != ni->blk_addr);
|
|
|
|
f2fs_bug_on(nat_get_blkaddr(e) == NULL_ADDR &&
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
new_blkaddr == NULL_ADDR);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nat_get_blkaddr(e) == NEW_ADDR &&
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
new_blkaddr == NEW_ADDR);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nat_get_blkaddr(e) != NEW_ADDR &&
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
nat_get_blkaddr(e) != NULL_ADDR &&
|
|
|
|
new_blkaddr == NEW_ADDR);
|
|
|
|
|
|
|
|
/* increament version no as node is removed */
|
|
|
|
if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) {
|
|
|
|
unsigned char version = nat_get_version(e);
|
|
|
|
nat_set_version(e, inc_node_version(version));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* change address */
|
|
|
|
nat_set_blkaddr(e, new_blkaddr);
|
|
|
|
__set_nat_cache_dirty(nm_i, e);
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
}
|
|
|
|
|
2013-10-24 05:19:18 +00:00
|
|
|
int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
|
2013-04-28 11:16:06 +00:00
|
|
|
if (nm_i->nat_cnt <= NM_WOUT_THRESHOLD)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
while (nr_shrink && !list_empty(&nm_i->nat_entries)) {
|
|
|
|
struct nat_entry *ne;
|
|
|
|
ne = list_first_entry(&nm_i->nat_entries,
|
|
|
|
struct nat_entry, list);
|
|
|
|
__del_from_nat_cache(nm_i, ne);
|
|
|
|
nr_shrink--;
|
|
|
|
}
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
return nr_shrink;
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* This function returns always success
|
|
|
|
*/
|
|
|
|
void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
|
|
|
struct f2fs_summary_block *sum = curseg->sum_blk;
|
|
|
|
nid_t start_nid = START_NID(nid);
|
|
|
|
struct f2fs_nat_block *nat_blk;
|
|
|
|
struct page *page = NULL;
|
|
|
|
struct f2fs_nat_entry ne;
|
|
|
|
struct nat_entry *e;
|
|
|
|
int i;
|
|
|
|
|
2012-12-01 01:55:12 +00:00
|
|
|
memset(&ne, 0, sizeof(struct f2fs_nat_entry));
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
ni->nid = nid;
|
|
|
|
|
|
|
|
/* Check nat cache */
|
|
|
|
read_lock(&nm_i->nat_tree_lock);
|
|
|
|
e = __lookup_nat_cache(nm_i, nid);
|
|
|
|
if (e) {
|
|
|
|
ni->ino = nat_get_ino(e);
|
|
|
|
ni->blk_addr = nat_get_blkaddr(e);
|
|
|
|
ni->version = nat_get_version(e);
|
|
|
|
}
|
|
|
|
read_unlock(&nm_i->nat_tree_lock);
|
|
|
|
if (e)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* Check current segment summary */
|
|
|
|
mutex_lock(&curseg->curseg_mutex);
|
|
|
|
i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0);
|
|
|
|
if (i >= 0) {
|
|
|
|
ne = nat_in_journal(sum, i);
|
|
|
|
node_info_from_raw_nat(ni, &ne);
|
|
|
|
}
|
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
|
if (i >= 0)
|
|
|
|
goto cache;
|
|
|
|
|
|
|
|
/* Fill node_info from nat page */
|
|
|
|
page = get_current_nat_page(sbi, start_nid);
|
|
|
|
nat_blk = (struct f2fs_nat_block *)page_address(page);
|
|
|
|
ne = nat_blk->entries[nid - start_nid];
|
|
|
|
node_info_from_raw_nat(ni, &ne);
|
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
cache:
|
|
|
|
/* cache nat entry */
|
|
|
|
cache_nat_entry(NM_I(sbi), nid, &ne);
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* The maximum depth is four.
|
|
|
|
* Offset[0] will have raw inode offset.
|
|
|
|
*/
|
2013-08-12 12:08:03 +00:00
|
|
|
static int get_node_path(struct f2fs_inode_info *fi, long block,
|
|
|
|
int offset[4], unsigned int noffset[4])
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
2013-08-12 12:08:03 +00:00
|
|
|
const long direct_index = ADDRS_PER_INODE(fi);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
const long direct_blks = ADDRS_PER_BLOCK;
|
|
|
|
const long dptrs_per_blk = NIDS_PER_BLOCK;
|
|
|
|
const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK;
|
|
|
|
const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK;
|
|
|
|
int n = 0;
|
|
|
|
int level = 0;
|
|
|
|
|
|
|
|
noffset[0] = 0;
|
|
|
|
|
|
|
|
if (block < direct_index) {
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
goto got;
|
|
|
|
}
|
|
|
|
block -= direct_index;
|
|
|
|
if (block < direct_blks) {
|
|
|
|
offset[n++] = NODE_DIR1_BLOCK;
|
|
|
|
noffset[n] = 1;
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
level = 1;
|
|
|
|
goto got;
|
|
|
|
}
|
|
|
|
block -= direct_blks;
|
|
|
|
if (block < direct_blks) {
|
|
|
|
offset[n++] = NODE_DIR2_BLOCK;
|
|
|
|
noffset[n] = 2;
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
level = 1;
|
|
|
|
goto got;
|
|
|
|
}
|
|
|
|
block -= direct_blks;
|
|
|
|
if (block < indirect_blks) {
|
|
|
|
offset[n++] = NODE_IND1_BLOCK;
|
|
|
|
noffset[n] = 3;
|
|
|
|
offset[n++] = block / direct_blks;
|
|
|
|
noffset[n] = 4 + offset[n - 1];
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block % direct_blks;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
level = 2;
|
|
|
|
goto got;
|
|
|
|
}
|
|
|
|
block -= indirect_blks;
|
|
|
|
if (block < indirect_blks) {
|
|
|
|
offset[n++] = NODE_IND2_BLOCK;
|
|
|
|
noffset[n] = 4 + dptrs_per_blk;
|
|
|
|
offset[n++] = block / direct_blks;
|
|
|
|
noffset[n] = 5 + dptrs_per_blk + offset[n - 1];
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block % direct_blks;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
level = 2;
|
|
|
|
goto got;
|
|
|
|
}
|
|
|
|
block -= indirect_blks;
|
|
|
|
if (block < dindirect_blks) {
|
|
|
|
offset[n++] = NODE_DIND_BLOCK;
|
|
|
|
noffset[n] = 5 + (dptrs_per_blk * 2);
|
|
|
|
offset[n++] = block / indirect_blks;
|
|
|
|
noffset[n] = 6 + (dptrs_per_blk * 2) +
|
|
|
|
offset[n - 1] * (dptrs_per_blk + 1);
|
|
|
|
offset[n++] = (block / direct_blks) % dptrs_per_blk;
|
|
|
|
noffset[n] = 7 + (dptrs_per_blk * 2) +
|
|
|
|
offset[n - 2] * (dptrs_per_blk + 1) +
|
|
|
|
offset[n - 1];
|
2013-03-02 03:41:31 +00:00
|
|
|
offset[n] = block % direct_blks;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
level = 3;
|
|
|
|
goto got;
|
|
|
|
} else {
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
got:
|
|
|
|
return level;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Caller should call f2fs_put_dnode(dn).
|
2013-12-21 10:02:14 +00:00
|
|
|
* Also, it should grab and release a rwsem by calling f2fs_lock_op() and
|
|
|
|
* f2fs_unlock_op() only if ro is not set RDONLY_NODE.
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
* In the case of RDONLY_NODE, we don't need to care about mutex.
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
*/
|
2013-02-26 04:10:46 +00:00
|
|
|
int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct page *npage[4];
|
|
|
|
struct page *parent;
|
|
|
|
int offset[4];
|
|
|
|
unsigned int noffset[4];
|
|
|
|
nid_t nids[4];
|
|
|
|
int level, i;
|
|
|
|
int err = 0;
|
|
|
|
|
2013-08-12 12:08:03 +00:00
|
|
|
level = get_node_path(F2FS_I(dn->inode), index, offset, noffset);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
nids[0] = dn->inode->i_ino;
|
2013-05-20 00:42:28 +00:00
|
|
|
npage[0] = dn->inode_page;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-05-20 00:42:28 +00:00
|
|
|
if (!npage[0]) {
|
|
|
|
npage[0] = get_node_page(sbi, nids[0]);
|
|
|
|
if (IS_ERR(npage[0]))
|
|
|
|
return PTR_ERR(npage[0]);
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
parent = npage[0];
|
2013-02-19 22:47:06 +00:00
|
|
|
if (level != 0)
|
|
|
|
nids[1] = get_nid(parent, offset[0], true);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
dn->inode_page = npage[0];
|
|
|
|
dn->inode_page_locked = true;
|
|
|
|
|
|
|
|
/* get indirect or direct nodes */
|
|
|
|
for (i = 1; i <= level; i++) {
|
|
|
|
bool done = false;
|
|
|
|
|
2013-02-26 04:10:46 +00:00
|
|
|
if (!nids[i] && mode == ALLOC_NODE) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
/* alloc new node */
|
|
|
|
if (!alloc_nid(sbi, &(nids[i]))) {
|
|
|
|
err = -ENOSPC;
|
|
|
|
goto release_pages;
|
|
|
|
}
|
|
|
|
|
|
|
|
dn->nid = nids[i];
|
2013-06-03 10:46:19 +00:00
|
|
|
npage[i] = new_node_page(dn, noffset[i], NULL);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (IS_ERR(npage[i])) {
|
|
|
|
alloc_nid_failed(sbi, nids[i]);
|
|
|
|
err = PTR_ERR(npage[i]);
|
|
|
|
goto release_pages;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_nid(parent, offset[i - 1], nids[i], i == 1);
|
|
|
|
alloc_nid_done(sbi, nids[i]);
|
|
|
|
done = true;
|
2013-02-26 04:10:46 +00:00
|
|
|
} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
npage[i] = get_node_page_ra(parent, offset[i - 1]);
|
|
|
|
if (IS_ERR(npage[i])) {
|
|
|
|
err = PTR_ERR(npage[i]);
|
|
|
|
goto release_pages;
|
|
|
|
}
|
|
|
|
done = true;
|
|
|
|
}
|
|
|
|
if (i == 1) {
|
|
|
|
dn->inode_page_locked = false;
|
|
|
|
unlock_page(parent);
|
|
|
|
} else {
|
|
|
|
f2fs_put_page(parent, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!done) {
|
|
|
|
npage[i] = get_node_page(sbi, nids[i]);
|
|
|
|
if (IS_ERR(npage[i])) {
|
|
|
|
err = PTR_ERR(npage[i]);
|
|
|
|
f2fs_put_page(npage[0], 0);
|
|
|
|
goto release_out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i < level) {
|
|
|
|
parent = npage[i];
|
|
|
|
nids[i + 1] = get_nid(parent, offset[i], false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dn->nid = nids[level];
|
|
|
|
dn->ofs_in_node = offset[level];
|
|
|
|
dn->node_page = npage[level];
|
|
|
|
dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
release_pages:
|
|
|
|
f2fs_put_page(parent, 1);
|
|
|
|
if (i > 1)
|
|
|
|
f2fs_put_page(npage[0], 0);
|
|
|
|
release_out:
|
|
|
|
dn->inode_page = NULL;
|
|
|
|
dn->node_page = NULL;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void truncate_node(struct dnode_of_data *dn)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct node_info ni;
|
|
|
|
|
|
|
|
get_node_info(sbi, dn->nid, &ni);
|
2012-12-20 06:10:06 +00:00
|
|
|
if (dn->inode->i_blocks == 0) {
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(ni.blk_addr != NULL_ADDR);
|
2012-12-20 06:10:06 +00:00
|
|
|
goto invalidate;
|
|
|
|
}
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(ni.blk_addr == NULL_ADDR);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
/* Deallocate node address */
|
2012-12-20 06:10:06 +00:00
|
|
|
invalidate_blocks(sbi, ni.blk_addr);
|
2013-11-19 10:03:38 +00:00
|
|
|
dec_valid_node_count(sbi, dn->inode);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
set_node_addr(sbi, &ni, NULL_ADDR);
|
|
|
|
|
|
|
|
if (dn->nid == dn->inode->i_ino) {
|
|
|
|
remove_orphan_inode(sbi, dn->nid);
|
|
|
|
dec_valid_inode_count(sbi);
|
|
|
|
} else {
|
|
|
|
sync_inode_page(dn);
|
|
|
|
}
|
2012-12-20 06:10:06 +00:00
|
|
|
invalidate:
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
clear_node_page_dirty(dn->node_page);
|
|
|
|
F2FS_SET_SB_DIRT(sbi);
|
|
|
|
|
|
|
|
f2fs_put_page(dn->node_page, 1);
|
2014-01-22 11:41:57 +00:00
|
|
|
|
|
|
|
invalidate_mapping_pages(NODE_MAPPING(sbi),
|
|
|
|
dn->node_page->index, dn->node_page->index);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
dn->node_page = NULL;
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int truncate_dnode(struct dnode_of_data *dn)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct page *page;
|
|
|
|
|
|
|
|
if (dn->nid == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
/* get direct node */
|
|
|
|
page = get_node_page(sbi, dn->nid);
|
|
|
|
if (IS_ERR(page) && PTR_ERR(page) == -ENOENT)
|
|
|
|
return 1;
|
|
|
|
else if (IS_ERR(page))
|
|
|
|
return PTR_ERR(page);
|
|
|
|
|
|
|
|
/* Make dnode_of_data for parameter */
|
|
|
|
dn->node_page = page;
|
|
|
|
dn->ofs_in_node = 0;
|
|
|
|
truncate_data_blocks(dn);
|
|
|
|
truncate_node(dn);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs,
|
|
|
|
int ofs, int depth)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct dnode_of_data rdn = *dn;
|
|
|
|
struct page *page;
|
|
|
|
struct f2fs_node *rn;
|
|
|
|
nid_t child_nid;
|
|
|
|
unsigned int child_nofs;
|
|
|
|
int freed = 0;
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
if (dn->nid == 0)
|
|
|
|
return NIDS_PER_BLOCK + 1;
|
|
|
|
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
page = get_node_page(sbi, dn->nid);
|
2013-04-19 16:28:52 +00:00
|
|
|
if (IS_ERR(page)) {
|
|
|
|
trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page));
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return PTR_ERR(page);
|
2013-04-19 16:28:52 +00:00
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-07-15 09:57:38 +00:00
|
|
|
rn = F2FS_NODE(page);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (depth < 3) {
|
|
|
|
for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) {
|
|
|
|
child_nid = le32_to_cpu(rn->in.nid[i]);
|
|
|
|
if (child_nid == 0)
|
|
|
|
continue;
|
|
|
|
rdn.nid = child_nid;
|
|
|
|
ret = truncate_dnode(&rdn);
|
|
|
|
if (ret < 0)
|
|
|
|
goto out_err;
|
|
|
|
set_nid(page, i, 0, false);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1;
|
|
|
|
for (i = ofs; i < NIDS_PER_BLOCK; i++) {
|
|
|
|
child_nid = le32_to_cpu(rn->in.nid[i]);
|
|
|
|
if (child_nid == 0) {
|
|
|
|
child_nofs += NIDS_PER_BLOCK + 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
rdn.nid = child_nid;
|
|
|
|
ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1);
|
|
|
|
if (ret == (NIDS_PER_BLOCK + 1)) {
|
|
|
|
set_nid(page, i, 0, false);
|
|
|
|
child_nofs += ret;
|
|
|
|
} else if (ret < 0 && ret != -ENOENT) {
|
|
|
|
goto out_err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
freed = child_nofs;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!ofs) {
|
|
|
|
/* remove current indirect node */
|
|
|
|
dn->node_page = page;
|
|
|
|
truncate_node(dn);
|
|
|
|
freed++;
|
|
|
|
} else {
|
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
}
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_nodes_exit(dn->inode, freed);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return freed;
|
|
|
|
|
|
|
|
out_err:
|
|
|
|
f2fs_put_page(page, 1);
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_nodes_exit(dn->inode, ret);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int truncate_partial_nodes(struct dnode_of_data *dn,
|
|
|
|
struct f2fs_inode *ri, int *offset, int depth)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct page *pages[2];
|
|
|
|
nid_t nid[3];
|
|
|
|
nid_t child_nid;
|
|
|
|
int err = 0;
|
|
|
|
int i;
|
|
|
|
int idx = depth - 2;
|
|
|
|
|
|
|
|
nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
|
|
|
|
if (!nid[0])
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* get indirect nodes in the path */
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
for (i = 0; i < idx + 1; i++) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
/* refernece count'll be increased */
|
|
|
|
pages[i] = get_node_page(sbi, nid[i]);
|
|
|
|
if (IS_ERR(pages[i])) {
|
|
|
|
err = PTR_ERR(pages[i]);
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
idx = i - 1;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* free direct nodes linked to a partial indirect node */
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
child_nid = get_nid(pages[idx], i, false);
|
|
|
|
if (!child_nid)
|
|
|
|
continue;
|
|
|
|
dn->nid = child_nid;
|
|
|
|
err = truncate_dnode(dn);
|
|
|
|
if (err < 0)
|
|
|
|
goto fail;
|
|
|
|
set_nid(pages[idx], i, 0, false);
|
|
|
|
}
|
|
|
|
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
if (offset[idx + 1] == 0) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
dn->node_page = pages[idx];
|
|
|
|
dn->nid = nid[idx];
|
|
|
|
truncate_node(dn);
|
|
|
|
} else {
|
|
|
|
f2fs_put_page(pages[idx], 1);
|
|
|
|
}
|
|
|
|
offset[idx]++;
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
offset[idx + 1] = 0;
|
|
|
|
idx--;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
fail:
|
f2fs: fix truncate_partial_nodes bug
The truncate_partial_nodes puts pages incorrectly in the following two cases.
Note that the value for argc 'depth' can only be 2 or 3.
Please see truncate_inode_blocks() and truncate_partial_nodes().
1) An err is occurred in the first 'for' loop
When err is occurred with depth = 2, pages[0] is invalid, so this page doesn't
need to be put. There is no problem, however, when depth is 3, it doesn't put
the pages correctly where pages[0] is valid and pages[1] is invalid.
In this case, depth is set to 2 (ref to statemnt depth = i + 1), and then
'goto fail'.
In label 'fail', for (i = depth - 3; i >= 0; i--) cannot meet the condition
because i = -1, so pages[0] cann't be put.
2) An err happened in the second 'for' loop
Now we've got pages[0] with depth = 2, or we've got pages[0] and pages[1]
with depth = 3. When an err is detected, we need 'goto fail' to put such
the pages.
When depth is 2, in label 'fail', for (i = depth - 3; i >= 0; i--) cann't
meet the condition because i = -1, so pages[0] cann't be put.
When depth is 3, in label 'fail', for (i = depth - 3; i >= 0; i--) can
only put pages[0], pages[1] also cann't be put.
Note that 'depth' has been changed before first 'goto fail' (ref to statemnt
depth = i + 1), so passing this modified 'depth' to the tracepoint,
trace_f2fs_truncate_partial_nodes, is also incorrect.
Signed-off-by: Shifei Ge <shifei10.ge@samsung.com>
[Jaegeuk Kim: modify the description and fix one bug]
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-10-29 07:32:34 +00:00
|
|
|
for (i = idx; i >= 0; i--)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
f2fs_put_page(pages[i], 1);
|
2013-04-19 16:28:52 +00:00
|
|
|
|
|
|
|
trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* All the block addresses of data and nodes should be nullified.
|
|
|
|
*/
|
|
|
|
int truncate_inode_blocks(struct inode *inode, pgoff_t from)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
|
int err = 0, cont = 1;
|
|
|
|
int level, offset[4], noffset[4];
|
2013-02-11 22:28:55 +00:00
|
|
|
unsigned int nofs = 0;
|
2013-12-26 07:30:41 +00:00
|
|
|
struct f2fs_inode *ri;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
struct dnode_of_data dn;
|
|
|
|
struct page *page;
|
|
|
|
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_inode_blocks_enter(inode, from);
|
|
|
|
|
2013-08-12 12:08:03 +00:00
|
|
|
level = get_node_path(F2FS_I(inode), from, offset, noffset);
|
2013-04-26 02:55:17 +00:00
|
|
|
restart:
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
page = get_node_page(sbi, inode->i_ino);
|
2013-04-19 16:28:52 +00:00
|
|
|
if (IS_ERR(page)) {
|
|
|
|
trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page));
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return PTR_ERR(page);
|
2013-04-19 16:28:52 +00:00
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
set_new_dnode(&dn, inode, page, NULL, 0);
|
|
|
|
unlock_page(page);
|
|
|
|
|
2013-12-26 07:30:41 +00:00
|
|
|
ri = F2FS_INODE(page);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
switch (level) {
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
nofs = noffset[1];
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
nofs = noffset[1];
|
|
|
|
if (!offset[level - 1])
|
|
|
|
goto skip_partial;
|
2013-12-26 07:30:41 +00:00
|
|
|
err = truncate_partial_nodes(&dn, ri, offset, level);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (err < 0 && err != -ENOENT)
|
|
|
|
goto fail;
|
|
|
|
nofs += 1 + NIDS_PER_BLOCK;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
nofs = 5 + 2 * NIDS_PER_BLOCK;
|
|
|
|
if (!offset[level - 1])
|
|
|
|
goto skip_partial;
|
2013-12-26 07:30:41 +00:00
|
|
|
err = truncate_partial_nodes(&dn, ri, offset, level);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (err < 0 && err != -ENOENT)
|
|
|
|
goto fail;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
|
|
|
|
skip_partial:
|
|
|
|
while (cont) {
|
2013-12-26 07:30:41 +00:00
|
|
|
dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
switch (offset[0]) {
|
|
|
|
case NODE_DIR1_BLOCK:
|
|
|
|
case NODE_DIR2_BLOCK:
|
|
|
|
err = truncate_dnode(&dn);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NODE_IND1_BLOCK:
|
|
|
|
case NODE_IND2_BLOCK:
|
|
|
|
err = truncate_nodes(&dn, nofs, offset[1], 2);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case NODE_DIND_BLOCK:
|
|
|
|
err = truncate_nodes(&dn, nofs, offset[1], 3);
|
|
|
|
cont = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
BUG();
|
|
|
|
}
|
|
|
|
if (err < 0 && err != -ENOENT)
|
|
|
|
goto fail;
|
|
|
|
if (offset[1] == 0 &&
|
2013-12-26 07:30:41 +00:00
|
|
|
ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
lock_page(page);
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
|
2013-04-26 02:55:17 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
goto restart;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
wait_on_page_writeback(page);
|
2013-12-26 07:30:41 +00:00
|
|
|
ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
set_page_dirty(page);
|
|
|
|
unlock_page(page);
|
|
|
|
}
|
|
|
|
offset[1] = 0;
|
|
|
|
offset[0]++;
|
|
|
|
nofs += err;
|
|
|
|
}
|
|
|
|
fail:
|
|
|
|
f2fs_put_page(page, 0);
|
2013-04-19 16:28:52 +00:00
|
|
|
trace_f2fs_truncate_inode_blocks_exit(inode, err);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return err > 0 ? 0 : err;
|
|
|
|
}
|
|
|
|
|
2013-08-14 11:40:06 +00:00
|
|
|
int truncate_xattr_node(struct inode *inode, struct page *page)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
|
nid_t nid = F2FS_I(inode)->i_xattr_nid;
|
|
|
|
struct dnode_of_data dn;
|
|
|
|
struct page *npage;
|
|
|
|
|
|
|
|
if (!nid)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
npage = get_node_page(sbi, nid);
|
|
|
|
if (IS_ERR(npage))
|
|
|
|
return PTR_ERR(npage);
|
|
|
|
|
|
|
|
F2FS_I(inode)->i_xattr_nid = 0;
|
2013-08-14 12:57:27 +00:00
|
|
|
|
|
|
|
/* need to do checkpoint during fsync */
|
|
|
|
F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi));
|
|
|
|
|
2013-08-14 11:40:06 +00:00
|
|
|
set_new_dnode(&dn, inode, page, npage, nid);
|
|
|
|
|
|
|
|
if (page)
|
2013-11-28 07:43:07 +00:00
|
|
|
dn.inode_page_locked = true;
|
2013-08-14 11:40:06 +00:00
|
|
|
truncate_node(&dn);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
/*
|
2013-12-21 10:02:14 +00:00
|
|
|
* Caller should grab and release a rwsem by calling f2fs_lock_op() and
|
|
|
|
* f2fs_unlock_op().
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
*/
|
2013-11-19 10:03:18 +00:00
|
|
|
void remove_inode_page(struct inode *inode)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
|
struct page *page;
|
|
|
|
nid_t ino = inode->i_ino;
|
|
|
|
struct dnode_of_data dn;
|
|
|
|
|
|
|
|
page = get_node_page(sbi, ino);
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
if (IS_ERR(page))
|
2013-11-19 10:03:18 +00:00
|
|
|
return;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-11-19 10:03:18 +00:00
|
|
|
if (truncate_xattr_node(inode, page)) {
|
2013-08-14 11:40:06 +00:00
|
|
|
f2fs_put_page(page, 1);
|
2013-11-19 10:03:18 +00:00
|
|
|
return;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
2012-12-20 06:10:06 +00:00
|
|
|
/* 0 is possible, after f2fs_new_inode() is failed */
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(inode->i_blocks != 0 && inode->i_blocks != 1);
|
2012-12-20 06:10:06 +00:00
|
|
|
set_new_dnode(&dn, inode, page, page, ino);
|
|
|
|
truncate_node(&dn);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2013-05-20 01:10:29 +00:00
|
|
|
struct page *new_inode_page(struct inode *inode, const struct qstr *name)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct dnode_of_data dn;
|
|
|
|
|
|
|
|
/* allocate inode page for new inode */
|
|
|
|
set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
|
2013-05-20 01:10:29 +00:00
|
|
|
|
|
|
|
/* caller should f2fs_put_page(page, 1); */
|
2013-06-03 10:46:19 +00:00
|
|
|
return new_node_page(&dn, 0, NULL);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2013-06-03 10:46:19 +00:00
|
|
|
struct page *new_node_page(struct dnode_of_data *dn,
|
|
|
|
unsigned int ofs, struct page *ipage)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
|
|
|
|
struct node_info old_ni, new_ni;
|
|
|
|
struct page *page;
|
|
|
|
int err;
|
|
|
|
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)))
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return ERR_PTR(-EPERM);
|
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
page = grab_cache_page(NODE_MAPPING(sbi), dn->nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (!page)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(!inc_valid_node_count(sbi, dn->inode))) {
|
2013-08-12 07:00:46 +00:00
|
|
|
err = -ENOSPC;
|
|
|
|
goto fail;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-08-12 07:00:46 +00:00
|
|
|
get_node_info(sbi, dn->nid, &old_ni);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
/* Reinitialize old_ni with new node page */
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(old_ni.blk_addr != NULL_ADDR);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
new_ni = old_ni;
|
|
|
|
new_ni.ino = dn->inode->i_ino;
|
|
|
|
set_node_addr(sbi, &new_ni, NEW_ADDR);
|
2013-08-12 07:00:46 +00:00
|
|
|
|
|
|
|
fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
|
f2fs: fix handling errors got by f2fs_write_inode
Ruslan reported that f2fs hangs with an infinite loop in f2fs_sync_file():
while (sync_node_pages(sbi, inode->i_ino, &wbc) == 0)
f2fs_write_inode(inode, NULL);
The reason was revealed that the cold flag is not set even thought this inode is
a normal file. Therefore, sync_node_pages() skips to write node blocks since it
only writes cold node blocks.
The cold flag is stored to the node_footer in node block, and whenever a new
node page is allocated, it is set according to its file type, file or directory.
But, after sudden-power-off, when recovering the inode page, f2fs doesn't recover
its cold flag.
So, let's assign the cold flag in more right places.
One more thing:
If f2fs_write_inode() returns an error due to whatever situations, there would
be no dirty node pages so that sync_node_pages() returns zero.
(i.e., zero means nothing was written.)
Reported-by: Ruslan N. Marchenko <me@ruff.mobi>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-12-19 06:28:39 +00:00
|
|
|
set_cold_node(dn->inode, page);
|
2013-08-12 07:00:46 +00:00
|
|
|
SetPageUptodate(page);
|
|
|
|
set_page_dirty(page);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-08-12 07:04:53 +00:00
|
|
|
if (ofs == XATTR_NODE_OFFSET)
|
|
|
|
F2FS_I(dn->inode)->i_xattr_nid = dn->nid;
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
dn->node_page = page;
|
2013-06-03 10:46:19 +00:00
|
|
|
if (ipage)
|
|
|
|
update_inode(dn->inode, ipage);
|
|
|
|
else
|
|
|
|
sync_inode_page(dn);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (ofs == 0)
|
|
|
|
inc_valid_inode_count(sbi);
|
|
|
|
|
|
|
|
return page;
|
|
|
|
|
|
|
|
fail:
|
2012-12-20 06:10:06 +00:00
|
|
|
clear_node_page_dirty(page);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
return ERR_PTR(err);
|
|
|
|
}
|
|
|
|
|
2013-03-31 03:47:20 +00:00
|
|
|
/*
|
|
|
|
* Caller should do after getting the following values.
|
|
|
|
* 0: f2fs_put_page(page, 0)
|
|
|
|
* LOCKED_PAGE: f2fs_put_page(page, 1)
|
|
|
|
* error: nothing
|
|
|
|
*/
|
2013-11-30 03:51:14 +00:00
|
|
|
static int read_node_page(struct page *page, int rw)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
|
|
|
|
struct node_info ni;
|
|
|
|
|
|
|
|
get_node_info(sbi, page->index, &ni);
|
|
|
|
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(ni.blk_addr == NULL_ADDR)) {
|
2013-03-08 12:29:23 +00:00
|
|
|
f2fs_put_page(page, 1);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return -ENOENT;
|
2013-03-08 12:29:23 +00:00
|
|
|
}
|
|
|
|
|
2013-03-31 03:47:20 +00:00
|
|
|
if (PageUptodate(page))
|
|
|
|
return LOCKED_PAGE;
|
2013-03-08 12:29:23 +00:00
|
|
|
|
2013-11-30 03:51:14 +00:00
|
|
|
return f2fs_submit_page_bio(sbi, page, ni.blk_addr, rw);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* Readahead a node page
|
|
|
|
*/
|
|
|
|
void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
|
|
|
struct page *apage;
|
2013-03-31 03:47:20 +00:00
|
|
|
int err;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
apage = find_get_page(NODE_MAPPING(sbi), nid);
|
2013-03-08 12:29:23 +00:00
|
|
|
if (apage && PageUptodate(apage)) {
|
|
|
|
f2fs_put_page(apage, 0);
|
|
|
|
return;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
f2fs_put_page(apage, 0);
|
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
apage = grab_cache_page(NODE_MAPPING(sbi), nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (!apage)
|
|
|
|
return;
|
|
|
|
|
2013-03-31 03:47:20 +00:00
|
|
|
err = read_node_page(apage, READA);
|
|
|
|
if (err == 0)
|
2013-03-08 12:29:23 +00:00
|
|
|
f2fs_put_page(apage, 0);
|
2013-03-31 03:47:20 +00:00
|
|
|
else if (err == LOCKED_PAGE)
|
|
|
|
f2fs_put_page(apage, 1);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid)
|
|
|
|
{
|
2013-03-31 03:47:20 +00:00
|
|
|
struct page *page;
|
|
|
|
int err;
|
2013-04-26 02:55:17 +00:00
|
|
|
repeat:
|
2014-01-21 09:51:16 +00:00
|
|
|
page = grab_cache_page(NODE_MAPPING(sbi), nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (!page)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
|
|
|
err = read_node_page(page, READ_SYNC);
|
2013-03-31 03:47:20 +00:00
|
|
|
if (err < 0)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return ERR_PTR(err);
|
2013-03-31 03:47:20 +00:00
|
|
|
else if (err == LOCKED_PAGE)
|
|
|
|
goto got_it;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-03-08 12:29:23 +00:00
|
|
|
lock_page(page);
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(!PageUptodate(page))) {
|
2013-03-08 12:29:23 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
return ERR_PTR(-EIO);
|
|
|
|
}
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
|
2013-04-26 02:55:17 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
goto repeat;
|
|
|
|
}
|
2013-03-31 03:47:20 +00:00
|
|
|
got_it:
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nid != nid_of_node(page));
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
mark_page_accessed(page);
|
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* Return a locked page for the desired node page.
|
|
|
|
* And, readahead MAX_RA_NODE number of node pages.
|
|
|
|
*/
|
|
|
|
struct page *get_node_page_ra(struct page *parent, int start)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb);
|
f2fs: give a chance to merge IOs by IO scheduler
Previously, background GC submits many 4KB read requests to load victim blocks
and/or its (i)node blocks.
...
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb61, blkaddr = 0x3b964ed
f2fs_gc : block_rq_complete: 8,16 R () 499854968 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb6f, blkaddr = 0x3b964ee
f2fs_gc : block_rq_complete: 8,16 R () 499854976 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb79, blkaddr = 0x3b964ef
f2fs_gc : block_rq_complete: 8,16 R () 499854984 + 8 [0]
...
However, by the fact that many IOs are sequential, we can give a chance to merge
the IOs by IO scheduler.
In order to do that, let's use blk_plug.
...
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c6, blkaddr = 0x2e6ee
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c7, blkaddr = 0x2e6ef
<idle> : block_rq_complete: 8,16 R () 1519616 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1519848 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1520432 + 96 [0]
<idle> : block_rq_complete: 8,16 R () 1520536 + 104 [0]
<idle> : block_rq_complete: 8,16 R () 1521008 + 112 [0]
<idle> : block_rq_complete: 8,16 R () 1521440 + 152 [0]
<idle> : block_rq_complete: 8,16 R () 1521688 + 144 [0]
<idle> : block_rq_complete: 8,16 R () 1522128 + 192 [0]
<idle> : block_rq_complete: 8,16 R () 1523256 + 328 [0]
...
Note that this issue should be addressed in checkpoint, and some readahead
flows too.
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-04-24 04:19:56 +00:00
|
|
|
struct blk_plug plug;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
struct page *page;
|
2013-03-31 03:47:20 +00:00
|
|
|
int err, i, end;
|
|
|
|
nid_t nid;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
/* First, try getting the desired direct node. */
|
|
|
|
nid = get_nid(parent, start, false);
|
|
|
|
if (!nid)
|
|
|
|
return ERR_PTR(-ENOENT);
|
2013-04-26 02:55:17 +00:00
|
|
|
repeat:
|
2014-01-21 09:51:16 +00:00
|
|
|
page = grab_cache_page(NODE_MAPPING(sbi), nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (!page)
|
|
|
|
return ERR_PTR(-ENOMEM);
|
|
|
|
|
2013-02-26 03:43:46 +00:00
|
|
|
err = read_node_page(page, READ_SYNC);
|
2013-03-31 03:47:20 +00:00
|
|
|
if (err < 0)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return ERR_PTR(err);
|
2013-03-31 03:47:20 +00:00
|
|
|
else if (err == LOCKED_PAGE)
|
|
|
|
goto page_hit;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
f2fs: give a chance to merge IOs by IO scheduler
Previously, background GC submits many 4KB read requests to load victim blocks
and/or its (i)node blocks.
...
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb61, blkaddr = 0x3b964ed
f2fs_gc : block_rq_complete: 8,16 R () 499854968 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb6f, blkaddr = 0x3b964ee
f2fs_gc : block_rq_complete: 8,16 R () 499854976 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb79, blkaddr = 0x3b964ef
f2fs_gc : block_rq_complete: 8,16 R () 499854984 + 8 [0]
...
However, by the fact that many IOs are sequential, we can give a chance to merge
the IOs by IO scheduler.
In order to do that, let's use blk_plug.
...
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c6, blkaddr = 0x2e6ee
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c7, blkaddr = 0x2e6ef
<idle> : block_rq_complete: 8,16 R () 1519616 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1519848 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1520432 + 96 [0]
<idle> : block_rq_complete: 8,16 R () 1520536 + 104 [0]
<idle> : block_rq_complete: 8,16 R () 1521008 + 112 [0]
<idle> : block_rq_complete: 8,16 R () 1521440 + 152 [0]
<idle> : block_rq_complete: 8,16 R () 1521688 + 144 [0]
<idle> : block_rq_complete: 8,16 R () 1522128 + 192 [0]
<idle> : block_rq_complete: 8,16 R () 1523256 + 328 [0]
...
Note that this issue should be addressed in checkpoint, and some readahead
flows too.
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-04-24 04:19:56 +00:00
|
|
|
blk_start_plug(&plug);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
/* Then, try readahead for siblings of the desired node */
|
|
|
|
end = start + MAX_RA_NODE;
|
|
|
|
end = min(end, NIDS_PER_BLOCK);
|
|
|
|
for (i = start + 1; i < end; i++) {
|
|
|
|
nid = get_nid(parent, i, false);
|
|
|
|
if (!nid)
|
|
|
|
continue;
|
|
|
|
ra_node_page(sbi, nid);
|
|
|
|
}
|
|
|
|
|
f2fs: give a chance to merge IOs by IO scheduler
Previously, background GC submits many 4KB read requests to load victim blocks
and/or its (i)node blocks.
...
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb61, blkaddr = 0x3b964ed
f2fs_gc : block_rq_complete: 8,16 R () 499854968 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb6f, blkaddr = 0x3b964ee
f2fs_gc : block_rq_complete: 8,16 R () 499854976 + 8 [0]
f2fs_gc : f2fs_readpage: ino = 1, page_index = 0xb79, blkaddr = 0x3b964ef
f2fs_gc : block_rq_complete: 8,16 R () 499854984 + 8 [0]
...
However, by the fact that many IOs are sequential, we can give a chance to merge
the IOs by IO scheduler.
In order to do that, let's use blk_plug.
...
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c6, blkaddr = 0x2e6ee
f2fs_gc : f2fs_iget: ino = 143
f2fs_gc : f2fs_readpage: ino = 143, page_index = 0x1c7, blkaddr = 0x2e6ef
<idle> : block_rq_complete: 8,16 R () 1519616 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1519848 + 8 [0]
<idle> : block_rq_complete: 8,16 R () 1520432 + 96 [0]
<idle> : block_rq_complete: 8,16 R () 1520536 + 104 [0]
<idle> : block_rq_complete: 8,16 R () 1521008 + 112 [0]
<idle> : block_rq_complete: 8,16 R () 1521440 + 152 [0]
<idle> : block_rq_complete: 8,16 R () 1521688 + 144 [0]
<idle> : block_rq_complete: 8,16 R () 1522128 + 192 [0]
<idle> : block_rq_complete: 8,16 R () 1523256 + 328 [0]
...
Note that this issue should be addressed in checkpoint, and some readahead
flows too.
Reviewed-by: Namjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-04-24 04:19:56 +00:00
|
|
|
blk_finish_plug(&plug);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
lock_page(page);
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
|
2013-04-26 02:55:17 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
goto repeat;
|
|
|
|
}
|
2013-02-02 14:51:51 +00:00
|
|
|
page_hit:
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(!PageUptodate(page))) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
return ERR_PTR(-EIO);
|
|
|
|
}
|
2013-03-08 12:29:23 +00:00
|
|
|
mark_page_accessed(page);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return page;
|
|
|
|
}
|
|
|
|
|
|
|
|
void sync_inode_page(struct dnode_of_data *dn)
|
|
|
|
{
|
|
|
|
if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) {
|
|
|
|
update_inode(dn->inode, dn->node_page);
|
|
|
|
} else if (dn->inode_page) {
|
|
|
|
if (!dn->inode_page_locked)
|
|
|
|
lock_page(dn->inode_page);
|
|
|
|
update_inode(dn->inode, dn->inode_page);
|
|
|
|
if (!dn->inode_page_locked)
|
|
|
|
unlock_page(dn->inode_page);
|
|
|
|
} else {
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
update_inode_page(dn->inode);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
pgoff_t index, end;
|
|
|
|
struct pagevec pvec;
|
|
|
|
int step = ino ? 2 : 0;
|
|
|
|
int nwritten = 0, wrote = 0;
|
|
|
|
|
|
|
|
pagevec_init(&pvec, 0);
|
|
|
|
|
|
|
|
next_step:
|
|
|
|
index = 0;
|
|
|
|
end = LONG_MAX;
|
|
|
|
|
|
|
|
while (index <= end) {
|
|
|
|
int i, nr_pages;
|
2014-01-21 09:51:16 +00:00
|
|
|
nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
PAGECACHE_TAG_DIRTY,
|
|
|
|
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
|
|
|
|
if (nr_pages == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
for (i = 0; i < nr_pages; i++) {
|
|
|
|
struct page *page = pvec.pages[i];
|
|
|
|
|
|
|
|
/*
|
|
|
|
* flushing sequence with step:
|
|
|
|
* 0. indirect nodes
|
|
|
|
* 1. dentry dnodes
|
|
|
|
* 2. file dnodes
|
|
|
|
*/
|
|
|
|
if (step == 0 && IS_DNODE(page))
|
|
|
|
continue;
|
|
|
|
if (step == 1 && (!IS_DNODE(page) ||
|
|
|
|
is_cold_node(page)))
|
|
|
|
continue;
|
|
|
|
if (step == 2 && (!IS_DNODE(page) ||
|
|
|
|
!is_cold_node(page)))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If an fsync mode,
|
|
|
|
* we should not skip writing node pages.
|
|
|
|
*/
|
|
|
|
if (ino && ino_of_node(page) == ino)
|
|
|
|
lock_page(page);
|
|
|
|
else if (!trylock_page(page))
|
|
|
|
continue;
|
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
continue_unlock:
|
|
|
|
unlock_page(page);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (ino && ino_of_node(page) != ino)
|
|
|
|
goto continue_unlock;
|
|
|
|
|
|
|
|
if (!PageDirty(page)) {
|
|
|
|
/* someone wrote it for us */
|
|
|
|
goto continue_unlock;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!clear_page_dirty_for_io(page))
|
|
|
|
goto continue_unlock;
|
|
|
|
|
|
|
|
/* called by fsync() */
|
|
|
|
if (ino && IS_DNODE(page)) {
|
|
|
|
int mark = !is_checkpointed_node(sbi, ino);
|
|
|
|
set_fsync_mark(page, 1);
|
|
|
|
if (IS_INODE(page))
|
|
|
|
set_dentry_mark(page, mark);
|
|
|
|
nwritten++;
|
|
|
|
} else {
|
|
|
|
set_fsync_mark(page, 0);
|
|
|
|
set_dentry_mark(page, 0);
|
|
|
|
}
|
2014-01-21 09:51:16 +00:00
|
|
|
NODE_MAPPING(sbi)->a_ops->writepage(page, wbc);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
wrote++;
|
|
|
|
|
|
|
|
if (--wbc->nr_to_write == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
pagevec_release(&pvec);
|
|
|
|
cond_resched();
|
|
|
|
|
|
|
|
if (wbc->nr_to_write == 0) {
|
|
|
|
step = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (step < 2) {
|
|
|
|
step++;
|
|
|
|
goto next_step;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (wrote)
|
2013-12-11 04:54:01 +00:00
|
|
|
f2fs_submit_merged_bio(sbi, NODE, WRITE);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return nwritten;
|
|
|
|
}
|
|
|
|
|
2013-10-31 05:57:01 +00:00
|
|
|
int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
|
|
|
|
{
|
|
|
|
pgoff_t index = 0, end = LONG_MAX;
|
|
|
|
struct pagevec pvec;
|
|
|
|
int ret2 = 0, ret = 0;
|
|
|
|
|
|
|
|
pagevec_init(&pvec, 0);
|
2014-01-21 09:51:16 +00:00
|
|
|
|
|
|
|
while (index <= end) {
|
|
|
|
int i, nr_pages;
|
|
|
|
nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
|
|
|
|
PAGECACHE_TAG_WRITEBACK,
|
|
|
|
min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
|
|
|
|
if (nr_pages == 0)
|
|
|
|
break;
|
2013-10-31 05:57:01 +00:00
|
|
|
|
|
|
|
for (i = 0; i < nr_pages; i++) {
|
|
|
|
struct page *page = pvec.pages[i];
|
|
|
|
|
|
|
|
/* until radix tree lookup accepts end_index */
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(page->index > end))
|
2013-10-31 05:57:01 +00:00
|
|
|
continue;
|
|
|
|
|
2013-11-04 02:28:33 +00:00
|
|
|
if (ino && ino_of_node(page) == ino) {
|
2013-10-31 05:57:01 +00:00
|
|
|
wait_on_page_writeback(page);
|
2013-11-04 02:28:33 +00:00
|
|
|
if (TestClearPageError(page))
|
|
|
|
ret = -EIO;
|
|
|
|
}
|
2013-10-31 05:57:01 +00:00
|
|
|
}
|
|
|
|
pagevec_release(&pvec);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(test_and_clear_bit(AS_ENOSPC, &NODE_MAPPING(sbi)->flags)))
|
2013-10-31 05:57:01 +00:00
|
|
|
ret2 = -ENOSPC;
|
2014-01-21 09:51:16 +00:00
|
|
|
if (unlikely(test_and_clear_bit(AS_EIO, &NODE_MAPPING(sbi)->flags)))
|
2013-10-31 05:57:01 +00:00
|
|
|
ret2 = -EIO;
|
|
|
|
if (!ret)
|
|
|
|
ret = ret2;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
static int f2fs_write_node_page(struct page *page,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb);
|
|
|
|
nid_t nid;
|
|
|
|
block_t new_addr;
|
|
|
|
struct node_info ni;
|
2014-01-08 01:09:51 +00:00
|
|
|
struct f2fs_io_info fio = {
|
|
|
|
.type = NODE,
|
2014-01-17 20:44:39 +00:00
|
|
|
.rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE,
|
2014-01-08 01:09:51 +00:00
|
|
|
};
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(sbi->por_doing))
|
2013-10-16 06:09:26 +00:00
|
|
|
goto redirty_out;
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
wait_on_page_writeback(page);
|
|
|
|
|
|
|
|
/* get old block addr of this node page */
|
|
|
|
nid = nid_of_node(page);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(page->index != nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
get_node_info(sbi, nid, &ni);
|
|
|
|
|
|
|
|
/* This page is already truncated */
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(ni.blk_addr == NULL_ADDR)) {
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
dec_page_count(sbi, F2FS_DIRTY_NODES);
|
|
|
|
unlock_page(page);
|
|
|
|
return 0;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-10-16 06:09:26 +00:00
|
|
|
if (wbc->for_reclaim)
|
|
|
|
goto redirty_out;
|
2013-03-13 08:49:22 +00:00
|
|
|
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
mutex_lock(&sbi->node_write);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
set_page_writeback(page);
|
2014-01-08 01:09:51 +00:00
|
|
|
write_node_page(sbi, page, &fio, nid, ni.blk_addr, &new_addr);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
set_node_addr(sbi, &ni, new_addr);
|
|
|
|
dec_page_count(sbi, F2FS_DIRTY_NODES);
|
f2fs: introduce a new global lock scheme
In the previous version, f2fs uses global locks according to the usage types,
such as directory operations, block allocation, block write, and so on.
Reference the following lock types in f2fs.h.
enum lock_type {
RENAME, /* for renaming operations */
DENTRY_OPS, /* for directory operations */
DATA_WRITE, /* for data write */
DATA_NEW, /* for data allocation */
DATA_TRUNC, /* for data truncate */
NODE_NEW, /* for node allocation */
NODE_TRUNC, /* for node truncate */
NODE_WRITE, /* for node write */
NR_LOCK_TYPE,
};
In that case, we lose the performance under the multi-threading environment,
since every types of operations must be conducted one at a time.
In order to address the problem, let's share the locks globally with a mutex
array regardless of any types.
So, let users grab a mutex and perform their jobs in parallel as much as
possbile.
For this, I propose a new global lock scheme as follows.
0. Data structure
- f2fs_sb_info -> mutex_lock[NR_GLOBAL_LOCKS]
- f2fs_sb_info -> node_write
1. mutex_lock_op(sbi)
- try to get an avaiable lock from the array.
- returns the index of the gottern lock variable.
2. mutex_unlock_op(sbi, index of the lock)
- unlock the given index of the lock.
3. mutex_lock_all(sbi)
- grab all the locks in the array before the checkpoint.
4. mutex_unlock_all(sbi)
- release all the locks in the array after checkpoint.
5. block_operations()
- call mutex_lock_all()
- sync_dirty_dir_inodes()
- grab node_write
- sync_node_pages()
Note that,
the pairs of mutex_lock_op()/mutex_unlock_op() and
mutex_lock_all()/mutex_unlock_all() should be used together.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-22 07:21:29 +00:00
|
|
|
mutex_unlock(&sbi->node_write);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
unlock_page(page);
|
|
|
|
return 0;
|
2013-10-16 06:09:26 +00:00
|
|
|
|
|
|
|
redirty_out:
|
|
|
|
dec_page_count(sbi, F2FS_DIRTY_NODES);
|
|
|
|
wbc->pages_skipped++;
|
|
|
|
set_page_dirty(page);
|
|
|
|
return AOP_WRITEPAGE_ACTIVATE;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2013-01-18 05:54:13 +00:00
|
|
|
/*
|
|
|
|
* 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.
|
f2fs: merge more bios of node block writes
Previously, we experience bio traces as follows when running simple sequential
write test.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500104928, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499922208, size = 368K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499914752, size = 140K
-> total 512K
The first one is to write an indirect node block, and the others are to write
direct node blocks.
The reason why there are two separate bios for direct node blocks is:
0. initial state
------------------ ------------------
| | |xxxxxxxx |
------------------ ------------------
1. write 368K
------------------ ------------------
| | |xxxxxxxxWWWWWWWW|
------------------ ------------------
2. write 140K
------------------ ------------------
|WWWWWWW | |xxxxxxxxWWWWWWWW|
------------------ ------------------
This is because f2fs_write_node_pages tries to write just 512K totally, so that
we can lose the chance to merge more bios nicely.
After this patch is applied, we can get the following bio traces.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500103168, size = 8K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500111368, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500107272, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500108296, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500109320, size = 500K
And finally, we can improve the sequential write performance,
from 458.775 MB/s to 479.945 MB/s on SSD.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-09-05 01:07:15 +00:00
|
|
|
* Be default, 512 pages (2MB) * 3 node types, is more reasonable.
|
2013-01-18 05:54:13 +00:00
|
|
|
*/
|
f2fs: merge more bios of node block writes
Previously, we experience bio traces as follows when running simple sequential
write test.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500104928, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499922208, size = 368K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499914752, size = 140K
-> total 512K
The first one is to write an indirect node block, and the others are to write
direct node blocks.
The reason why there are two separate bios for direct node blocks is:
0. initial state
------------------ ------------------
| | |xxxxxxxx |
------------------ ------------------
1. write 368K
------------------ ------------------
| | |xxxxxxxxWWWWWWWW|
------------------ ------------------
2. write 140K
------------------ ------------------
|WWWWWWW | |xxxxxxxxWWWWWWWW|
------------------ ------------------
This is because f2fs_write_node_pages tries to write just 512K totally, so that
we can lose the chance to merge more bios nicely.
After this patch is applied, we can get the following bio traces.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500103168, size = 8K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500111368, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500107272, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500108296, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500109320, size = 500K
And finally, we can improve the sequential write performance,
from 458.775 MB/s to 479.945 MB/s on SSD.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-09-05 01:07:15 +00:00
|
|
|
#define COLLECT_DIRTY_NODES 1536
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
static int f2fs_write_node_pages(struct address_space *mapping,
|
|
|
|
struct writeback_control *wbc)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
|
|
|
|
long nr_to_write = wbc->nr_to_write;
|
|
|
|
|
2013-10-24 05:19:18 +00:00
|
|
|
/* balancing f2fs's metadata in background */
|
|
|
|
f2fs_balance_fs_bg(sbi);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-01-18 05:54:13 +00:00
|
|
|
/* collect a number of dirty node pages and write together */
|
|
|
|
if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
|
|
|
|
return 0;
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
/* if mounting is failed, skip writing node pages */
|
f2fs: merge more bios of node block writes
Previously, we experience bio traces as follows when running simple sequential
write test.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500104928, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499922208, size = 368K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499914752, size = 140K
-> total 512K
The first one is to write an indirect node block, and the others are to write
direct node blocks.
The reason why there are two separate bios for direct node blocks is:
0. initial state
------------------ ------------------
| | |xxxxxxxx |
------------------ ------------------
1. write 368K
------------------ ------------------
| | |xxxxxxxxWWWWWWWW|
------------------ ------------------
2. write 140K
------------------ ------------------
|WWWWWWW | |xxxxxxxxWWWWWWWW|
------------------ ------------------
This is because f2fs_write_node_pages tries to write just 512K totally, so that
we can lose the chance to merge more bios nicely.
After this patch is applied, we can get the following bio traces.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500103168, size = 8K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500111368, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500107272, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500108296, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500109320, size = 500K
And finally, we can improve the sequential write performance,
from 458.775 MB/s to 479.945 MB/s on SSD.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-09-05 01:07:15 +00:00
|
|
|
wbc->nr_to_write = 3 * max_hw_blocks(sbi);
|
2014-01-08 01:09:51 +00:00
|
|
|
wbc->sync_mode = WB_SYNC_NONE;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
sync_node_pages(sbi, 0, wbc);
|
f2fs: merge more bios of node block writes
Previously, we experience bio traces as follows when running simple sequential
write test.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500104928, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499922208, size = 368K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 499914752, size = 140K
-> total 512K
The first one is to write an indirect node block, and the others are to write
direct node blocks.
The reason why there are two separate bios for direct node blocks is:
0. initial state
------------------ ------------------
| | |xxxxxxxx |
------------------ ------------------
1. write 368K
------------------ ------------------
| | |xxxxxxxxWWWWWWWW|
------------------ ------------------
2. write 140K
------------------ ------------------
|WWWWWWW | |xxxxxxxxWWWWWWWW|
------------------ ------------------
This is because f2fs_write_node_pages tries to write just 512K totally, so that
we can lose the chance to merge more bios nicely.
After this patch is applied, we can get the following bio traces.
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500103168, size = 8K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500111368, size = 4K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500107272, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500108296, size = 512K
f2fs_do_submit_bio: type = NODE, io = no sync, sector = 500109320, size = 500K
And finally, we can improve the sequential write performance,
from 458.775 MB/s to 479.945 MB/s on SSD.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2013-09-05 01:07:15 +00:00
|
|
|
wbc->nr_to_write = nr_to_write - (3 * max_hw_blocks(sbi) -
|
|
|
|
wbc->nr_to_write);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int f2fs_set_node_page_dirty(struct page *page)
|
|
|
|
{
|
|
|
|
struct address_space *mapping = page->mapping;
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb);
|
|
|
|
|
2013-10-24 08:53:29 +00:00
|
|
|
trace_f2fs_set_page_dirty(page, NODE);
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
SetPageUptodate(page);
|
|
|
|
if (!PageDirty(page)) {
|
|
|
|
__set_page_dirty_nobuffers(page);
|
|
|
|
inc_page_count(sbi, F2FS_DIRTY_NODES);
|
|
|
|
SetPagePrivate(page);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-22 03:17:23 +00:00
|
|
|
static void f2fs_invalidate_node_page(struct page *page, unsigned int offset,
|
|
|
|
unsigned int length)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct inode *inode = page->mapping->host;
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
|
if (PageDirty(page))
|
|
|
|
dec_page_count(sbi, F2FS_DIRTY_NODES);
|
|
|
|
ClearPagePrivate(page);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int f2fs_release_node_page(struct page *page, gfp_t wait)
|
|
|
|
{
|
|
|
|
ClearPagePrivate(page);
|
2013-03-14 00:24:32 +00:00
|
|
|
return 1;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* Structure of the f2fs node operations
|
|
|
|
*/
|
|
|
|
const struct address_space_operations f2fs_node_aops = {
|
|
|
|
.writepage = f2fs_write_node_page,
|
|
|
|
.writepages = f2fs_write_node_pages,
|
|
|
|
.set_page_dirty = f2fs_set_node_page_dirty,
|
|
|
|
.invalidatepage = f2fs_invalidate_node_page,
|
|
|
|
.releasepage = f2fs_release_node_page,
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head)
|
|
|
|
{
|
|
|
|
struct list_head *this;
|
2013-03-02 03:40:50 +00:00
|
|
|
struct free_nid *i;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
list_for_each(this, head) {
|
|
|
|
i = list_entry(this, struct free_nid, list);
|
|
|
|
if (i->nid == n)
|
2013-03-02 03:40:50 +00:00
|
|
|
return i;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
2013-03-02 03:40:50 +00:00
|
|
|
return NULL;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void __del_from_free_nid_list(struct free_nid *i)
|
|
|
|
{
|
|
|
|
list_del(&i->list);
|
|
|
|
kmem_cache_free(free_nid_slab, i);
|
|
|
|
}
|
|
|
|
|
2013-05-07 11:47:40 +00:00
|
|
|
static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
struct free_nid *i;
|
2013-05-07 11:47:40 +00:00
|
|
|
struct nat_entry *ne;
|
|
|
|
bool allocated = false;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
if (nm_i->fcnt > 2 * MAX_FREE_NIDS)
|
2013-05-06 15:15:43 +00:00
|
|
|
return -1;
|
2013-04-25 04:21:12 +00:00
|
|
|
|
|
|
|
/* 0 nid should not be used */
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(nid == 0))
|
2013-04-25 04:21:12 +00:00
|
|
|
return 0;
|
2013-05-07 11:47:40 +00:00
|
|
|
|
2013-10-22 06:52:26 +00:00
|
|
|
if (build) {
|
|
|
|
/* do not add allocated nids */
|
|
|
|
read_lock(&nm_i->nat_tree_lock);
|
|
|
|
ne = __lookup_nat_cache(nm_i, nid);
|
|
|
|
if (ne && nat_get_blkaddr(ne) != NULL_ADDR)
|
|
|
|
allocated = true;
|
|
|
|
read_unlock(&nm_i->nat_tree_lock);
|
|
|
|
if (allocated)
|
|
|
|
return 0;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
2013-10-22 06:52:26 +00:00
|
|
|
|
|
|
|
i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
i->nid = nid;
|
|
|
|
i->state = NID_NEW;
|
|
|
|
|
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) {
|
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
kmem_cache_free(free_nid_slab, i);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
list_add_tail(&i->list, &nm_i->free_nid_list);
|
|
|
|
nm_i->fcnt++;
|
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid)
|
|
|
|
{
|
|
|
|
struct free_nid *i;
|
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
|
|
|
|
if (i && i->state == NID_NEW) {
|
|
|
|
__del_from_free_nid_list(i);
|
|
|
|
nm_i->fcnt--;
|
|
|
|
}
|
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
}
|
|
|
|
|
2013-05-06 15:15:42 +00:00
|
|
|
static void scan_nat_page(struct f2fs_nm_info *nm_i,
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
struct page *nat_page, nid_t start_nid)
|
|
|
|
{
|
|
|
|
struct f2fs_nat_block *nat_blk = page_address(nat_page);
|
|
|
|
block_t blk_addr;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
i = start_nid % NAT_ENTRY_PER_BLOCK;
|
|
|
|
|
|
|
|
for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
|
2013-05-06 15:15:43 +00:00
|
|
|
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(start_nid >= nm_i->max_nid))
|
2013-03-15 23:34:37 +00:00
|
|
|
break;
|
2013-05-06 15:15:43 +00:00
|
|
|
|
|
|
|
blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(blk_addr == NEW_ADDR);
|
2013-05-06 15:15:43 +00:00
|
|
|
if (blk_addr == NULL_ADDR) {
|
2013-05-07 11:47:40 +00:00
|
|
|
if (add_free_nid(nm_i, start_nid, true) < 0)
|
2013-05-06 15:15:43 +00:00
|
|
|
break;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void build_free_nids(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
|
|
|
struct f2fs_summary_block *sum = curseg->sum_blk;
|
2013-05-06 15:15:42 +00:00
|
|
|
int i = 0;
|
2013-04-25 07:05:51 +00:00
|
|
|
nid_t nid = nm_i->next_scan_nid;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-04-25 07:05:51 +00:00
|
|
|
/* Enough entries */
|
|
|
|
if (nm_i->fcnt > NAT_ENTRY_PER_BLOCK)
|
|
|
|
return;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-04-25 07:05:51 +00:00
|
|
|
/* readahead nat pages to be scanned */
|
2014-02-07 08:11:53 +00:00
|
|
|
ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, META_NAT);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
while (1) {
|
|
|
|
struct page *page = get_current_nat_page(sbi, nid);
|
|
|
|
|
2013-05-06 15:15:42 +00:00
|
|
|
scan_nat_page(nm_i, page, nid);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
|
|
|
|
nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(nid >= nm_i->max_nid))
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
nid = 0;
|
2013-04-25 07:05:51 +00:00
|
|
|
|
|
|
|
if (i++ == FREE_NID_PAGES)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-04-25 07:05:51 +00:00
|
|
|
/* go to the next free nat pages to find free nids abundantly */
|
|
|
|
nm_i->next_scan_nid = nid;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
/* find free nids from current sum_pages */
|
|
|
|
mutex_lock(&curseg->curseg_mutex);
|
|
|
|
for (i = 0; i < nats_in_cursum(sum); i++) {
|
|
|
|
block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr);
|
|
|
|
nid = le32_to_cpu(nid_in_journal(sum, i));
|
|
|
|
if (addr == NULL_ADDR)
|
2013-05-07 11:47:40 +00:00
|
|
|
add_free_nid(nm_i, nid, true);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
else
|
|
|
|
remove_free_nid(nm_i, nid);
|
|
|
|
}
|
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If this function returns success, caller can obtain a new nid
|
|
|
|
* from second parameter of this function.
|
|
|
|
* The returned nid could be used ino as well as nid when inode is created.
|
|
|
|
*/
|
|
|
|
bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct free_nid *i = NULL;
|
|
|
|
struct list_head *this;
|
|
|
|
retry:
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(sbi->total_valid_node_count + 1 >= nm_i->max_nid))
|
2013-04-25 07:05:51 +00:00
|
|
|
return false;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
|
2013-04-25 07:05:51 +00:00
|
|
|
/* We should not use stale free nids created by build_free_nids */
|
|
|
|
if (nm_i->fcnt && !sbi->on_build_free_nids) {
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(list_empty(&nm_i->free_nid_list));
|
2013-04-25 07:05:51 +00:00
|
|
|
list_for_each(this, &nm_i->free_nid_list) {
|
|
|
|
i = list_entry(this, struct free_nid, list);
|
|
|
|
if (i->state == NID_NEW)
|
|
|
|
break;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(i->state != NID_NEW);
|
2013-04-25 07:05:51 +00:00
|
|
|
*nid = i->nid;
|
|
|
|
i->state = NID_ALLOC;
|
|
|
|
nm_i->fcnt--;
|
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
return true;
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
2013-04-25 07:05:51 +00:00
|
|
|
|
|
|
|
/* Let's scan nat pages and its caches to get free nids */
|
|
|
|
mutex_lock(&nm_i->build_lock);
|
2013-10-23 04:39:32 +00:00
|
|
|
sbi->on_build_free_nids = true;
|
2013-04-25 07:05:51 +00:00
|
|
|
build_free_nids(sbi);
|
2013-10-23 04:39:32 +00:00
|
|
|
sbi->on_build_free_nids = false;
|
2013-04-25 07:05:51 +00:00
|
|
|
mutex_unlock(&nm_i->build_lock);
|
|
|
|
goto retry;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* alloc_nid() should be called prior to this function.
|
|
|
|
*/
|
|
|
|
void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct free_nid *i;
|
|
|
|
|
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(!i || i->state != NID_ALLOC);
|
2013-04-03 13:19:03 +00:00
|
|
|
__del_from_free_nid_list(i);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* alloc_nid() should be called prior to this function.
|
|
|
|
*/
|
|
|
|
void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
|
|
|
|
{
|
2013-04-03 13:19:03 +00:00
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct free_nid *i;
|
|
|
|
|
2013-08-14 12:57:27 +00:00
|
|
|
if (!nid)
|
|
|
|
return;
|
|
|
|
|
2013-04-03 13:19:03 +00:00
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
i = __lookup_free_nid_list(nid, &nm_i->free_nid_list);
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(!i || i->state != NID_ALLOC);
|
2013-05-06 15:15:41 +00:00
|
|
|
if (nm_i->fcnt > 2 * MAX_FREE_NIDS) {
|
|
|
|
__del_from_free_nid_list(i);
|
|
|
|
} else {
|
|
|
|
i->state = NID_NEW;
|
|
|
|
nm_i->fcnt++;
|
|
|
|
}
|
2013-04-03 13:19:03 +00:00
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
|
|
|
|
struct f2fs_summary *sum, struct node_info *ni,
|
|
|
|
block_t new_blkaddr)
|
|
|
|
{
|
|
|
|
rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr);
|
|
|
|
set_node_addr(sbi, ni, new_blkaddr);
|
|
|
|
clear_node_page_dirty(page);
|
|
|
|
}
|
|
|
|
|
2014-01-28 03:25:06 +00:00
|
|
|
bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
|
|
|
|
{
|
|
|
|
struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
|
nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
|
|
|
|
nid_t new_xnid = nid_of_node(page);
|
|
|
|
struct node_info ni;
|
|
|
|
|
|
|
|
if (ofs_of_node(page) != XATTR_NODE_OFFSET)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
/* 1: invalidate the previous xattr nid */
|
|
|
|
if (!prev_xnid)
|
|
|
|
goto recover_xnid;
|
|
|
|
|
|
|
|
/* Deallocate node address */
|
|
|
|
get_node_info(sbi, prev_xnid, &ni);
|
|
|
|
f2fs_bug_on(ni.blk_addr == NULL_ADDR);
|
|
|
|
invalidate_blocks(sbi, ni.blk_addr);
|
|
|
|
dec_valid_node_count(sbi, inode);
|
|
|
|
set_node_addr(sbi, &ni, NULL_ADDR);
|
|
|
|
|
|
|
|
recover_xnid:
|
|
|
|
/* 2: allocate new xattr nid */
|
|
|
|
if (unlikely(!inc_valid_node_count(sbi, inode)))
|
|
|
|
f2fs_bug_on(1);
|
|
|
|
|
|
|
|
remove_free_nid(NM_I(sbi), new_xnid);
|
|
|
|
get_node_info(sbi, new_xnid, &ni);
|
|
|
|
ni.ino = inode->i_ino;
|
|
|
|
set_node_addr(sbi, &ni, NEW_ADDR);
|
|
|
|
F2FS_I(inode)->i_xattr_nid = new_xnid;
|
|
|
|
|
|
|
|
/* 3: update xattr blkaddr */
|
|
|
|
refresh_sit_entry(sbi, NEW_ADDR, blkaddr);
|
|
|
|
set_node_addr(sbi, &ni, blkaddr);
|
|
|
|
|
|
|
|
update_inode_page(inode);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
|
|
|
|
{
|
2013-12-26 07:30:41 +00:00
|
|
|
struct f2fs_inode *src, *dst;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
nid_t ino = ino_of_node(page);
|
|
|
|
struct node_info old_ni, new_ni;
|
|
|
|
struct page *ipage;
|
|
|
|
|
2014-01-21 09:51:16 +00:00
|
|
|
ipage = grab_cache_page(NODE_MAPPING(sbi), ino);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
if (!ipage)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
/* Should not use this inode from free nid list */
|
|
|
|
remove_free_nid(NM_I(sbi), ino);
|
|
|
|
|
|
|
|
get_node_info(sbi, ino, &old_ni);
|
|
|
|
SetPageUptodate(ipage);
|
|
|
|
fill_node_footer(ipage, ino, ino, 0, true);
|
|
|
|
|
2013-12-26 07:30:41 +00:00
|
|
|
src = F2FS_INODE(page);
|
|
|
|
dst = F2FS_INODE(ipage);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-12-26 07:30:41 +00:00
|
|
|
memcpy(dst, src, (unsigned long)&src->i_ext - (unsigned long)src);
|
|
|
|
dst->i_size = 0;
|
|
|
|
dst->i_blocks = cpu_to_le64(1);
|
|
|
|
dst->i_links = cpu_to_le32(1);
|
|
|
|
dst->i_xattr_nid = 0;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
new_ni = old_ni;
|
|
|
|
new_ni.ino = ino;
|
|
|
|
|
2013-12-05 09:15:22 +00:00
|
|
|
if (unlikely(!inc_valid_node_count(sbi, NULL)))
|
2013-05-14 06:47:43 +00:00
|
|
|
WARN_ON(1);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
set_node_addr(sbi, &new_ni, NEW_ADDR);
|
|
|
|
inc_valid_inode_count(sbi);
|
|
|
|
f2fs_put_page(ipage, 1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-11-22 07:48:54 +00:00
|
|
|
/*
|
|
|
|
* ra_sum_pages() merge contiguous pages into one bio and submit.
|
|
|
|
* these pre-readed pages are linked in pages list.
|
|
|
|
*/
|
|
|
|
static int ra_sum_pages(struct f2fs_sb_info *sbi, struct list_head *pages,
|
|
|
|
int start, int nrpages)
|
|
|
|
{
|
|
|
|
struct page *page;
|
|
|
|
int page_idx = start;
|
2013-12-11 04:54:01 +00:00
|
|
|
struct f2fs_io_info fio = {
|
|
|
|
.type = META,
|
2013-12-20 10:17:49 +00:00
|
|
|
.rw = READ_SYNC | REQ_META | REQ_PRIO
|
2013-12-11 04:54:01 +00:00
|
|
|
};
|
2013-11-22 07:48:54 +00:00
|
|
|
|
|
|
|
for (; page_idx < start + nrpages; page_idx++) {
|
|
|
|
/* alloc temporal page for read node summary info*/
|
2013-12-05 01:54:00 +00:00
|
|
|
page = alloc_page(GFP_F2FS_ZERO);
|
2013-11-22 07:48:54 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock_page(page);
|
|
|
|
page->index = page_idx;
|
|
|
|
list_add_tail(&page->lru, pages);
|
|
|
|
}
|
|
|
|
|
|
|
|
list_for_each_entry(page, pages, lru)
|
2013-12-11 04:54:01 +00:00
|
|
|
f2fs_submit_page_mbio(sbi, page, page->index, &fio);
|
2013-11-22 07:48:54 +00:00
|
|
|
|
2013-12-11 04:54:01 +00:00
|
|
|
f2fs_submit_merged_bio(sbi, META, READ);
|
2013-11-22 07:48:54 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
int restore_node_summary(struct f2fs_sb_info *sbi,
|
|
|
|
unsigned int segno, struct f2fs_summary_block *sum)
|
|
|
|
{
|
|
|
|
struct f2fs_node *rn;
|
|
|
|
struct f2fs_summary *sum_entry;
|
2013-11-22 07:48:54 +00:00
|
|
|
struct page *page, *tmp;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
block_t addr;
|
2013-11-22 07:48:54 +00:00
|
|
|
int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
|
|
|
|
int i, last_offset, nrpages, err = 0;
|
|
|
|
LIST_HEAD(page_list);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
/* scan the node segment */
|
|
|
|
last_offset = sbi->blocks_per_seg;
|
|
|
|
addr = START_BLOCK(sbi, segno);
|
|
|
|
sum_entry = &sum->entries[0];
|
|
|
|
|
2013-11-22 07:48:54 +00:00
|
|
|
for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
|
|
|
|
nrpages = min(last_offset - i, bio_blocks);
|
2013-03-08 12:29:23 +00:00
|
|
|
|
2013-11-22 07:48:54 +00:00
|
|
|
/* read ahead node pages */
|
|
|
|
err = ra_sum_pages(sbi, &page_list, addr, nrpages);
|
|
|
|
if (err)
|
|
|
|
return err;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
2013-11-22 07:48:54 +00:00
|
|
|
list_for_each_entry_safe(page, tmp, &page_list, lru) {
|
|
|
|
|
|
|
|
lock_page(page);
|
2013-12-06 06:00:58 +00:00
|
|
|
if (unlikely(!PageUptodate(page))) {
|
|
|
|
err = -EIO;
|
|
|
|
} else {
|
2013-11-22 07:48:54 +00:00
|
|
|
rn = F2FS_NODE(page);
|
|
|
|
sum_entry->nid = rn->footer.nid;
|
|
|
|
sum_entry->version = 0;
|
|
|
|
sum_entry->ofs_in_node = 0;
|
|
|
|
sum_entry++;
|
|
|
|
}
|
|
|
|
|
|
|
|
list_del(&page->lru);
|
|
|
|
unlock_page(page);
|
|
|
|
__free_pages(page, 0);
|
|
|
|
}
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
2013-11-22 07:48:54 +00:00
|
|
|
return err;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool flush_nats_in_journal(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
|
|
|
struct f2fs_summary_block *sum = curseg->sum_blk;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
mutex_lock(&curseg->curseg_mutex);
|
|
|
|
|
|
|
|
if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) {
|
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < nats_in_cursum(sum); i++) {
|
|
|
|
struct nat_entry *ne;
|
|
|
|
struct f2fs_nat_entry raw_ne;
|
|
|
|
nid_t nid = le32_to_cpu(nid_in_journal(sum, i));
|
|
|
|
|
|
|
|
raw_ne = nat_in_journal(sum, i);
|
|
|
|
retry:
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
ne = __lookup_nat_cache(nm_i, nid);
|
|
|
|
if (ne) {
|
|
|
|
__set_nat_cache_dirty(nm_i, ne);
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ne = grab_nat_entry(nm_i, nid);
|
|
|
|
if (!ne) {
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
goto retry;
|
|
|
|
}
|
|
|
|
nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr));
|
|
|
|
nat_set_ino(ne, le32_to_cpu(raw_ne.ino));
|
|
|
|
nat_set_version(ne, raw_ne.version);
|
|
|
|
__set_nat_cache_dirty(nm_i, ne);
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
}
|
|
|
|
update_nats_in_cursum(sum, -i);
|
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-11-29 04:28:09 +00:00
|
|
|
/*
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
* This function is called during the checkpointing process.
|
|
|
|
*/
|
|
|
|
void flush_nat_entries(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA);
|
|
|
|
struct f2fs_summary_block *sum = curseg->sum_blk;
|
|
|
|
struct list_head *cur, *n;
|
|
|
|
struct page *page = NULL;
|
|
|
|
struct f2fs_nat_block *nat_blk = NULL;
|
|
|
|
nid_t start_nid = 0, end_nid = 0;
|
|
|
|
bool flushed;
|
|
|
|
|
|
|
|
flushed = flush_nats_in_journal(sbi);
|
|
|
|
|
|
|
|
if (!flushed)
|
|
|
|
mutex_lock(&curseg->curseg_mutex);
|
|
|
|
|
|
|
|
/* 1) flush dirty nat caches */
|
|
|
|
list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) {
|
|
|
|
struct nat_entry *ne;
|
|
|
|
nid_t nid;
|
|
|
|
struct f2fs_nat_entry raw_ne;
|
|
|
|
int offset = -1;
|
2012-12-26 05:39:50 +00:00
|
|
|
block_t new_blkaddr;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
|
|
|
|
ne = list_entry(cur, struct nat_entry, list);
|
|
|
|
nid = nat_get_nid(ne);
|
|
|
|
|
|
|
|
if (nat_get_blkaddr(ne) == NEW_ADDR)
|
|
|
|
continue;
|
|
|
|
if (flushed)
|
|
|
|
goto to_nat_page;
|
|
|
|
|
|
|
|
/* if there is room for nat enries in curseg->sumpage */
|
|
|
|
offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1);
|
|
|
|
if (offset >= 0) {
|
|
|
|
raw_ne = nat_in_journal(sum, offset);
|
|
|
|
goto flush_now;
|
|
|
|
}
|
|
|
|
to_nat_page:
|
|
|
|
if (!page || (start_nid > nid || nid > end_nid)) {
|
|
|
|
if (page) {
|
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
page = NULL;
|
|
|
|
}
|
|
|
|
start_nid = START_NID(nid);
|
|
|
|
end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* get nat block with dirty flag, increased reference
|
|
|
|
* count, mapped and lock
|
|
|
|
*/
|
|
|
|
page = get_next_nat_page(sbi, start_nid);
|
|
|
|
nat_blk = page_address(page);
|
|
|
|
}
|
|
|
|
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(!nat_blk);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
raw_ne = nat_blk->entries[nid - start_nid];
|
|
|
|
flush_now:
|
|
|
|
new_blkaddr = nat_get_blkaddr(ne);
|
|
|
|
|
|
|
|
raw_ne.ino = cpu_to_le32(nat_get_ino(ne));
|
|
|
|
raw_ne.block_addr = cpu_to_le32(new_blkaddr);
|
|
|
|
raw_ne.version = nat_get_version(ne);
|
|
|
|
|
|
|
|
if (offset < 0) {
|
|
|
|
nat_blk->entries[nid - start_nid] = raw_ne;
|
|
|
|
} else {
|
|
|
|
nat_in_journal(sum, offset) = raw_ne;
|
|
|
|
nid_in_journal(sum, offset) = cpu_to_le32(nid);
|
|
|
|
}
|
|
|
|
|
2013-03-21 03:53:19 +00:00
|
|
|
if (nat_get_blkaddr(ne) == NULL_ADDR &&
|
2013-05-07 11:47:40 +00:00
|
|
|
add_free_nid(NM_I(sbi), nid, false) <= 0) {
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
__del_from_nat_cache(nm_i, ne);
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
} else {
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
__clear_nat_cache_dirty(nm_i, ne);
|
|
|
|
ne->checkpointed = true;
|
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!flushed)
|
|
|
|
mutex_unlock(&curseg->curseg_mutex);
|
|
|
|
f2fs_put_page(page, 1);
|
|
|
|
|
|
|
|
/* 2) shrink nat caches if necessary */
|
|
|
|
try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int init_node_manager(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi);
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
unsigned char *version_bitmap;
|
|
|
|
unsigned int nat_segs, nat_blocks;
|
|
|
|
|
|
|
|
nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr);
|
|
|
|
|
|
|
|
/* segment_count_nat includes pair segment so divide to 2. */
|
|
|
|
nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1;
|
|
|
|
nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg);
|
|
|
|
nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
|
|
|
|
nm_i->fcnt = 0;
|
|
|
|
nm_i->nat_cnt = 0;
|
|
|
|
|
|
|
|
INIT_LIST_HEAD(&nm_i->free_nid_list);
|
|
|
|
INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC);
|
|
|
|
INIT_LIST_HEAD(&nm_i->nat_entries);
|
|
|
|
INIT_LIST_HEAD(&nm_i->dirty_nat_entries);
|
|
|
|
|
|
|
|
mutex_init(&nm_i->build_lock);
|
|
|
|
spin_lock_init(&nm_i->free_nid_list_lock);
|
|
|
|
rwlock_init(&nm_i->nat_tree_lock);
|
|
|
|
|
|
|
|
nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
|
2013-03-28 00:24:53 +00:00
|
|
|
nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
|
|
|
|
if (!version_bitmap)
|
|
|
|
return -EFAULT;
|
|
|
|
|
2013-03-28 00:24:53 +00:00
|
|
|
nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size,
|
|
|
|
GFP_KERNEL);
|
|
|
|
if (!nm_i->nat_bitmap)
|
|
|
|
return -ENOMEM;
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int build_node_manager(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
int err;
|
|
|
|
|
|
|
|
sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL);
|
|
|
|
if (!sbi->nm_info)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
err = init_node_manager(sbi);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
build_free_nids(sbi);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroy_node_manager(struct f2fs_sb_info *sbi)
|
|
|
|
{
|
|
|
|
struct f2fs_nm_info *nm_i = NM_I(sbi);
|
|
|
|
struct free_nid *i, *next_i;
|
|
|
|
struct nat_entry *natvec[NATVEC_SIZE];
|
|
|
|
nid_t nid = 0;
|
|
|
|
unsigned int found;
|
|
|
|
|
|
|
|
if (!nm_i)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* destroy free nid list */
|
|
|
|
spin_lock(&nm_i->free_nid_list_lock);
|
|
|
|
list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) {
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(i->state == NID_ALLOC);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
__del_from_free_nid_list(i);
|
|
|
|
nm_i->fcnt--;
|
|
|
|
}
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nm_i->fcnt);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
spin_unlock(&nm_i->free_nid_list_lock);
|
|
|
|
|
|
|
|
/* destroy nat cache */
|
|
|
|
write_lock(&nm_i->nat_tree_lock);
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2013-10-29 06:14:54 +00:00
|
|
|
f2fs_bug_on(nm_i->nat_cnt);
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
write_unlock(&nm_i->nat_tree_lock);
|
|
|
|
|
|
|
|
kfree(nm_i->nat_bitmap);
|
|
|
|
sbi->nm_info = NULL;
|
|
|
|
kfree(nm_i);
|
|
|
|
}
|
|
|
|
|
2013-01-16 15:08:30 +00:00
|
|
|
int __init create_node_manager_caches(void)
|
f2fs: add node operations
This adds specific functions to manage NAT pages, a cache for NAT entries, free
nids, direct/indirect node blocks for indexing data, and address space for node
pages.
- The key information of an NAT entry consists of a node id and a block address.
- An NAT page is composed of block addresses covered by a certain range of NAT
entries, which is maintained by the address space of meta_inode.
- A radix tree structure is used to cache NAT entries. The index for the tree
is a node id.
- When there is no free nid, F2FS should scan NAT entries to find new one. In
order to avoid scanning frequently, F2FS manages a list containing a number of
free nids in memory. Only when free nids in the list are exhausted, scanning
process, build_free_nids(), is triggered.
- F2FS has direct and indirect node blocks for indexing data. This patch adds
fuctions related to the node block management such as getting, allocating, and
truncating node blocks to index data.
- In order to cache node blocks in memory, F2FS has a node_inode with an address
space for node pages. This patch also adds the address space operations for
node_inode.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
2012-11-02 08:08:50 +00:00
|
|
|
{
|
|
|
|
nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
|
|
|
|
sizeof(struct nat_entry), NULL);
|
|
|
|
if (!nat_entry_slab)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
free_nid_slab = f2fs_kmem_cache_create("free_nid",
|
|
|
|
sizeof(struct free_nid), NULL);
|
|
|
|
if (!free_nid_slab) {
|
|
|
|
kmem_cache_destroy(nat_entry_slab);
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void destroy_node_manager_caches(void)
|
|
|
|
{
|
|
|
|
kmem_cache_destroy(free_nid_slab);
|
|
|
|
kmem_cache_destroy(nat_entry_slab);
|
|
|
|
}
|