diff options
-rw-r--r-- | Documentation/ABI/testing/sysfs-fs-f2fs | 6 | ||||
-rw-r--r-- | Documentation/filesystems/f2fs.txt | 4 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 1 | ||||
-rw-r--r-- | fs/f2fs/node.c | 23 | ||||
-rw-r--r-- | fs/f2fs/node.h | 11 | ||||
-rw-r--r-- | fs/f2fs/super.c | 5 |
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 | |||
55 | Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> | 55 | Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> |
56 | Description: | 56 | Description: |
57 | Controls the number of trials to find a victim segment. | 57 | Controls the number of trials to find a victim segment. |
58 | |||
59 | What: /sys/fs/f2fs/<disk>/ram_thresh | ||
60 | Date: March 2014 | ||
61 | Contact: "Jaegeuk Kim" <jaegeuk.kim@samsung.com> | ||
62 | Description: | ||
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 | ================================================================================ |
206 | USAGE | 210 | USAGE |
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 @@ | |||
26 | static struct kmem_cache *nat_entry_slab; | 26 | static struct kmem_cache *nat_entry_slab; |
27 | static struct kmem_cache *free_nid_slab; | 27 | static struct kmem_cache *free_nid_slab; |
28 | 28 | ||
29 | static inline bool available_free_memory(struct f2fs_nm_info *nm_i, int type) | ||
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 | |||
29 | static void clear_node_page_dirty(struct page *page) | 45 | static 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 | ||
80 | enum 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 = { | |||
74 | enum { | 74 | enum { |
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); | |||
183 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); | 186 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); |
184 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); | 187 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); |
185 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); | 188 | F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); |
189 | F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh); | ||
186 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); | 190 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); |
187 | F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); | 191 | F2FS_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 | ||