aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-fs-f2fs6
-rw-r--r--Documentation/filesystems/f2fs.txt4
-rw-r--r--fs/f2fs/f2fs.h1
-rw-r--r--fs/f2fs/node.c23
-rw-r--r--fs/f2fs/node.h11
-rw-r--r--fs/f2fs/super.c5
6 files changed, 44 insertions, 6 deletions
diff --git a/Documentation/ABI/testing/sysfs-fs-f2fs b/Documentation/ABI/testing/sysfs-fs-f2fs
index 32b0809203dd..4ac2c25025ea 100644
--- a/Documentation/ABI/testing/sysfs-fs-f2fs
+++ b/Documentation/ABI/testing/sysfs-fs-f2fs
@@ -55,3 +55,9 @@ Date: January 2014
55Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> 55Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
56Description: 56Description:
57 Controls the number of trials to find a victim segment. 57 Controls the number of trials to find a victim segment.
58
59What: /sys/fs/f2fs/<disk>/ram_thresh
60Date: March 2014
61Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com>
62Description:
63 Controls the memory footprint used by f2fs.
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 803784e1e8ef..f415b9fc4cc8 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -202,6 +202,10 @@ Files in /sys/fs/f2fs/<devname>
202 Otherwise, it needs to decrease this value to 202 Otherwise, it needs to decrease this value to
203 reduce the space overhead. The default value is 0. 203 reduce the space overhead. The default value is 0.
204 204
205 ram_thresh This parameter controls the memory footprint used
206 by free nids and cached nat entries. By default,
207 10 is set, which indicates 10 MB / 1 GB RAM.
208
205================================================================================ 209================================================================================
206USAGE 210USAGE
207================================================================================ 211================================================================================
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 59fac1a9f0c2..05c652493f04 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -242,6 +242,7 @@ struct f2fs_nm_info {
242 block_t nat_blkaddr; /* base disk address of NAT */ 242 block_t nat_blkaddr; /* base disk address of NAT */
243 nid_t max_nid; /* maximum possible node ids */ 243 nid_t max_nid; /* maximum possible node ids */
244 nid_t next_scan_nid; /* the next nid to be scanned */ 244 nid_t next_scan_nid; /* the next nid to be scanned */
245 unsigned int ram_thresh; /* control the memory footprint */
245 246
246 /* NAT cache management */ 247 /* NAT cache management */
247 struct radix_tree_root nat_root;/* root of the nat entry cache */ 248 struct radix_tree_root nat_root;/* root of the nat entry cache */
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);
diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h
index ee6d28684ee8..c97215432100 100644
--- a/fs/f2fs/node.h
+++ b/fs/f2fs/node.h
@@ -17,15 +17,15 @@
17/* # of pages to perform readahead before building free nids */ 17/* # of pages to perform readahead before building free nids */
18#define FREE_NID_PAGES 4 18#define FREE_NID_PAGES 4
19 19
20/* maximum # of free node ids to produce during build_free_nids */
21#define MAX_FREE_NIDS (NAT_ENTRY_PER_BLOCK * FREE_NID_PAGES)
22
23/* maximum readahead size for node during getting data blocks */ 20/* maximum readahead size for node during getting data blocks */
24#define MAX_RA_NODE 128 21#define MAX_RA_NODE 128
25 22
26/* maximum cached nat entries to manage memory footprint */ 23/* maximum cached nat entries to manage memory footprint */
27#define NM_WOUT_THRESHOLD (64 * NAT_ENTRY_PER_BLOCK) 24#define NM_WOUT_THRESHOLD (64 * NAT_ENTRY_PER_BLOCK)
28 25
26/* control the memory footprint threshold (10MB per 1GB ram) */
27#define DEF_RAM_THRESHOLD 10
28
29/* vector size for gang look-up from nat cache that consists of radix tree */ 29/* vector size for gang look-up from nat cache that consists of radix tree */
30#define NATVEC_SIZE 64 30#define NATVEC_SIZE 64
31 31
@@ -77,6 +77,11 @@ static inline void node_info_from_raw_nat(struct node_info *ni,
77 ni->version = raw_ne->version; 77 ni->version = raw_ne->version;
78} 78}
79 79
80enum nid_type {
81 FREE_NIDS, /* indicates the free nid list */
82 NAT_ENTRIES /* indicates the cached nat entry */
83};
84
80/* 85/*
81 * For free nid mangement 86 * For free nid mangement
82 */ 87 */
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index dbe402b1a4b7..34c47b2010bc 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -74,6 +74,7 @@ static match_table_t f2fs_tokens = {
74enum { 74enum {
75 GC_THREAD, /* struct f2fs_gc_thread */ 75 GC_THREAD, /* struct f2fs_gc_thread */
76 SM_INFO, /* struct f2fs_sm_info */ 76 SM_INFO, /* struct f2fs_sm_info */
77 NM_INFO, /* struct f2fs_nm_info */
77 F2FS_SBI, /* struct f2fs_sb_info */ 78 F2FS_SBI, /* struct f2fs_sb_info */
78}; 79};
79 80
@@ -92,6 +93,8 @@ static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type)
92 return (unsigned char *)sbi->gc_thread; 93 return (unsigned char *)sbi->gc_thread;
93 else if (struct_type == SM_INFO) 94 else if (struct_type == SM_INFO)
94 return (unsigned char *)SM_I(sbi); 95 return (unsigned char *)SM_I(sbi);
96 else if (struct_type == NM_INFO)
97 return (unsigned char *)NM_I(sbi);
95 else if (struct_type == F2FS_SBI) 98 else if (struct_type == F2FS_SBI)
96 return (unsigned char *)sbi; 99 return (unsigned char *)sbi;
97 return NULL; 100 return NULL;
@@ -183,6 +186,7 @@ F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments);
183F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); 186F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards);
184F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); 187F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy);
185F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); 188F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util);
189F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh);
186F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); 190F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search);
187F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); 191F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level);
188 192
@@ -198,6 +202,7 @@ static struct attribute *f2fs_attrs[] = {
198 ATTR_LIST(min_ipu_util), 202 ATTR_LIST(min_ipu_util),
199 ATTR_LIST(max_victim_search), 203 ATTR_LIST(max_victim_search),
200 ATTR_LIST(dir_level), 204 ATTR_LIST(dir_level),
205 ATTR_LIST(ram_thresh),
201 NULL, 206 NULL,
202}; 207};
203 208