aboutsummaryrefslogtreecommitdiffstats
path: root/fs/f2fs/node.c
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2014-03-19 00:31:37 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2014-03-20 09:10:09 -0400
commitcdfc41c134d48c1923066bcfa6630b94588ad6bc (patch)
tree066af8a1d30379162ed299f3d30275f6e4809ab0 /fs/f2fs/node.c
parent40bb0058c871c6ddcd4aff9fe2f5224e59aba47b (diff)
f2fs: throttle the memory footprint with a sysfs entry
This patch introduces ram_thresh, a sysfs entry, which controls the memory footprint used by the free nid list and the nat cache. Previously, the free nid list was controlled by MAX_FREE_NIDS, while the nat cache was managed by NM_WOUT_THRESHOLD. However, this approach cannot be applied dynamically according to the system. So, this patch adds ram_thresh that users can specify the threshold, which is in order of 1 / 1024. For example, if the total ram size is 4GB and the value is set to 10 by default, f2fs tries to control the number of free nids and nat caches not to consume over 10 * (4GB / 1024) = 10MB. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/node.c')
-rw-r--r--fs/f2fs/node.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index d27e65a1fb0b..fec4967fb8d2 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -26,6 +26,22 @@
26static struct kmem_cache *nat_entry_slab; 26static struct kmem_cache *nat_entry_slab;
27static struct kmem_cache *free_nid_slab; 27static struct kmem_cache *free_nid_slab;
28 28
29static inline bool available_free_memory(struct f2fs_nm_info *nm_i, int type)
30{
31 struct sysinfo val;
32 unsigned long mem_size = 0;
33
34 si_meminfo(&val);
35 if (type == FREE_NIDS)
36 mem_size = nm_i->fcnt * sizeof(struct free_nid);
37 else if (type == NAT_ENTRIES)
38 mem_size += nm_i->nat_cnt * sizeof(struct nat_entry);
39 mem_size >>= 12;
40
41 /* give 50:50 memory for free nids and nat caches respectively */
42 return (mem_size < ((val.totalram * nm_i->ram_thresh) >> 11));
43}
44
29static void clear_node_page_dirty(struct page *page) 45static void clear_node_page_dirty(struct page *page)
30{ 46{
31 struct address_space *mapping = page->mapping; 47 struct address_space *mapping = page->mapping;
@@ -208,7 +224,7 @@ int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
208{ 224{
209 struct f2fs_nm_info *nm_i = NM_I(sbi); 225 struct f2fs_nm_info *nm_i = NM_I(sbi);
210 226
211 if (nm_i->nat_cnt <= NM_WOUT_THRESHOLD || nr_shrink <= 0) 227 if (available_free_memory(nm_i, NAT_ENTRIES) || nr_shrink <= 0)
212 return 0; 228 return 0;
213 229
214 write_lock(&nm_i->nat_tree_lock); 230 write_lock(&nm_i->nat_tree_lock);
@@ -1288,7 +1304,7 @@ static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid, bool build)
1288 struct nat_entry *ne; 1304 struct nat_entry *ne;
1289 bool allocated = false; 1305 bool allocated = false;
1290 1306
1291 if (nm_i->fcnt > 2 * MAX_FREE_NIDS) 1307 if (!available_free_memory(nm_i, FREE_NIDS))
1292 return -1; 1308 return -1;
1293 1309
1294 /* 0 nid should not be used */ 1310 /* 0 nid should not be used */
@@ -1473,7 +1489,7 @@ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid)
1473 spin_lock(&nm_i->free_nid_list_lock); 1489 spin_lock(&nm_i->free_nid_list_lock);
1474 i = __lookup_free_nid_list(nm_i, nid); 1490 i = __lookup_free_nid_list(nm_i, nid);
1475 f2fs_bug_on(!i || i->state != NID_ALLOC); 1491 f2fs_bug_on(!i || i->state != NID_ALLOC);
1476 if (nm_i->fcnt > 2 * MAX_FREE_NIDS) { 1492 if (!available_free_memory(nm_i, FREE_NIDS)) {
1477 __del_from_free_nid_list(nm_i, i); 1493 __del_from_free_nid_list(nm_i, i);
1478 } else { 1494 } else {
1479 i->state = NID_NEW; 1495 i->state = NID_NEW;
@@ -1836,6 +1852,7 @@ static int init_node_manager(struct f2fs_sb_info *sbi)
1836 nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks - 3; 1852 nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks - 3;
1837 nm_i->fcnt = 0; 1853 nm_i->fcnt = 0;
1838 nm_i->nat_cnt = 0; 1854 nm_i->nat_cnt = 0;
1855 nm_i->ram_thresh = DEF_RAM_THRESHOLD;
1839 1856
1840 INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC); 1857 INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC);
1841 INIT_LIST_HEAD(&nm_i->free_nid_list); 1858 INIT_LIST_HEAD(&nm_i->free_nid_list);