Commit ac5d156c78a68b39955ee9b09498ba93831c77d7
1 parent
b743ba78ae
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
f2fs: modify the number of issued pages to merge IOs
When testing f2fs on an SSD, I found some 128 page IOs followed by 1 page IO were issued by f2fs_write_node_pages. This means that there were some mishandling flows which degrades performance. Previous f2fs_write_node_pages determines the number of pages to be written, nr_to_write, as follows. 1. The bio_get_nr_vecs returns 129 pages. 2. The bio_alloc makes a room for 128 pages. 3. The initial 128 pages go into one bio. 4. The existing bio is submitted, and a new bio is prepared for the last 1 page. 5. Finally, sync_node_pages submits the last 1 page bio. The problem is from the use of bio_get_nr_vecs, so this patch replace it with max_hw_blocks using queue_max_sectors. Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Showing 3 changed files with 14 additions and 5 deletions Inline Diff
fs/f2fs/node.c
1 | /* | 1 | /* |
2 | * fs/f2fs/node.c | 2 | * fs/f2fs/node.c |
3 | * | 3 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 5 | * http://www.samsung.com/ |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 12 | #include <linux/f2fs_fs.h> |
13 | #include <linux/mpage.h> | 13 | #include <linux/mpage.h> |
14 | #include <linux/backing-dev.h> | 14 | #include <linux/backing-dev.h> |
15 | #include <linux/blkdev.h> | 15 | #include <linux/blkdev.h> |
16 | #include <linux/pagevec.h> | 16 | #include <linux/pagevec.h> |
17 | #include <linux/swap.h> | 17 | #include <linux/swap.h> |
18 | 18 | ||
19 | #include "f2fs.h" | 19 | #include "f2fs.h" |
20 | #include "node.h" | 20 | #include "node.h" |
21 | #include "segment.h" | 21 | #include "segment.h" |
22 | #include <trace/events/f2fs.h> | 22 | #include <trace/events/f2fs.h> |
23 | 23 | ||
24 | static struct kmem_cache *nat_entry_slab; | 24 | static struct kmem_cache *nat_entry_slab; |
25 | static struct kmem_cache *free_nid_slab; | 25 | static struct kmem_cache *free_nid_slab; |
26 | 26 | ||
27 | static void clear_node_page_dirty(struct page *page) | 27 | static void clear_node_page_dirty(struct page *page) |
28 | { | 28 | { |
29 | struct address_space *mapping = page->mapping; | 29 | struct address_space *mapping = page->mapping; |
30 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 30 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
31 | unsigned int long flags; | 31 | unsigned int long flags; |
32 | 32 | ||
33 | if (PageDirty(page)) { | 33 | if (PageDirty(page)) { |
34 | spin_lock_irqsave(&mapping->tree_lock, flags); | 34 | spin_lock_irqsave(&mapping->tree_lock, flags); |
35 | radix_tree_tag_clear(&mapping->page_tree, | 35 | radix_tree_tag_clear(&mapping->page_tree, |
36 | page_index(page), | 36 | page_index(page), |
37 | PAGECACHE_TAG_DIRTY); | 37 | PAGECACHE_TAG_DIRTY); |
38 | spin_unlock_irqrestore(&mapping->tree_lock, flags); | 38 | spin_unlock_irqrestore(&mapping->tree_lock, flags); |
39 | 39 | ||
40 | clear_page_dirty_for_io(page); | 40 | clear_page_dirty_for_io(page); |
41 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 41 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
42 | } | 42 | } |
43 | ClearPageUptodate(page); | 43 | ClearPageUptodate(page); |
44 | } | 44 | } |
45 | 45 | ||
46 | static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) | 46 | static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) |
47 | { | 47 | { |
48 | pgoff_t index = current_nat_addr(sbi, nid); | 48 | pgoff_t index = current_nat_addr(sbi, nid); |
49 | return get_meta_page(sbi, index); | 49 | return get_meta_page(sbi, index); |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) | 52 | static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) |
53 | { | 53 | { |
54 | struct page *src_page; | 54 | struct page *src_page; |
55 | struct page *dst_page; | 55 | struct page *dst_page; |
56 | pgoff_t src_off; | 56 | pgoff_t src_off; |
57 | pgoff_t dst_off; | 57 | pgoff_t dst_off; |
58 | void *src_addr; | 58 | void *src_addr; |
59 | void *dst_addr; | 59 | void *dst_addr; |
60 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 60 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
61 | 61 | ||
62 | src_off = current_nat_addr(sbi, nid); | 62 | src_off = current_nat_addr(sbi, nid); |
63 | dst_off = next_nat_addr(sbi, src_off); | 63 | dst_off = next_nat_addr(sbi, src_off); |
64 | 64 | ||
65 | /* get current nat block page with lock */ | 65 | /* get current nat block page with lock */ |
66 | src_page = get_meta_page(sbi, src_off); | 66 | src_page = get_meta_page(sbi, src_off); |
67 | 67 | ||
68 | /* Dirty src_page means that it is already the new target NAT page. */ | 68 | /* Dirty src_page means that it is already the new target NAT page. */ |
69 | if (PageDirty(src_page)) | 69 | if (PageDirty(src_page)) |
70 | return src_page; | 70 | return src_page; |
71 | 71 | ||
72 | dst_page = grab_meta_page(sbi, dst_off); | 72 | dst_page = grab_meta_page(sbi, dst_off); |
73 | 73 | ||
74 | src_addr = page_address(src_page); | 74 | src_addr = page_address(src_page); |
75 | dst_addr = page_address(dst_page); | 75 | dst_addr = page_address(dst_page); |
76 | memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); | 76 | memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); |
77 | set_page_dirty(dst_page); | 77 | set_page_dirty(dst_page); |
78 | f2fs_put_page(src_page, 1); | 78 | f2fs_put_page(src_page, 1); |
79 | 79 | ||
80 | set_to_next_nat(nm_i, nid); | 80 | set_to_next_nat(nm_i, nid); |
81 | 81 | ||
82 | return dst_page; | 82 | return dst_page; |
83 | } | 83 | } |
84 | 84 | ||
85 | /* | 85 | /* |
86 | * Readahead NAT pages | 86 | * Readahead NAT pages |
87 | */ | 87 | */ |
88 | static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) | 88 | static void ra_nat_pages(struct f2fs_sb_info *sbi, int nid) |
89 | { | 89 | { |
90 | struct address_space *mapping = sbi->meta_inode->i_mapping; | 90 | struct address_space *mapping = sbi->meta_inode->i_mapping; |
91 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 91 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
92 | struct blk_plug plug; | 92 | struct blk_plug plug; |
93 | struct page *page; | 93 | struct page *page; |
94 | pgoff_t index; | 94 | pgoff_t index; |
95 | int i; | 95 | int i; |
96 | 96 | ||
97 | blk_start_plug(&plug); | 97 | blk_start_plug(&plug); |
98 | 98 | ||
99 | for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) { | 99 | for (i = 0; i < FREE_NID_PAGES; i++, nid += NAT_ENTRY_PER_BLOCK) { |
100 | if (nid >= nm_i->max_nid) | 100 | if (nid >= nm_i->max_nid) |
101 | nid = 0; | 101 | nid = 0; |
102 | index = current_nat_addr(sbi, nid); | 102 | index = current_nat_addr(sbi, nid); |
103 | 103 | ||
104 | page = grab_cache_page(mapping, index); | 104 | page = grab_cache_page(mapping, index); |
105 | if (!page) | 105 | if (!page) |
106 | continue; | 106 | continue; |
107 | if (PageUptodate(page)) { | 107 | if (PageUptodate(page)) { |
108 | f2fs_put_page(page, 1); | 108 | f2fs_put_page(page, 1); |
109 | continue; | 109 | continue; |
110 | } | 110 | } |
111 | if (f2fs_readpage(sbi, page, index, READ)) | 111 | if (f2fs_readpage(sbi, page, index, READ)) |
112 | continue; | 112 | continue; |
113 | 113 | ||
114 | f2fs_put_page(page, 0); | 114 | f2fs_put_page(page, 0); |
115 | } | 115 | } |
116 | blk_finish_plug(&plug); | 116 | blk_finish_plug(&plug); |
117 | } | 117 | } |
118 | 118 | ||
119 | static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) | 119 | static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) |
120 | { | 120 | { |
121 | return radix_tree_lookup(&nm_i->nat_root, n); | 121 | return radix_tree_lookup(&nm_i->nat_root, n); |
122 | } | 122 | } |
123 | 123 | ||
124 | static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, | 124 | static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, |
125 | nid_t start, unsigned int nr, struct nat_entry **ep) | 125 | nid_t start, unsigned int nr, struct nat_entry **ep) |
126 | { | 126 | { |
127 | return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); | 127 | return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); |
128 | } | 128 | } |
129 | 129 | ||
130 | static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) | 130 | static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) |
131 | { | 131 | { |
132 | list_del(&e->list); | 132 | list_del(&e->list); |
133 | radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); | 133 | radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); |
134 | nm_i->nat_cnt--; | 134 | nm_i->nat_cnt--; |
135 | kmem_cache_free(nat_entry_slab, e); | 135 | kmem_cache_free(nat_entry_slab, e); |
136 | } | 136 | } |
137 | 137 | ||
138 | int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) | 138 | int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) |
139 | { | 139 | { |
140 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 140 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
141 | struct nat_entry *e; | 141 | struct nat_entry *e; |
142 | int is_cp = 1; | 142 | int is_cp = 1; |
143 | 143 | ||
144 | read_lock(&nm_i->nat_tree_lock); | 144 | read_lock(&nm_i->nat_tree_lock); |
145 | e = __lookup_nat_cache(nm_i, nid); | 145 | e = __lookup_nat_cache(nm_i, nid); |
146 | if (e && !e->checkpointed) | 146 | if (e && !e->checkpointed) |
147 | is_cp = 0; | 147 | is_cp = 0; |
148 | read_unlock(&nm_i->nat_tree_lock); | 148 | read_unlock(&nm_i->nat_tree_lock); |
149 | return is_cp; | 149 | return is_cp; |
150 | } | 150 | } |
151 | 151 | ||
152 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) | 152 | static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) |
153 | { | 153 | { |
154 | struct nat_entry *new; | 154 | struct nat_entry *new; |
155 | 155 | ||
156 | new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC); | 156 | new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC); |
157 | if (!new) | 157 | if (!new) |
158 | return NULL; | 158 | return NULL; |
159 | if (radix_tree_insert(&nm_i->nat_root, nid, new)) { | 159 | if (radix_tree_insert(&nm_i->nat_root, nid, new)) { |
160 | kmem_cache_free(nat_entry_slab, new); | 160 | kmem_cache_free(nat_entry_slab, new); |
161 | return NULL; | 161 | return NULL; |
162 | } | 162 | } |
163 | memset(new, 0, sizeof(struct nat_entry)); | 163 | memset(new, 0, sizeof(struct nat_entry)); |
164 | nat_set_nid(new, nid); | 164 | nat_set_nid(new, nid); |
165 | list_add_tail(&new->list, &nm_i->nat_entries); | 165 | list_add_tail(&new->list, &nm_i->nat_entries); |
166 | nm_i->nat_cnt++; | 166 | nm_i->nat_cnt++; |
167 | return new; | 167 | return new; |
168 | } | 168 | } |
169 | 169 | ||
170 | static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid, | 170 | static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid, |
171 | struct f2fs_nat_entry *ne) | 171 | struct f2fs_nat_entry *ne) |
172 | { | 172 | { |
173 | struct nat_entry *e; | 173 | struct nat_entry *e; |
174 | retry: | 174 | retry: |
175 | write_lock(&nm_i->nat_tree_lock); | 175 | write_lock(&nm_i->nat_tree_lock); |
176 | e = __lookup_nat_cache(nm_i, nid); | 176 | e = __lookup_nat_cache(nm_i, nid); |
177 | if (!e) { | 177 | if (!e) { |
178 | e = grab_nat_entry(nm_i, nid); | 178 | e = grab_nat_entry(nm_i, nid); |
179 | if (!e) { | 179 | if (!e) { |
180 | write_unlock(&nm_i->nat_tree_lock); | 180 | write_unlock(&nm_i->nat_tree_lock); |
181 | goto retry; | 181 | goto retry; |
182 | } | 182 | } |
183 | nat_set_blkaddr(e, le32_to_cpu(ne->block_addr)); | 183 | nat_set_blkaddr(e, le32_to_cpu(ne->block_addr)); |
184 | nat_set_ino(e, le32_to_cpu(ne->ino)); | 184 | nat_set_ino(e, le32_to_cpu(ne->ino)); |
185 | nat_set_version(e, ne->version); | 185 | nat_set_version(e, ne->version); |
186 | e->checkpointed = true; | 186 | e->checkpointed = true; |
187 | } | 187 | } |
188 | write_unlock(&nm_i->nat_tree_lock); | 188 | write_unlock(&nm_i->nat_tree_lock); |
189 | } | 189 | } |
190 | 190 | ||
191 | static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, | 191 | static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, |
192 | block_t new_blkaddr) | 192 | block_t new_blkaddr) |
193 | { | 193 | { |
194 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 194 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
195 | struct nat_entry *e; | 195 | struct nat_entry *e; |
196 | retry: | 196 | retry: |
197 | write_lock(&nm_i->nat_tree_lock); | 197 | write_lock(&nm_i->nat_tree_lock); |
198 | e = __lookup_nat_cache(nm_i, ni->nid); | 198 | e = __lookup_nat_cache(nm_i, ni->nid); |
199 | if (!e) { | 199 | if (!e) { |
200 | e = grab_nat_entry(nm_i, ni->nid); | 200 | e = grab_nat_entry(nm_i, ni->nid); |
201 | if (!e) { | 201 | if (!e) { |
202 | write_unlock(&nm_i->nat_tree_lock); | 202 | write_unlock(&nm_i->nat_tree_lock); |
203 | goto retry; | 203 | goto retry; |
204 | } | 204 | } |
205 | e->ni = *ni; | 205 | e->ni = *ni; |
206 | e->checkpointed = true; | 206 | e->checkpointed = true; |
207 | BUG_ON(ni->blk_addr == NEW_ADDR); | 207 | BUG_ON(ni->blk_addr == NEW_ADDR); |
208 | } else if (new_blkaddr == NEW_ADDR) { | 208 | } else if (new_blkaddr == NEW_ADDR) { |
209 | /* | 209 | /* |
210 | * when nid is reallocated, | 210 | * when nid is reallocated, |
211 | * previous nat entry can be remained in nat cache. | 211 | * previous nat entry can be remained in nat cache. |
212 | * So, reinitialize it with new information. | 212 | * So, reinitialize it with new information. |
213 | */ | 213 | */ |
214 | e->ni = *ni; | 214 | e->ni = *ni; |
215 | BUG_ON(ni->blk_addr != NULL_ADDR); | 215 | BUG_ON(ni->blk_addr != NULL_ADDR); |
216 | } | 216 | } |
217 | 217 | ||
218 | if (new_blkaddr == NEW_ADDR) | 218 | if (new_blkaddr == NEW_ADDR) |
219 | e->checkpointed = false; | 219 | e->checkpointed = false; |
220 | 220 | ||
221 | /* sanity check */ | 221 | /* sanity check */ |
222 | BUG_ON(nat_get_blkaddr(e) != ni->blk_addr); | 222 | BUG_ON(nat_get_blkaddr(e) != ni->blk_addr); |
223 | BUG_ON(nat_get_blkaddr(e) == NULL_ADDR && | 223 | BUG_ON(nat_get_blkaddr(e) == NULL_ADDR && |
224 | new_blkaddr == NULL_ADDR); | 224 | new_blkaddr == NULL_ADDR); |
225 | BUG_ON(nat_get_blkaddr(e) == NEW_ADDR && | 225 | BUG_ON(nat_get_blkaddr(e) == NEW_ADDR && |
226 | new_blkaddr == NEW_ADDR); | 226 | new_blkaddr == NEW_ADDR); |
227 | BUG_ON(nat_get_blkaddr(e) != NEW_ADDR && | 227 | BUG_ON(nat_get_blkaddr(e) != NEW_ADDR && |
228 | nat_get_blkaddr(e) != NULL_ADDR && | 228 | nat_get_blkaddr(e) != NULL_ADDR && |
229 | new_blkaddr == NEW_ADDR); | 229 | new_blkaddr == NEW_ADDR); |
230 | 230 | ||
231 | /* increament version no as node is removed */ | 231 | /* increament version no as node is removed */ |
232 | if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { | 232 | if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { |
233 | unsigned char version = nat_get_version(e); | 233 | unsigned char version = nat_get_version(e); |
234 | nat_set_version(e, inc_node_version(version)); | 234 | nat_set_version(e, inc_node_version(version)); |
235 | } | 235 | } |
236 | 236 | ||
237 | /* change address */ | 237 | /* change address */ |
238 | nat_set_blkaddr(e, new_blkaddr); | 238 | nat_set_blkaddr(e, new_blkaddr); |
239 | __set_nat_cache_dirty(nm_i, e); | 239 | __set_nat_cache_dirty(nm_i, e); |
240 | write_unlock(&nm_i->nat_tree_lock); | 240 | write_unlock(&nm_i->nat_tree_lock); |
241 | } | 241 | } |
242 | 242 | ||
243 | static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) | 243 | static int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) |
244 | { | 244 | { |
245 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 245 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
246 | 246 | ||
247 | if (nm_i->nat_cnt <= NM_WOUT_THRESHOLD) | 247 | if (nm_i->nat_cnt <= NM_WOUT_THRESHOLD) |
248 | return 0; | 248 | return 0; |
249 | 249 | ||
250 | write_lock(&nm_i->nat_tree_lock); | 250 | write_lock(&nm_i->nat_tree_lock); |
251 | while (nr_shrink && !list_empty(&nm_i->nat_entries)) { | 251 | while (nr_shrink && !list_empty(&nm_i->nat_entries)) { |
252 | struct nat_entry *ne; | 252 | struct nat_entry *ne; |
253 | ne = list_first_entry(&nm_i->nat_entries, | 253 | ne = list_first_entry(&nm_i->nat_entries, |
254 | struct nat_entry, list); | 254 | struct nat_entry, list); |
255 | __del_from_nat_cache(nm_i, ne); | 255 | __del_from_nat_cache(nm_i, ne); |
256 | nr_shrink--; | 256 | nr_shrink--; |
257 | } | 257 | } |
258 | write_unlock(&nm_i->nat_tree_lock); | 258 | write_unlock(&nm_i->nat_tree_lock); |
259 | return nr_shrink; | 259 | return nr_shrink; |
260 | } | 260 | } |
261 | 261 | ||
262 | /* | 262 | /* |
263 | * This function returns always success | 263 | * This function returns always success |
264 | */ | 264 | */ |
265 | void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) | 265 | void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) |
266 | { | 266 | { |
267 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 267 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
268 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 268 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
269 | struct f2fs_summary_block *sum = curseg->sum_blk; | 269 | struct f2fs_summary_block *sum = curseg->sum_blk; |
270 | nid_t start_nid = START_NID(nid); | 270 | nid_t start_nid = START_NID(nid); |
271 | struct f2fs_nat_block *nat_blk; | 271 | struct f2fs_nat_block *nat_blk; |
272 | struct page *page = NULL; | 272 | struct page *page = NULL; |
273 | struct f2fs_nat_entry ne; | 273 | struct f2fs_nat_entry ne; |
274 | struct nat_entry *e; | 274 | struct nat_entry *e; |
275 | int i; | 275 | int i; |
276 | 276 | ||
277 | memset(&ne, 0, sizeof(struct f2fs_nat_entry)); | 277 | memset(&ne, 0, sizeof(struct f2fs_nat_entry)); |
278 | ni->nid = nid; | 278 | ni->nid = nid; |
279 | 279 | ||
280 | /* Check nat cache */ | 280 | /* Check nat cache */ |
281 | read_lock(&nm_i->nat_tree_lock); | 281 | read_lock(&nm_i->nat_tree_lock); |
282 | e = __lookup_nat_cache(nm_i, nid); | 282 | e = __lookup_nat_cache(nm_i, nid); |
283 | if (e) { | 283 | if (e) { |
284 | ni->ino = nat_get_ino(e); | 284 | ni->ino = nat_get_ino(e); |
285 | ni->blk_addr = nat_get_blkaddr(e); | 285 | ni->blk_addr = nat_get_blkaddr(e); |
286 | ni->version = nat_get_version(e); | 286 | ni->version = nat_get_version(e); |
287 | } | 287 | } |
288 | read_unlock(&nm_i->nat_tree_lock); | 288 | read_unlock(&nm_i->nat_tree_lock); |
289 | if (e) | 289 | if (e) |
290 | return; | 290 | return; |
291 | 291 | ||
292 | /* Check current segment summary */ | 292 | /* Check current segment summary */ |
293 | mutex_lock(&curseg->curseg_mutex); | 293 | mutex_lock(&curseg->curseg_mutex); |
294 | i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0); | 294 | i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0); |
295 | if (i >= 0) { | 295 | if (i >= 0) { |
296 | ne = nat_in_journal(sum, i); | 296 | ne = nat_in_journal(sum, i); |
297 | node_info_from_raw_nat(ni, &ne); | 297 | node_info_from_raw_nat(ni, &ne); |
298 | } | 298 | } |
299 | mutex_unlock(&curseg->curseg_mutex); | 299 | mutex_unlock(&curseg->curseg_mutex); |
300 | if (i >= 0) | 300 | if (i >= 0) |
301 | goto cache; | 301 | goto cache; |
302 | 302 | ||
303 | /* Fill node_info from nat page */ | 303 | /* Fill node_info from nat page */ |
304 | page = get_current_nat_page(sbi, start_nid); | 304 | page = get_current_nat_page(sbi, start_nid); |
305 | nat_blk = (struct f2fs_nat_block *)page_address(page); | 305 | nat_blk = (struct f2fs_nat_block *)page_address(page); |
306 | ne = nat_blk->entries[nid - start_nid]; | 306 | ne = nat_blk->entries[nid - start_nid]; |
307 | node_info_from_raw_nat(ni, &ne); | 307 | node_info_from_raw_nat(ni, &ne); |
308 | f2fs_put_page(page, 1); | 308 | f2fs_put_page(page, 1); |
309 | cache: | 309 | cache: |
310 | /* cache nat entry */ | 310 | /* cache nat entry */ |
311 | cache_nat_entry(NM_I(sbi), nid, &ne); | 311 | cache_nat_entry(NM_I(sbi), nid, &ne); |
312 | } | 312 | } |
313 | 313 | ||
314 | /* | 314 | /* |
315 | * The maximum depth is four. | 315 | * The maximum depth is four. |
316 | * Offset[0] will have raw inode offset. | 316 | * Offset[0] will have raw inode offset. |
317 | */ | 317 | */ |
318 | static int get_node_path(long block, int offset[4], unsigned int noffset[4]) | 318 | static int get_node_path(long block, int offset[4], unsigned int noffset[4]) |
319 | { | 319 | { |
320 | const long direct_index = ADDRS_PER_INODE; | 320 | const long direct_index = ADDRS_PER_INODE; |
321 | const long direct_blks = ADDRS_PER_BLOCK; | 321 | const long direct_blks = ADDRS_PER_BLOCK; |
322 | const long dptrs_per_blk = NIDS_PER_BLOCK; | 322 | const long dptrs_per_blk = NIDS_PER_BLOCK; |
323 | const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; | 323 | const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; |
324 | const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; | 324 | const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; |
325 | int n = 0; | 325 | int n = 0; |
326 | int level = 0; | 326 | int level = 0; |
327 | 327 | ||
328 | noffset[0] = 0; | 328 | noffset[0] = 0; |
329 | 329 | ||
330 | if (block < direct_index) { | 330 | if (block < direct_index) { |
331 | offset[n] = block; | 331 | offset[n] = block; |
332 | goto got; | 332 | goto got; |
333 | } | 333 | } |
334 | block -= direct_index; | 334 | block -= direct_index; |
335 | if (block < direct_blks) { | 335 | if (block < direct_blks) { |
336 | offset[n++] = NODE_DIR1_BLOCK; | 336 | offset[n++] = NODE_DIR1_BLOCK; |
337 | noffset[n] = 1; | 337 | noffset[n] = 1; |
338 | offset[n] = block; | 338 | offset[n] = block; |
339 | level = 1; | 339 | level = 1; |
340 | goto got; | 340 | goto got; |
341 | } | 341 | } |
342 | block -= direct_blks; | 342 | block -= direct_blks; |
343 | if (block < direct_blks) { | 343 | if (block < direct_blks) { |
344 | offset[n++] = NODE_DIR2_BLOCK; | 344 | offset[n++] = NODE_DIR2_BLOCK; |
345 | noffset[n] = 2; | 345 | noffset[n] = 2; |
346 | offset[n] = block; | 346 | offset[n] = block; |
347 | level = 1; | 347 | level = 1; |
348 | goto got; | 348 | goto got; |
349 | } | 349 | } |
350 | block -= direct_blks; | 350 | block -= direct_blks; |
351 | if (block < indirect_blks) { | 351 | if (block < indirect_blks) { |
352 | offset[n++] = NODE_IND1_BLOCK; | 352 | offset[n++] = NODE_IND1_BLOCK; |
353 | noffset[n] = 3; | 353 | noffset[n] = 3; |
354 | offset[n++] = block / direct_blks; | 354 | offset[n++] = block / direct_blks; |
355 | noffset[n] = 4 + offset[n - 1]; | 355 | noffset[n] = 4 + offset[n - 1]; |
356 | offset[n] = block % direct_blks; | 356 | offset[n] = block % direct_blks; |
357 | level = 2; | 357 | level = 2; |
358 | goto got; | 358 | goto got; |
359 | } | 359 | } |
360 | block -= indirect_blks; | 360 | block -= indirect_blks; |
361 | if (block < indirect_blks) { | 361 | if (block < indirect_blks) { |
362 | offset[n++] = NODE_IND2_BLOCK; | 362 | offset[n++] = NODE_IND2_BLOCK; |
363 | noffset[n] = 4 + dptrs_per_blk; | 363 | noffset[n] = 4 + dptrs_per_blk; |
364 | offset[n++] = block / direct_blks; | 364 | offset[n++] = block / direct_blks; |
365 | noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; | 365 | noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; |
366 | offset[n] = block % direct_blks; | 366 | offset[n] = block % direct_blks; |
367 | level = 2; | 367 | level = 2; |
368 | goto got; | 368 | goto got; |
369 | } | 369 | } |
370 | block -= indirect_blks; | 370 | block -= indirect_blks; |
371 | if (block < dindirect_blks) { | 371 | if (block < dindirect_blks) { |
372 | offset[n++] = NODE_DIND_BLOCK; | 372 | offset[n++] = NODE_DIND_BLOCK; |
373 | noffset[n] = 5 + (dptrs_per_blk * 2); | 373 | noffset[n] = 5 + (dptrs_per_blk * 2); |
374 | offset[n++] = block / indirect_blks; | 374 | offset[n++] = block / indirect_blks; |
375 | noffset[n] = 6 + (dptrs_per_blk * 2) + | 375 | noffset[n] = 6 + (dptrs_per_blk * 2) + |
376 | offset[n - 1] * (dptrs_per_blk + 1); | 376 | offset[n - 1] * (dptrs_per_blk + 1); |
377 | offset[n++] = (block / direct_blks) % dptrs_per_blk; | 377 | offset[n++] = (block / direct_blks) % dptrs_per_blk; |
378 | noffset[n] = 7 + (dptrs_per_blk * 2) + | 378 | noffset[n] = 7 + (dptrs_per_blk * 2) + |
379 | offset[n - 2] * (dptrs_per_blk + 1) + | 379 | offset[n - 2] * (dptrs_per_blk + 1) + |
380 | offset[n - 1]; | 380 | offset[n - 1]; |
381 | offset[n] = block % direct_blks; | 381 | offset[n] = block % direct_blks; |
382 | level = 3; | 382 | level = 3; |
383 | goto got; | 383 | goto got; |
384 | } else { | 384 | } else { |
385 | BUG(); | 385 | BUG(); |
386 | } | 386 | } |
387 | got: | 387 | got: |
388 | return level; | 388 | return level; |
389 | } | 389 | } |
390 | 390 | ||
391 | /* | 391 | /* |
392 | * Caller should call f2fs_put_dnode(dn). | 392 | * Caller should call f2fs_put_dnode(dn). |
393 | * Also, it should grab and release a mutex by calling mutex_lock_op() and | 393 | * Also, it should grab and release a mutex by calling mutex_lock_op() and |
394 | * mutex_unlock_op() only if ro is not set RDONLY_NODE. | 394 | * mutex_unlock_op() only if ro is not set RDONLY_NODE. |
395 | * In the case of RDONLY_NODE, we don't need to care about mutex. | 395 | * In the case of RDONLY_NODE, we don't need to care about mutex. |
396 | */ | 396 | */ |
397 | int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) | 397 | int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) |
398 | { | 398 | { |
399 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 399 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
400 | struct page *npage[4]; | 400 | struct page *npage[4]; |
401 | struct page *parent; | 401 | struct page *parent; |
402 | int offset[4]; | 402 | int offset[4]; |
403 | unsigned int noffset[4]; | 403 | unsigned int noffset[4]; |
404 | nid_t nids[4]; | 404 | nid_t nids[4]; |
405 | int level, i; | 405 | int level, i; |
406 | int err = 0; | 406 | int err = 0; |
407 | 407 | ||
408 | level = get_node_path(index, offset, noffset); | 408 | level = get_node_path(index, offset, noffset); |
409 | 409 | ||
410 | nids[0] = dn->inode->i_ino; | 410 | nids[0] = dn->inode->i_ino; |
411 | npage[0] = get_node_page(sbi, nids[0]); | 411 | npage[0] = get_node_page(sbi, nids[0]); |
412 | if (IS_ERR(npage[0])) | 412 | if (IS_ERR(npage[0])) |
413 | return PTR_ERR(npage[0]); | 413 | return PTR_ERR(npage[0]); |
414 | 414 | ||
415 | parent = npage[0]; | 415 | parent = npage[0]; |
416 | if (level != 0) | 416 | if (level != 0) |
417 | nids[1] = get_nid(parent, offset[0], true); | 417 | nids[1] = get_nid(parent, offset[0], true); |
418 | dn->inode_page = npage[0]; | 418 | dn->inode_page = npage[0]; |
419 | dn->inode_page_locked = true; | 419 | dn->inode_page_locked = true; |
420 | 420 | ||
421 | /* get indirect or direct nodes */ | 421 | /* get indirect or direct nodes */ |
422 | for (i = 1; i <= level; i++) { | 422 | for (i = 1; i <= level; i++) { |
423 | bool done = false; | 423 | bool done = false; |
424 | 424 | ||
425 | if (!nids[i] && mode == ALLOC_NODE) { | 425 | if (!nids[i] && mode == ALLOC_NODE) { |
426 | /* alloc new node */ | 426 | /* alloc new node */ |
427 | if (!alloc_nid(sbi, &(nids[i]))) { | 427 | if (!alloc_nid(sbi, &(nids[i]))) { |
428 | err = -ENOSPC; | 428 | err = -ENOSPC; |
429 | goto release_pages; | 429 | goto release_pages; |
430 | } | 430 | } |
431 | 431 | ||
432 | dn->nid = nids[i]; | 432 | dn->nid = nids[i]; |
433 | npage[i] = new_node_page(dn, noffset[i]); | 433 | npage[i] = new_node_page(dn, noffset[i]); |
434 | if (IS_ERR(npage[i])) { | 434 | if (IS_ERR(npage[i])) { |
435 | alloc_nid_failed(sbi, nids[i]); | 435 | alloc_nid_failed(sbi, nids[i]); |
436 | err = PTR_ERR(npage[i]); | 436 | err = PTR_ERR(npage[i]); |
437 | goto release_pages; | 437 | goto release_pages; |
438 | } | 438 | } |
439 | 439 | ||
440 | set_nid(parent, offset[i - 1], nids[i], i == 1); | 440 | set_nid(parent, offset[i - 1], nids[i], i == 1); |
441 | alloc_nid_done(sbi, nids[i]); | 441 | alloc_nid_done(sbi, nids[i]); |
442 | done = true; | 442 | done = true; |
443 | } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { | 443 | } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { |
444 | npage[i] = get_node_page_ra(parent, offset[i - 1]); | 444 | npage[i] = get_node_page_ra(parent, offset[i - 1]); |
445 | if (IS_ERR(npage[i])) { | 445 | if (IS_ERR(npage[i])) { |
446 | err = PTR_ERR(npage[i]); | 446 | err = PTR_ERR(npage[i]); |
447 | goto release_pages; | 447 | goto release_pages; |
448 | } | 448 | } |
449 | done = true; | 449 | done = true; |
450 | } | 450 | } |
451 | if (i == 1) { | 451 | if (i == 1) { |
452 | dn->inode_page_locked = false; | 452 | dn->inode_page_locked = false; |
453 | unlock_page(parent); | 453 | unlock_page(parent); |
454 | } else { | 454 | } else { |
455 | f2fs_put_page(parent, 1); | 455 | f2fs_put_page(parent, 1); |
456 | } | 456 | } |
457 | 457 | ||
458 | if (!done) { | 458 | if (!done) { |
459 | npage[i] = get_node_page(sbi, nids[i]); | 459 | npage[i] = get_node_page(sbi, nids[i]); |
460 | if (IS_ERR(npage[i])) { | 460 | if (IS_ERR(npage[i])) { |
461 | err = PTR_ERR(npage[i]); | 461 | err = PTR_ERR(npage[i]); |
462 | f2fs_put_page(npage[0], 0); | 462 | f2fs_put_page(npage[0], 0); |
463 | goto release_out; | 463 | goto release_out; |
464 | } | 464 | } |
465 | } | 465 | } |
466 | if (i < level) { | 466 | if (i < level) { |
467 | parent = npage[i]; | 467 | parent = npage[i]; |
468 | nids[i + 1] = get_nid(parent, offset[i], false); | 468 | nids[i + 1] = get_nid(parent, offset[i], false); |
469 | } | 469 | } |
470 | } | 470 | } |
471 | dn->nid = nids[level]; | 471 | dn->nid = nids[level]; |
472 | dn->ofs_in_node = offset[level]; | 472 | dn->ofs_in_node = offset[level]; |
473 | dn->node_page = npage[level]; | 473 | dn->node_page = npage[level]; |
474 | dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node); | 474 | dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node); |
475 | return 0; | 475 | return 0; |
476 | 476 | ||
477 | release_pages: | 477 | release_pages: |
478 | f2fs_put_page(parent, 1); | 478 | f2fs_put_page(parent, 1); |
479 | if (i > 1) | 479 | if (i > 1) |
480 | f2fs_put_page(npage[0], 0); | 480 | f2fs_put_page(npage[0], 0); |
481 | release_out: | 481 | release_out: |
482 | dn->inode_page = NULL; | 482 | dn->inode_page = NULL; |
483 | dn->node_page = NULL; | 483 | dn->node_page = NULL; |
484 | return err; | 484 | return err; |
485 | } | 485 | } |
486 | 486 | ||
487 | static void truncate_node(struct dnode_of_data *dn) | 487 | static void truncate_node(struct dnode_of_data *dn) |
488 | { | 488 | { |
489 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 489 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
490 | struct node_info ni; | 490 | struct node_info ni; |
491 | 491 | ||
492 | get_node_info(sbi, dn->nid, &ni); | 492 | get_node_info(sbi, dn->nid, &ni); |
493 | if (dn->inode->i_blocks == 0) { | 493 | if (dn->inode->i_blocks == 0) { |
494 | BUG_ON(ni.blk_addr != NULL_ADDR); | 494 | BUG_ON(ni.blk_addr != NULL_ADDR); |
495 | goto invalidate; | 495 | goto invalidate; |
496 | } | 496 | } |
497 | BUG_ON(ni.blk_addr == NULL_ADDR); | 497 | BUG_ON(ni.blk_addr == NULL_ADDR); |
498 | 498 | ||
499 | /* Deallocate node address */ | 499 | /* Deallocate node address */ |
500 | invalidate_blocks(sbi, ni.blk_addr); | 500 | invalidate_blocks(sbi, ni.blk_addr); |
501 | dec_valid_node_count(sbi, dn->inode, 1); | 501 | dec_valid_node_count(sbi, dn->inode, 1); |
502 | set_node_addr(sbi, &ni, NULL_ADDR); | 502 | set_node_addr(sbi, &ni, NULL_ADDR); |
503 | 503 | ||
504 | if (dn->nid == dn->inode->i_ino) { | 504 | if (dn->nid == dn->inode->i_ino) { |
505 | remove_orphan_inode(sbi, dn->nid); | 505 | remove_orphan_inode(sbi, dn->nid); |
506 | dec_valid_inode_count(sbi); | 506 | dec_valid_inode_count(sbi); |
507 | } else { | 507 | } else { |
508 | sync_inode_page(dn); | 508 | sync_inode_page(dn); |
509 | } | 509 | } |
510 | invalidate: | 510 | invalidate: |
511 | clear_node_page_dirty(dn->node_page); | 511 | clear_node_page_dirty(dn->node_page); |
512 | F2FS_SET_SB_DIRT(sbi); | 512 | F2FS_SET_SB_DIRT(sbi); |
513 | 513 | ||
514 | f2fs_put_page(dn->node_page, 1); | 514 | f2fs_put_page(dn->node_page, 1); |
515 | dn->node_page = NULL; | 515 | dn->node_page = NULL; |
516 | trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); | 516 | trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); |
517 | } | 517 | } |
518 | 518 | ||
519 | static int truncate_dnode(struct dnode_of_data *dn) | 519 | static int truncate_dnode(struct dnode_of_data *dn) |
520 | { | 520 | { |
521 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 521 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
522 | struct page *page; | 522 | struct page *page; |
523 | 523 | ||
524 | if (dn->nid == 0) | 524 | if (dn->nid == 0) |
525 | return 1; | 525 | return 1; |
526 | 526 | ||
527 | /* get direct node */ | 527 | /* get direct node */ |
528 | page = get_node_page(sbi, dn->nid); | 528 | page = get_node_page(sbi, dn->nid); |
529 | if (IS_ERR(page) && PTR_ERR(page) == -ENOENT) | 529 | if (IS_ERR(page) && PTR_ERR(page) == -ENOENT) |
530 | return 1; | 530 | return 1; |
531 | else if (IS_ERR(page)) | 531 | else if (IS_ERR(page)) |
532 | return PTR_ERR(page); | 532 | return PTR_ERR(page); |
533 | 533 | ||
534 | /* Make dnode_of_data for parameter */ | 534 | /* Make dnode_of_data for parameter */ |
535 | dn->node_page = page; | 535 | dn->node_page = page; |
536 | dn->ofs_in_node = 0; | 536 | dn->ofs_in_node = 0; |
537 | truncate_data_blocks(dn); | 537 | truncate_data_blocks(dn); |
538 | truncate_node(dn); | 538 | truncate_node(dn); |
539 | return 1; | 539 | return 1; |
540 | } | 540 | } |
541 | 541 | ||
542 | static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, | 542 | static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, |
543 | int ofs, int depth) | 543 | int ofs, int depth) |
544 | { | 544 | { |
545 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 545 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
546 | struct dnode_of_data rdn = *dn; | 546 | struct dnode_of_data rdn = *dn; |
547 | struct page *page; | 547 | struct page *page; |
548 | struct f2fs_node *rn; | 548 | struct f2fs_node *rn; |
549 | nid_t child_nid; | 549 | nid_t child_nid; |
550 | unsigned int child_nofs; | 550 | unsigned int child_nofs; |
551 | int freed = 0; | 551 | int freed = 0; |
552 | int i, ret; | 552 | int i, ret; |
553 | 553 | ||
554 | if (dn->nid == 0) | 554 | if (dn->nid == 0) |
555 | return NIDS_PER_BLOCK + 1; | 555 | return NIDS_PER_BLOCK + 1; |
556 | 556 | ||
557 | trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); | 557 | trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); |
558 | 558 | ||
559 | page = get_node_page(sbi, dn->nid); | 559 | page = get_node_page(sbi, dn->nid); |
560 | if (IS_ERR(page)) { | 560 | if (IS_ERR(page)) { |
561 | trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); | 561 | trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); |
562 | return PTR_ERR(page); | 562 | return PTR_ERR(page); |
563 | } | 563 | } |
564 | 564 | ||
565 | rn = (struct f2fs_node *)page_address(page); | 565 | rn = (struct f2fs_node *)page_address(page); |
566 | if (depth < 3) { | 566 | if (depth < 3) { |
567 | for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { | 567 | for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { |
568 | child_nid = le32_to_cpu(rn->in.nid[i]); | 568 | child_nid = le32_to_cpu(rn->in.nid[i]); |
569 | if (child_nid == 0) | 569 | if (child_nid == 0) |
570 | continue; | 570 | continue; |
571 | rdn.nid = child_nid; | 571 | rdn.nid = child_nid; |
572 | ret = truncate_dnode(&rdn); | 572 | ret = truncate_dnode(&rdn); |
573 | if (ret < 0) | 573 | if (ret < 0) |
574 | goto out_err; | 574 | goto out_err; |
575 | set_nid(page, i, 0, false); | 575 | set_nid(page, i, 0, false); |
576 | } | 576 | } |
577 | } else { | 577 | } else { |
578 | child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; | 578 | child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; |
579 | for (i = ofs; i < NIDS_PER_BLOCK; i++) { | 579 | for (i = ofs; i < NIDS_PER_BLOCK; i++) { |
580 | child_nid = le32_to_cpu(rn->in.nid[i]); | 580 | child_nid = le32_to_cpu(rn->in.nid[i]); |
581 | if (child_nid == 0) { | 581 | if (child_nid == 0) { |
582 | child_nofs += NIDS_PER_BLOCK + 1; | 582 | child_nofs += NIDS_PER_BLOCK + 1; |
583 | continue; | 583 | continue; |
584 | } | 584 | } |
585 | rdn.nid = child_nid; | 585 | rdn.nid = child_nid; |
586 | ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); | 586 | ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); |
587 | if (ret == (NIDS_PER_BLOCK + 1)) { | 587 | if (ret == (NIDS_PER_BLOCK + 1)) { |
588 | set_nid(page, i, 0, false); | 588 | set_nid(page, i, 0, false); |
589 | child_nofs += ret; | 589 | child_nofs += ret; |
590 | } else if (ret < 0 && ret != -ENOENT) { | 590 | } else if (ret < 0 && ret != -ENOENT) { |
591 | goto out_err; | 591 | goto out_err; |
592 | } | 592 | } |
593 | } | 593 | } |
594 | freed = child_nofs; | 594 | freed = child_nofs; |
595 | } | 595 | } |
596 | 596 | ||
597 | if (!ofs) { | 597 | if (!ofs) { |
598 | /* remove current indirect node */ | 598 | /* remove current indirect node */ |
599 | dn->node_page = page; | 599 | dn->node_page = page; |
600 | truncate_node(dn); | 600 | truncate_node(dn); |
601 | freed++; | 601 | freed++; |
602 | } else { | 602 | } else { |
603 | f2fs_put_page(page, 1); | 603 | f2fs_put_page(page, 1); |
604 | } | 604 | } |
605 | trace_f2fs_truncate_nodes_exit(dn->inode, freed); | 605 | trace_f2fs_truncate_nodes_exit(dn->inode, freed); |
606 | return freed; | 606 | return freed; |
607 | 607 | ||
608 | out_err: | 608 | out_err: |
609 | f2fs_put_page(page, 1); | 609 | f2fs_put_page(page, 1); |
610 | trace_f2fs_truncate_nodes_exit(dn->inode, ret); | 610 | trace_f2fs_truncate_nodes_exit(dn->inode, ret); |
611 | return ret; | 611 | return ret; |
612 | } | 612 | } |
613 | 613 | ||
614 | static int truncate_partial_nodes(struct dnode_of_data *dn, | 614 | static int truncate_partial_nodes(struct dnode_of_data *dn, |
615 | struct f2fs_inode *ri, int *offset, int depth) | 615 | struct f2fs_inode *ri, int *offset, int depth) |
616 | { | 616 | { |
617 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 617 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
618 | struct page *pages[2]; | 618 | struct page *pages[2]; |
619 | nid_t nid[3]; | 619 | nid_t nid[3]; |
620 | nid_t child_nid; | 620 | nid_t child_nid; |
621 | int err = 0; | 621 | int err = 0; |
622 | int i; | 622 | int i; |
623 | int idx = depth - 2; | 623 | int idx = depth - 2; |
624 | 624 | ||
625 | nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); | 625 | nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); |
626 | if (!nid[0]) | 626 | if (!nid[0]) |
627 | return 0; | 627 | return 0; |
628 | 628 | ||
629 | /* get indirect nodes in the path */ | 629 | /* get indirect nodes in the path */ |
630 | for (i = 0; i < depth - 1; i++) { | 630 | for (i = 0; i < depth - 1; i++) { |
631 | /* refernece count'll be increased */ | 631 | /* refernece count'll be increased */ |
632 | pages[i] = get_node_page(sbi, nid[i]); | 632 | pages[i] = get_node_page(sbi, nid[i]); |
633 | if (IS_ERR(pages[i])) { | 633 | if (IS_ERR(pages[i])) { |
634 | depth = i + 1; | 634 | depth = i + 1; |
635 | err = PTR_ERR(pages[i]); | 635 | err = PTR_ERR(pages[i]); |
636 | goto fail; | 636 | goto fail; |
637 | } | 637 | } |
638 | nid[i + 1] = get_nid(pages[i], offset[i + 1], false); | 638 | nid[i + 1] = get_nid(pages[i], offset[i + 1], false); |
639 | } | 639 | } |
640 | 640 | ||
641 | /* free direct nodes linked to a partial indirect node */ | 641 | /* free direct nodes linked to a partial indirect node */ |
642 | for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) { | 642 | for (i = offset[depth - 1]; i < NIDS_PER_BLOCK; i++) { |
643 | child_nid = get_nid(pages[idx], i, false); | 643 | child_nid = get_nid(pages[idx], i, false); |
644 | if (!child_nid) | 644 | if (!child_nid) |
645 | continue; | 645 | continue; |
646 | dn->nid = child_nid; | 646 | dn->nid = child_nid; |
647 | err = truncate_dnode(dn); | 647 | err = truncate_dnode(dn); |
648 | if (err < 0) | 648 | if (err < 0) |
649 | goto fail; | 649 | goto fail; |
650 | set_nid(pages[idx], i, 0, false); | 650 | set_nid(pages[idx], i, 0, false); |
651 | } | 651 | } |
652 | 652 | ||
653 | if (offset[depth - 1] == 0) { | 653 | if (offset[depth - 1] == 0) { |
654 | dn->node_page = pages[idx]; | 654 | dn->node_page = pages[idx]; |
655 | dn->nid = nid[idx]; | 655 | dn->nid = nid[idx]; |
656 | truncate_node(dn); | 656 | truncate_node(dn); |
657 | } else { | 657 | } else { |
658 | f2fs_put_page(pages[idx], 1); | 658 | f2fs_put_page(pages[idx], 1); |
659 | } | 659 | } |
660 | offset[idx]++; | 660 | offset[idx]++; |
661 | offset[depth - 1] = 0; | 661 | offset[depth - 1] = 0; |
662 | fail: | 662 | fail: |
663 | for (i = depth - 3; i >= 0; i--) | 663 | for (i = depth - 3; i >= 0; i--) |
664 | f2fs_put_page(pages[i], 1); | 664 | f2fs_put_page(pages[i], 1); |
665 | 665 | ||
666 | trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); | 666 | trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); |
667 | 667 | ||
668 | return err; | 668 | return err; |
669 | } | 669 | } |
670 | 670 | ||
671 | /* | 671 | /* |
672 | * All the block addresses of data and nodes should be nullified. | 672 | * All the block addresses of data and nodes should be nullified. |
673 | */ | 673 | */ |
674 | int truncate_inode_blocks(struct inode *inode, pgoff_t from) | 674 | int truncate_inode_blocks(struct inode *inode, pgoff_t from) |
675 | { | 675 | { |
676 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 676 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
677 | struct address_space *node_mapping = sbi->node_inode->i_mapping; | 677 | struct address_space *node_mapping = sbi->node_inode->i_mapping; |
678 | int err = 0, cont = 1; | 678 | int err = 0, cont = 1; |
679 | int level, offset[4], noffset[4]; | 679 | int level, offset[4], noffset[4]; |
680 | unsigned int nofs = 0; | 680 | unsigned int nofs = 0; |
681 | struct f2fs_node *rn; | 681 | struct f2fs_node *rn; |
682 | struct dnode_of_data dn; | 682 | struct dnode_of_data dn; |
683 | struct page *page; | 683 | struct page *page; |
684 | 684 | ||
685 | trace_f2fs_truncate_inode_blocks_enter(inode, from); | 685 | trace_f2fs_truncate_inode_blocks_enter(inode, from); |
686 | 686 | ||
687 | level = get_node_path(from, offset, noffset); | 687 | level = get_node_path(from, offset, noffset); |
688 | restart: | 688 | restart: |
689 | page = get_node_page(sbi, inode->i_ino); | 689 | page = get_node_page(sbi, inode->i_ino); |
690 | if (IS_ERR(page)) { | 690 | if (IS_ERR(page)) { |
691 | trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); | 691 | trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); |
692 | return PTR_ERR(page); | 692 | return PTR_ERR(page); |
693 | } | 693 | } |
694 | 694 | ||
695 | set_new_dnode(&dn, inode, page, NULL, 0); | 695 | set_new_dnode(&dn, inode, page, NULL, 0); |
696 | unlock_page(page); | 696 | unlock_page(page); |
697 | 697 | ||
698 | rn = page_address(page); | 698 | rn = page_address(page); |
699 | switch (level) { | 699 | switch (level) { |
700 | case 0: | 700 | case 0: |
701 | case 1: | 701 | case 1: |
702 | nofs = noffset[1]; | 702 | nofs = noffset[1]; |
703 | break; | 703 | break; |
704 | case 2: | 704 | case 2: |
705 | nofs = noffset[1]; | 705 | nofs = noffset[1]; |
706 | if (!offset[level - 1]) | 706 | if (!offset[level - 1]) |
707 | goto skip_partial; | 707 | goto skip_partial; |
708 | err = truncate_partial_nodes(&dn, &rn->i, offset, level); | 708 | err = truncate_partial_nodes(&dn, &rn->i, offset, level); |
709 | if (err < 0 && err != -ENOENT) | 709 | if (err < 0 && err != -ENOENT) |
710 | goto fail; | 710 | goto fail; |
711 | nofs += 1 + NIDS_PER_BLOCK; | 711 | nofs += 1 + NIDS_PER_BLOCK; |
712 | break; | 712 | break; |
713 | case 3: | 713 | case 3: |
714 | nofs = 5 + 2 * NIDS_PER_BLOCK; | 714 | nofs = 5 + 2 * NIDS_PER_BLOCK; |
715 | if (!offset[level - 1]) | 715 | if (!offset[level - 1]) |
716 | goto skip_partial; | 716 | goto skip_partial; |
717 | err = truncate_partial_nodes(&dn, &rn->i, offset, level); | 717 | err = truncate_partial_nodes(&dn, &rn->i, offset, level); |
718 | if (err < 0 && err != -ENOENT) | 718 | if (err < 0 && err != -ENOENT) |
719 | goto fail; | 719 | goto fail; |
720 | break; | 720 | break; |
721 | default: | 721 | default: |
722 | BUG(); | 722 | BUG(); |
723 | } | 723 | } |
724 | 724 | ||
725 | skip_partial: | 725 | skip_partial: |
726 | while (cont) { | 726 | while (cont) { |
727 | dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]); | 727 | dn.nid = le32_to_cpu(rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]); |
728 | switch (offset[0]) { | 728 | switch (offset[0]) { |
729 | case NODE_DIR1_BLOCK: | 729 | case NODE_DIR1_BLOCK: |
730 | case NODE_DIR2_BLOCK: | 730 | case NODE_DIR2_BLOCK: |
731 | err = truncate_dnode(&dn); | 731 | err = truncate_dnode(&dn); |
732 | break; | 732 | break; |
733 | 733 | ||
734 | case NODE_IND1_BLOCK: | 734 | case NODE_IND1_BLOCK: |
735 | case NODE_IND2_BLOCK: | 735 | case NODE_IND2_BLOCK: |
736 | err = truncate_nodes(&dn, nofs, offset[1], 2); | 736 | err = truncate_nodes(&dn, nofs, offset[1], 2); |
737 | break; | 737 | break; |
738 | 738 | ||
739 | case NODE_DIND_BLOCK: | 739 | case NODE_DIND_BLOCK: |
740 | err = truncate_nodes(&dn, nofs, offset[1], 3); | 740 | err = truncate_nodes(&dn, nofs, offset[1], 3); |
741 | cont = 0; | 741 | cont = 0; |
742 | break; | 742 | break; |
743 | 743 | ||
744 | default: | 744 | default: |
745 | BUG(); | 745 | BUG(); |
746 | } | 746 | } |
747 | if (err < 0 && err != -ENOENT) | 747 | if (err < 0 && err != -ENOENT) |
748 | goto fail; | 748 | goto fail; |
749 | if (offset[1] == 0 && | 749 | if (offset[1] == 0 && |
750 | rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) { | 750 | rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK]) { |
751 | lock_page(page); | 751 | lock_page(page); |
752 | if (page->mapping != node_mapping) { | 752 | if (page->mapping != node_mapping) { |
753 | f2fs_put_page(page, 1); | 753 | f2fs_put_page(page, 1); |
754 | goto restart; | 754 | goto restart; |
755 | } | 755 | } |
756 | wait_on_page_writeback(page); | 756 | wait_on_page_writeback(page); |
757 | rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; | 757 | rn->i.i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; |
758 | set_page_dirty(page); | 758 | set_page_dirty(page); |
759 | unlock_page(page); | 759 | unlock_page(page); |
760 | } | 760 | } |
761 | offset[1] = 0; | 761 | offset[1] = 0; |
762 | offset[0]++; | 762 | offset[0]++; |
763 | nofs += err; | 763 | nofs += err; |
764 | } | 764 | } |
765 | fail: | 765 | fail: |
766 | f2fs_put_page(page, 0); | 766 | f2fs_put_page(page, 0); |
767 | trace_f2fs_truncate_inode_blocks_exit(inode, err); | 767 | trace_f2fs_truncate_inode_blocks_exit(inode, err); |
768 | return err > 0 ? 0 : err; | 768 | return err > 0 ? 0 : err; |
769 | } | 769 | } |
770 | 770 | ||
771 | /* | 771 | /* |
772 | * Caller should grab and release a mutex by calling mutex_lock_op() and | 772 | * Caller should grab and release a mutex by calling mutex_lock_op() and |
773 | * mutex_unlock_op(). | 773 | * mutex_unlock_op(). |
774 | */ | 774 | */ |
775 | int remove_inode_page(struct inode *inode) | 775 | int remove_inode_page(struct inode *inode) |
776 | { | 776 | { |
777 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 777 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
778 | struct page *page; | 778 | struct page *page; |
779 | nid_t ino = inode->i_ino; | 779 | nid_t ino = inode->i_ino; |
780 | struct dnode_of_data dn; | 780 | struct dnode_of_data dn; |
781 | 781 | ||
782 | page = get_node_page(sbi, ino); | 782 | page = get_node_page(sbi, ino); |
783 | if (IS_ERR(page)) | 783 | if (IS_ERR(page)) |
784 | return PTR_ERR(page); | 784 | return PTR_ERR(page); |
785 | 785 | ||
786 | if (F2FS_I(inode)->i_xattr_nid) { | 786 | if (F2FS_I(inode)->i_xattr_nid) { |
787 | nid_t nid = F2FS_I(inode)->i_xattr_nid; | 787 | nid_t nid = F2FS_I(inode)->i_xattr_nid; |
788 | struct page *npage = get_node_page(sbi, nid); | 788 | struct page *npage = get_node_page(sbi, nid); |
789 | 789 | ||
790 | if (IS_ERR(npage)) | 790 | if (IS_ERR(npage)) |
791 | return PTR_ERR(npage); | 791 | return PTR_ERR(npage); |
792 | 792 | ||
793 | F2FS_I(inode)->i_xattr_nid = 0; | 793 | F2FS_I(inode)->i_xattr_nid = 0; |
794 | set_new_dnode(&dn, inode, page, npage, nid); | 794 | set_new_dnode(&dn, inode, page, npage, nid); |
795 | dn.inode_page_locked = 1; | 795 | dn.inode_page_locked = 1; |
796 | truncate_node(&dn); | 796 | truncate_node(&dn); |
797 | } | 797 | } |
798 | 798 | ||
799 | /* 0 is possible, after f2fs_new_inode() is failed */ | 799 | /* 0 is possible, after f2fs_new_inode() is failed */ |
800 | BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1); | 800 | BUG_ON(inode->i_blocks != 0 && inode->i_blocks != 1); |
801 | set_new_dnode(&dn, inode, page, page, ino); | 801 | set_new_dnode(&dn, inode, page, page, ino); |
802 | truncate_node(&dn); | 802 | truncate_node(&dn); |
803 | return 0; | 803 | return 0; |
804 | } | 804 | } |
805 | 805 | ||
806 | int new_inode_page(struct inode *inode, const struct qstr *name) | 806 | int new_inode_page(struct inode *inode, const struct qstr *name) |
807 | { | 807 | { |
808 | struct page *page; | 808 | struct page *page; |
809 | struct dnode_of_data dn; | 809 | struct dnode_of_data dn; |
810 | 810 | ||
811 | /* allocate inode page for new inode */ | 811 | /* allocate inode page for new inode */ |
812 | set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); | 812 | set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); |
813 | page = new_node_page(&dn, 0); | 813 | page = new_node_page(&dn, 0); |
814 | init_dent_inode(name, page); | 814 | init_dent_inode(name, page); |
815 | if (IS_ERR(page)) | 815 | if (IS_ERR(page)) |
816 | return PTR_ERR(page); | 816 | return PTR_ERR(page); |
817 | f2fs_put_page(page, 1); | 817 | f2fs_put_page(page, 1); |
818 | return 0; | 818 | return 0; |
819 | } | 819 | } |
820 | 820 | ||
821 | struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) | 821 | struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) |
822 | { | 822 | { |
823 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); | 823 | struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); |
824 | struct address_space *mapping = sbi->node_inode->i_mapping; | 824 | struct address_space *mapping = sbi->node_inode->i_mapping; |
825 | struct node_info old_ni, new_ni; | 825 | struct node_info old_ni, new_ni; |
826 | struct page *page; | 826 | struct page *page; |
827 | int err; | 827 | int err; |
828 | 828 | ||
829 | if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)) | 829 | if (is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC)) |
830 | return ERR_PTR(-EPERM); | 830 | return ERR_PTR(-EPERM); |
831 | 831 | ||
832 | page = grab_cache_page(mapping, dn->nid); | 832 | page = grab_cache_page(mapping, dn->nid); |
833 | if (!page) | 833 | if (!page) |
834 | return ERR_PTR(-ENOMEM); | 834 | return ERR_PTR(-ENOMEM); |
835 | 835 | ||
836 | get_node_info(sbi, dn->nid, &old_ni); | 836 | get_node_info(sbi, dn->nid, &old_ni); |
837 | 837 | ||
838 | SetPageUptodate(page); | 838 | SetPageUptodate(page); |
839 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); | 839 | fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); |
840 | 840 | ||
841 | /* Reinitialize old_ni with new node page */ | 841 | /* Reinitialize old_ni with new node page */ |
842 | BUG_ON(old_ni.blk_addr != NULL_ADDR); | 842 | BUG_ON(old_ni.blk_addr != NULL_ADDR); |
843 | new_ni = old_ni; | 843 | new_ni = old_ni; |
844 | new_ni.ino = dn->inode->i_ino; | 844 | new_ni.ino = dn->inode->i_ino; |
845 | 845 | ||
846 | if (!inc_valid_node_count(sbi, dn->inode, 1)) { | 846 | if (!inc_valid_node_count(sbi, dn->inode, 1)) { |
847 | err = -ENOSPC; | 847 | err = -ENOSPC; |
848 | goto fail; | 848 | goto fail; |
849 | } | 849 | } |
850 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 850 | set_node_addr(sbi, &new_ni, NEW_ADDR); |
851 | set_cold_node(dn->inode, page); | 851 | set_cold_node(dn->inode, page); |
852 | 852 | ||
853 | dn->node_page = page; | 853 | dn->node_page = page; |
854 | sync_inode_page(dn); | 854 | sync_inode_page(dn); |
855 | set_page_dirty(page); | 855 | set_page_dirty(page); |
856 | if (ofs == 0) | 856 | if (ofs == 0) |
857 | inc_valid_inode_count(sbi); | 857 | inc_valid_inode_count(sbi); |
858 | 858 | ||
859 | return page; | 859 | return page; |
860 | 860 | ||
861 | fail: | 861 | fail: |
862 | clear_node_page_dirty(page); | 862 | clear_node_page_dirty(page); |
863 | f2fs_put_page(page, 1); | 863 | f2fs_put_page(page, 1); |
864 | return ERR_PTR(err); | 864 | return ERR_PTR(err); |
865 | } | 865 | } |
866 | 866 | ||
867 | /* | 867 | /* |
868 | * Caller should do after getting the following values. | 868 | * Caller should do after getting the following values. |
869 | * 0: f2fs_put_page(page, 0) | 869 | * 0: f2fs_put_page(page, 0) |
870 | * LOCKED_PAGE: f2fs_put_page(page, 1) | 870 | * LOCKED_PAGE: f2fs_put_page(page, 1) |
871 | * error: nothing | 871 | * error: nothing |
872 | */ | 872 | */ |
873 | static int read_node_page(struct page *page, int type) | 873 | static int read_node_page(struct page *page, int type) |
874 | { | 874 | { |
875 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | 875 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); |
876 | struct node_info ni; | 876 | struct node_info ni; |
877 | 877 | ||
878 | get_node_info(sbi, page->index, &ni); | 878 | get_node_info(sbi, page->index, &ni); |
879 | 879 | ||
880 | if (ni.blk_addr == NULL_ADDR) { | 880 | if (ni.blk_addr == NULL_ADDR) { |
881 | f2fs_put_page(page, 1); | 881 | f2fs_put_page(page, 1); |
882 | return -ENOENT; | 882 | return -ENOENT; |
883 | } | 883 | } |
884 | 884 | ||
885 | if (PageUptodate(page)) | 885 | if (PageUptodate(page)) |
886 | return LOCKED_PAGE; | 886 | return LOCKED_PAGE; |
887 | 887 | ||
888 | return f2fs_readpage(sbi, page, ni.blk_addr, type); | 888 | return f2fs_readpage(sbi, page, ni.blk_addr, type); |
889 | } | 889 | } |
890 | 890 | ||
891 | /* | 891 | /* |
892 | * Readahead a node page | 892 | * Readahead a node page |
893 | */ | 893 | */ |
894 | void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) | 894 | void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) |
895 | { | 895 | { |
896 | struct address_space *mapping = sbi->node_inode->i_mapping; | 896 | struct address_space *mapping = sbi->node_inode->i_mapping; |
897 | struct page *apage; | 897 | struct page *apage; |
898 | int err; | 898 | int err; |
899 | 899 | ||
900 | apage = find_get_page(mapping, nid); | 900 | apage = find_get_page(mapping, nid); |
901 | if (apage && PageUptodate(apage)) { | 901 | if (apage && PageUptodate(apage)) { |
902 | f2fs_put_page(apage, 0); | 902 | f2fs_put_page(apage, 0); |
903 | return; | 903 | return; |
904 | } | 904 | } |
905 | f2fs_put_page(apage, 0); | 905 | f2fs_put_page(apage, 0); |
906 | 906 | ||
907 | apage = grab_cache_page(mapping, nid); | 907 | apage = grab_cache_page(mapping, nid); |
908 | if (!apage) | 908 | if (!apage) |
909 | return; | 909 | return; |
910 | 910 | ||
911 | err = read_node_page(apage, READA); | 911 | err = read_node_page(apage, READA); |
912 | if (err == 0) | 912 | if (err == 0) |
913 | f2fs_put_page(apage, 0); | 913 | f2fs_put_page(apage, 0); |
914 | else if (err == LOCKED_PAGE) | 914 | else if (err == LOCKED_PAGE) |
915 | f2fs_put_page(apage, 1); | 915 | f2fs_put_page(apage, 1); |
916 | return; | 916 | return; |
917 | } | 917 | } |
918 | 918 | ||
919 | struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) | 919 | struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) |
920 | { | 920 | { |
921 | struct address_space *mapping = sbi->node_inode->i_mapping; | 921 | struct address_space *mapping = sbi->node_inode->i_mapping; |
922 | struct page *page; | 922 | struct page *page; |
923 | int err; | 923 | int err; |
924 | repeat: | 924 | repeat: |
925 | page = grab_cache_page(mapping, nid); | 925 | page = grab_cache_page(mapping, nid); |
926 | if (!page) | 926 | if (!page) |
927 | return ERR_PTR(-ENOMEM); | 927 | return ERR_PTR(-ENOMEM); |
928 | 928 | ||
929 | err = read_node_page(page, READ_SYNC); | 929 | err = read_node_page(page, READ_SYNC); |
930 | if (err < 0) | 930 | if (err < 0) |
931 | return ERR_PTR(err); | 931 | return ERR_PTR(err); |
932 | else if (err == LOCKED_PAGE) | 932 | else if (err == LOCKED_PAGE) |
933 | goto got_it; | 933 | goto got_it; |
934 | 934 | ||
935 | lock_page(page); | 935 | lock_page(page); |
936 | if (!PageUptodate(page)) { | 936 | if (!PageUptodate(page)) { |
937 | f2fs_put_page(page, 1); | 937 | f2fs_put_page(page, 1); |
938 | return ERR_PTR(-EIO); | 938 | return ERR_PTR(-EIO); |
939 | } | 939 | } |
940 | if (page->mapping != mapping) { | 940 | if (page->mapping != mapping) { |
941 | f2fs_put_page(page, 1); | 941 | f2fs_put_page(page, 1); |
942 | goto repeat; | 942 | goto repeat; |
943 | } | 943 | } |
944 | got_it: | 944 | got_it: |
945 | BUG_ON(nid != nid_of_node(page)); | 945 | BUG_ON(nid != nid_of_node(page)); |
946 | mark_page_accessed(page); | 946 | mark_page_accessed(page); |
947 | return page; | 947 | return page; |
948 | } | 948 | } |
949 | 949 | ||
950 | /* | 950 | /* |
951 | * Return a locked page for the desired node page. | 951 | * Return a locked page for the desired node page. |
952 | * And, readahead MAX_RA_NODE number of node pages. | 952 | * And, readahead MAX_RA_NODE number of node pages. |
953 | */ | 953 | */ |
954 | struct page *get_node_page_ra(struct page *parent, int start) | 954 | struct page *get_node_page_ra(struct page *parent, int start) |
955 | { | 955 | { |
956 | struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb); | 956 | struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb); |
957 | struct address_space *mapping = sbi->node_inode->i_mapping; | 957 | struct address_space *mapping = sbi->node_inode->i_mapping; |
958 | struct blk_plug plug; | 958 | struct blk_plug plug; |
959 | struct page *page; | 959 | struct page *page; |
960 | int err, i, end; | 960 | int err, i, end; |
961 | nid_t nid; | 961 | nid_t nid; |
962 | 962 | ||
963 | /* First, try getting the desired direct node. */ | 963 | /* First, try getting the desired direct node. */ |
964 | nid = get_nid(parent, start, false); | 964 | nid = get_nid(parent, start, false); |
965 | if (!nid) | 965 | if (!nid) |
966 | return ERR_PTR(-ENOENT); | 966 | return ERR_PTR(-ENOENT); |
967 | repeat: | 967 | repeat: |
968 | page = grab_cache_page(mapping, nid); | 968 | page = grab_cache_page(mapping, nid); |
969 | if (!page) | 969 | if (!page) |
970 | return ERR_PTR(-ENOMEM); | 970 | return ERR_PTR(-ENOMEM); |
971 | 971 | ||
972 | err = read_node_page(page, READ_SYNC); | 972 | err = read_node_page(page, READ_SYNC); |
973 | if (err < 0) | 973 | if (err < 0) |
974 | return ERR_PTR(err); | 974 | return ERR_PTR(err); |
975 | else if (err == LOCKED_PAGE) | 975 | else if (err == LOCKED_PAGE) |
976 | goto page_hit; | 976 | goto page_hit; |
977 | 977 | ||
978 | blk_start_plug(&plug); | 978 | blk_start_plug(&plug); |
979 | 979 | ||
980 | /* Then, try readahead for siblings of the desired node */ | 980 | /* Then, try readahead for siblings of the desired node */ |
981 | end = start + MAX_RA_NODE; | 981 | end = start + MAX_RA_NODE; |
982 | end = min(end, NIDS_PER_BLOCK); | 982 | end = min(end, NIDS_PER_BLOCK); |
983 | for (i = start + 1; i < end; i++) { | 983 | for (i = start + 1; i < end; i++) { |
984 | nid = get_nid(parent, i, false); | 984 | nid = get_nid(parent, i, false); |
985 | if (!nid) | 985 | if (!nid) |
986 | continue; | 986 | continue; |
987 | ra_node_page(sbi, nid); | 987 | ra_node_page(sbi, nid); |
988 | } | 988 | } |
989 | 989 | ||
990 | blk_finish_plug(&plug); | 990 | blk_finish_plug(&plug); |
991 | 991 | ||
992 | lock_page(page); | 992 | lock_page(page); |
993 | if (page->mapping != mapping) { | 993 | if (page->mapping != mapping) { |
994 | f2fs_put_page(page, 1); | 994 | f2fs_put_page(page, 1); |
995 | goto repeat; | 995 | goto repeat; |
996 | } | 996 | } |
997 | page_hit: | 997 | page_hit: |
998 | if (!PageUptodate(page)) { | 998 | if (!PageUptodate(page)) { |
999 | f2fs_put_page(page, 1); | 999 | f2fs_put_page(page, 1); |
1000 | return ERR_PTR(-EIO); | 1000 | return ERR_PTR(-EIO); |
1001 | } | 1001 | } |
1002 | mark_page_accessed(page); | 1002 | mark_page_accessed(page); |
1003 | return page; | 1003 | return page; |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | void sync_inode_page(struct dnode_of_data *dn) | 1006 | void sync_inode_page(struct dnode_of_data *dn) |
1007 | { | 1007 | { |
1008 | if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) { | 1008 | if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) { |
1009 | update_inode(dn->inode, dn->node_page); | 1009 | update_inode(dn->inode, dn->node_page); |
1010 | } else if (dn->inode_page) { | 1010 | } else if (dn->inode_page) { |
1011 | if (!dn->inode_page_locked) | 1011 | if (!dn->inode_page_locked) |
1012 | lock_page(dn->inode_page); | 1012 | lock_page(dn->inode_page); |
1013 | update_inode(dn->inode, dn->inode_page); | 1013 | update_inode(dn->inode, dn->inode_page); |
1014 | if (!dn->inode_page_locked) | 1014 | if (!dn->inode_page_locked) |
1015 | unlock_page(dn->inode_page); | 1015 | unlock_page(dn->inode_page); |
1016 | } else { | 1016 | } else { |
1017 | update_inode_page(dn->inode); | 1017 | update_inode_page(dn->inode); |
1018 | } | 1018 | } |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, | 1021 | int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, |
1022 | struct writeback_control *wbc) | 1022 | struct writeback_control *wbc) |
1023 | { | 1023 | { |
1024 | struct address_space *mapping = sbi->node_inode->i_mapping; | 1024 | struct address_space *mapping = sbi->node_inode->i_mapping; |
1025 | pgoff_t index, end; | 1025 | pgoff_t index, end; |
1026 | struct pagevec pvec; | 1026 | struct pagevec pvec; |
1027 | int step = ino ? 2 : 0; | 1027 | int step = ino ? 2 : 0; |
1028 | int nwritten = 0, wrote = 0; | 1028 | int nwritten = 0, wrote = 0; |
1029 | 1029 | ||
1030 | pagevec_init(&pvec, 0); | 1030 | pagevec_init(&pvec, 0); |
1031 | 1031 | ||
1032 | next_step: | 1032 | next_step: |
1033 | index = 0; | 1033 | index = 0; |
1034 | end = LONG_MAX; | 1034 | end = LONG_MAX; |
1035 | 1035 | ||
1036 | while (index <= end) { | 1036 | while (index <= end) { |
1037 | int i, nr_pages; | 1037 | int i, nr_pages; |
1038 | nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, | 1038 | nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, |
1039 | PAGECACHE_TAG_DIRTY, | 1039 | PAGECACHE_TAG_DIRTY, |
1040 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); | 1040 | min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); |
1041 | if (nr_pages == 0) | 1041 | if (nr_pages == 0) |
1042 | break; | 1042 | break; |
1043 | 1043 | ||
1044 | for (i = 0; i < nr_pages; i++) { | 1044 | for (i = 0; i < nr_pages; i++) { |
1045 | struct page *page = pvec.pages[i]; | 1045 | struct page *page = pvec.pages[i]; |
1046 | 1046 | ||
1047 | /* | 1047 | /* |
1048 | * flushing sequence with step: | 1048 | * flushing sequence with step: |
1049 | * 0. indirect nodes | 1049 | * 0. indirect nodes |
1050 | * 1. dentry dnodes | 1050 | * 1. dentry dnodes |
1051 | * 2. file dnodes | 1051 | * 2. file dnodes |
1052 | */ | 1052 | */ |
1053 | if (step == 0 && IS_DNODE(page)) | 1053 | if (step == 0 && IS_DNODE(page)) |
1054 | continue; | 1054 | continue; |
1055 | if (step == 1 && (!IS_DNODE(page) || | 1055 | if (step == 1 && (!IS_DNODE(page) || |
1056 | is_cold_node(page))) | 1056 | is_cold_node(page))) |
1057 | continue; | 1057 | continue; |
1058 | if (step == 2 && (!IS_DNODE(page) || | 1058 | if (step == 2 && (!IS_DNODE(page) || |
1059 | !is_cold_node(page))) | 1059 | !is_cold_node(page))) |
1060 | continue; | 1060 | continue; |
1061 | 1061 | ||
1062 | /* | 1062 | /* |
1063 | * If an fsync mode, | 1063 | * If an fsync mode, |
1064 | * we should not skip writing node pages. | 1064 | * we should not skip writing node pages. |
1065 | */ | 1065 | */ |
1066 | if (ino && ino_of_node(page) == ino) | 1066 | if (ino && ino_of_node(page) == ino) |
1067 | lock_page(page); | 1067 | lock_page(page); |
1068 | else if (!trylock_page(page)) | 1068 | else if (!trylock_page(page)) |
1069 | continue; | 1069 | continue; |
1070 | 1070 | ||
1071 | if (unlikely(page->mapping != mapping)) { | 1071 | if (unlikely(page->mapping != mapping)) { |
1072 | continue_unlock: | 1072 | continue_unlock: |
1073 | unlock_page(page); | 1073 | unlock_page(page); |
1074 | continue; | 1074 | continue; |
1075 | } | 1075 | } |
1076 | if (ino && ino_of_node(page) != ino) | 1076 | if (ino && ino_of_node(page) != ino) |
1077 | goto continue_unlock; | 1077 | goto continue_unlock; |
1078 | 1078 | ||
1079 | if (!PageDirty(page)) { | 1079 | if (!PageDirty(page)) { |
1080 | /* someone wrote it for us */ | 1080 | /* someone wrote it for us */ |
1081 | goto continue_unlock; | 1081 | goto continue_unlock; |
1082 | } | 1082 | } |
1083 | 1083 | ||
1084 | if (!clear_page_dirty_for_io(page)) | 1084 | if (!clear_page_dirty_for_io(page)) |
1085 | goto continue_unlock; | 1085 | goto continue_unlock; |
1086 | 1086 | ||
1087 | /* called by fsync() */ | 1087 | /* called by fsync() */ |
1088 | if (ino && IS_DNODE(page)) { | 1088 | if (ino && IS_DNODE(page)) { |
1089 | int mark = !is_checkpointed_node(sbi, ino); | 1089 | int mark = !is_checkpointed_node(sbi, ino); |
1090 | set_fsync_mark(page, 1); | 1090 | set_fsync_mark(page, 1); |
1091 | if (IS_INODE(page)) | 1091 | if (IS_INODE(page)) |
1092 | set_dentry_mark(page, mark); | 1092 | set_dentry_mark(page, mark); |
1093 | nwritten++; | 1093 | nwritten++; |
1094 | } else { | 1094 | } else { |
1095 | set_fsync_mark(page, 0); | 1095 | set_fsync_mark(page, 0); |
1096 | set_dentry_mark(page, 0); | 1096 | set_dentry_mark(page, 0); |
1097 | } | 1097 | } |
1098 | mapping->a_ops->writepage(page, wbc); | 1098 | mapping->a_ops->writepage(page, wbc); |
1099 | wrote++; | 1099 | wrote++; |
1100 | 1100 | ||
1101 | if (--wbc->nr_to_write == 0) | 1101 | if (--wbc->nr_to_write == 0) |
1102 | break; | 1102 | break; |
1103 | } | 1103 | } |
1104 | pagevec_release(&pvec); | 1104 | pagevec_release(&pvec); |
1105 | cond_resched(); | 1105 | cond_resched(); |
1106 | 1106 | ||
1107 | if (wbc->nr_to_write == 0) { | 1107 | if (wbc->nr_to_write == 0) { |
1108 | step = 2; | 1108 | step = 2; |
1109 | break; | 1109 | break; |
1110 | } | 1110 | } |
1111 | } | 1111 | } |
1112 | 1112 | ||
1113 | if (step < 2) { | 1113 | if (step < 2) { |
1114 | step++; | 1114 | step++; |
1115 | goto next_step; | 1115 | goto next_step; |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | if (wrote) | 1118 | if (wrote) |
1119 | f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL); | 1119 | f2fs_submit_bio(sbi, NODE, wbc->sync_mode == WB_SYNC_ALL); |
1120 | 1120 | ||
1121 | return nwritten; | 1121 | return nwritten; |
1122 | } | 1122 | } |
1123 | 1123 | ||
1124 | static int f2fs_write_node_page(struct page *page, | 1124 | static int f2fs_write_node_page(struct page *page, |
1125 | struct writeback_control *wbc) | 1125 | struct writeback_control *wbc) |
1126 | { | 1126 | { |
1127 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | 1127 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); |
1128 | nid_t nid; | 1128 | nid_t nid; |
1129 | block_t new_addr; | 1129 | block_t new_addr; |
1130 | struct node_info ni; | 1130 | struct node_info ni; |
1131 | 1131 | ||
1132 | wait_on_page_writeback(page); | 1132 | wait_on_page_writeback(page); |
1133 | 1133 | ||
1134 | /* get old block addr of this node page */ | 1134 | /* get old block addr of this node page */ |
1135 | nid = nid_of_node(page); | 1135 | nid = nid_of_node(page); |
1136 | BUG_ON(page->index != nid); | 1136 | BUG_ON(page->index != nid); |
1137 | 1137 | ||
1138 | get_node_info(sbi, nid, &ni); | 1138 | get_node_info(sbi, nid, &ni); |
1139 | 1139 | ||
1140 | /* This page is already truncated */ | 1140 | /* This page is already truncated */ |
1141 | if (ni.blk_addr == NULL_ADDR) { | 1141 | if (ni.blk_addr == NULL_ADDR) { |
1142 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1142 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
1143 | unlock_page(page); | 1143 | unlock_page(page); |
1144 | return 0; | 1144 | return 0; |
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | if (wbc->for_reclaim) { | 1147 | if (wbc->for_reclaim) { |
1148 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1148 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
1149 | wbc->pages_skipped++; | 1149 | wbc->pages_skipped++; |
1150 | set_page_dirty(page); | 1150 | set_page_dirty(page); |
1151 | return AOP_WRITEPAGE_ACTIVATE; | 1151 | return AOP_WRITEPAGE_ACTIVATE; |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | mutex_lock(&sbi->node_write); | 1154 | mutex_lock(&sbi->node_write); |
1155 | set_page_writeback(page); | 1155 | set_page_writeback(page); |
1156 | write_node_page(sbi, page, nid, ni.blk_addr, &new_addr); | 1156 | write_node_page(sbi, page, nid, ni.blk_addr, &new_addr); |
1157 | set_node_addr(sbi, &ni, new_addr); | 1157 | set_node_addr(sbi, &ni, new_addr); |
1158 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1158 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
1159 | mutex_unlock(&sbi->node_write); | 1159 | mutex_unlock(&sbi->node_write); |
1160 | unlock_page(page); | 1160 | unlock_page(page); |
1161 | return 0; | 1161 | return 0; |
1162 | } | 1162 | } |
1163 | 1163 | ||
1164 | /* | 1164 | /* |
1165 | * It is very important to gather dirty pages and write at once, so that we can | 1165 | * It is very important to gather dirty pages and write at once, so that we can |
1166 | * submit a big bio without interfering other data writes. | 1166 | * submit a big bio without interfering other data writes. |
1167 | * Be default, 512 pages (2MB), a segment size, is quite reasonable. | 1167 | * Be default, 512 pages (2MB), a segment size, is quite reasonable. |
1168 | */ | 1168 | */ |
1169 | #define COLLECT_DIRTY_NODES 512 | 1169 | #define COLLECT_DIRTY_NODES 512 |
1170 | static int f2fs_write_node_pages(struct address_space *mapping, | 1170 | static int f2fs_write_node_pages(struct address_space *mapping, |
1171 | struct writeback_control *wbc) | 1171 | struct writeback_control *wbc) |
1172 | { | 1172 | { |
1173 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 1173 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
1174 | struct block_device *bdev = sbi->sb->s_bdev; | ||
1175 | long nr_to_write = wbc->nr_to_write; | 1174 | long nr_to_write = wbc->nr_to_write; |
1176 | 1175 | ||
1177 | /* First check balancing cached NAT entries */ | 1176 | /* First check balancing cached NAT entries */ |
1178 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { | 1177 | if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) { |
1179 | f2fs_sync_fs(sbi->sb, true); | 1178 | f2fs_sync_fs(sbi->sb, true); |
1180 | return 0; | 1179 | return 0; |
1181 | } | 1180 | } |
1182 | 1181 | ||
1183 | /* collect a number of dirty node pages and write together */ | 1182 | /* collect a number of dirty node pages and write together */ |
1184 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) | 1183 | if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES) |
1185 | return 0; | 1184 | return 0; |
1186 | 1185 | ||
1187 | /* if mounting is failed, skip writing node pages */ | 1186 | /* if mounting is failed, skip writing node pages */ |
1188 | wbc->nr_to_write = bio_get_nr_vecs(bdev); | 1187 | wbc->nr_to_write = max_hw_blocks(sbi); |
1189 | sync_node_pages(sbi, 0, wbc); | 1188 | sync_node_pages(sbi, 0, wbc); |
1190 | wbc->nr_to_write = nr_to_write - | 1189 | wbc->nr_to_write = nr_to_write - (max_hw_blocks(sbi) - wbc->nr_to_write); |
1191 | (bio_get_nr_vecs(bdev) - wbc->nr_to_write); | ||
1192 | return 0; | 1190 | return 0; |
1193 | } | 1191 | } |
1194 | 1192 | ||
1195 | static int f2fs_set_node_page_dirty(struct page *page) | 1193 | static int f2fs_set_node_page_dirty(struct page *page) |
1196 | { | 1194 | { |
1197 | struct address_space *mapping = page->mapping; | 1195 | struct address_space *mapping = page->mapping; |
1198 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); | 1196 | struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); |
1199 | 1197 | ||
1200 | SetPageUptodate(page); | 1198 | SetPageUptodate(page); |
1201 | if (!PageDirty(page)) { | 1199 | if (!PageDirty(page)) { |
1202 | __set_page_dirty_nobuffers(page); | 1200 | __set_page_dirty_nobuffers(page); |
1203 | inc_page_count(sbi, F2FS_DIRTY_NODES); | 1201 | inc_page_count(sbi, F2FS_DIRTY_NODES); |
1204 | SetPagePrivate(page); | 1202 | SetPagePrivate(page); |
1205 | return 1; | 1203 | return 1; |
1206 | } | 1204 | } |
1207 | return 0; | 1205 | return 0; |
1208 | } | 1206 | } |
1209 | 1207 | ||
1210 | static void f2fs_invalidate_node_page(struct page *page, unsigned long offset) | 1208 | static void f2fs_invalidate_node_page(struct page *page, unsigned long offset) |
1211 | { | 1209 | { |
1212 | struct inode *inode = page->mapping->host; | 1210 | struct inode *inode = page->mapping->host; |
1213 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 1211 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
1214 | if (PageDirty(page)) | 1212 | if (PageDirty(page)) |
1215 | dec_page_count(sbi, F2FS_DIRTY_NODES); | 1213 | dec_page_count(sbi, F2FS_DIRTY_NODES); |
1216 | ClearPagePrivate(page); | 1214 | ClearPagePrivate(page); |
1217 | } | 1215 | } |
1218 | 1216 | ||
1219 | static int f2fs_release_node_page(struct page *page, gfp_t wait) | 1217 | static int f2fs_release_node_page(struct page *page, gfp_t wait) |
1220 | { | 1218 | { |
1221 | ClearPagePrivate(page); | 1219 | ClearPagePrivate(page); |
1222 | return 1; | 1220 | return 1; |
1223 | } | 1221 | } |
1224 | 1222 | ||
1225 | /* | 1223 | /* |
1226 | * Structure of the f2fs node operations | 1224 | * Structure of the f2fs node operations |
1227 | */ | 1225 | */ |
1228 | const struct address_space_operations f2fs_node_aops = { | 1226 | const struct address_space_operations f2fs_node_aops = { |
1229 | .writepage = f2fs_write_node_page, | 1227 | .writepage = f2fs_write_node_page, |
1230 | .writepages = f2fs_write_node_pages, | 1228 | .writepages = f2fs_write_node_pages, |
1231 | .set_page_dirty = f2fs_set_node_page_dirty, | 1229 | .set_page_dirty = f2fs_set_node_page_dirty, |
1232 | .invalidatepage = f2fs_invalidate_node_page, | 1230 | .invalidatepage = f2fs_invalidate_node_page, |
1233 | .releasepage = f2fs_release_node_page, | 1231 | .releasepage = f2fs_release_node_page, |
1234 | }; | 1232 | }; |
1235 | 1233 | ||
1236 | static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head) | 1234 | static struct free_nid *__lookup_free_nid_list(nid_t n, struct list_head *head) |
1237 | { | 1235 | { |
1238 | struct list_head *this; | 1236 | struct list_head *this; |
1239 | struct free_nid *i; | 1237 | struct free_nid *i; |
1240 | list_for_each(this, head) { | 1238 | list_for_each(this, head) { |
1241 | i = list_entry(this, struct free_nid, list); | 1239 | i = list_entry(this, struct free_nid, list); |
1242 | if (i->nid == n) | 1240 | if (i->nid == n) |
1243 | return i; | 1241 | return i; |
1244 | } | 1242 | } |
1245 | return NULL; | 1243 | return NULL; |
1246 | } | 1244 | } |
1247 | 1245 | ||
1248 | static void __del_from_free_nid_list(struct free_nid *i) | 1246 | static void __del_from_free_nid_list(struct free_nid *i) |
1249 | { | 1247 | { |
1250 | list_del(&i->list); | 1248 | list_del(&i->list); |
1251 | kmem_cache_free(free_nid_slab, i); | 1249 | kmem_cache_free(free_nid_slab, i); |
1252 | } | 1250 | } |
1253 | 1251 | ||
1254 | static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) | 1252 | static int add_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) |
1255 | { | 1253 | { |
1256 | struct free_nid *i; | 1254 | struct free_nid *i; |
1257 | 1255 | ||
1258 | if (nm_i->fcnt > 2 * MAX_FREE_NIDS) | 1256 | if (nm_i->fcnt > 2 * MAX_FREE_NIDS) |
1259 | return 0; | 1257 | return 0; |
1260 | 1258 | ||
1261 | /* 0 nid should not be used */ | 1259 | /* 0 nid should not be used */ |
1262 | if (nid == 0) | 1260 | if (nid == 0) |
1263 | return 0; | 1261 | return 0; |
1264 | retry: | 1262 | retry: |
1265 | i = kmem_cache_alloc(free_nid_slab, GFP_NOFS); | 1263 | i = kmem_cache_alloc(free_nid_slab, GFP_NOFS); |
1266 | if (!i) { | 1264 | if (!i) { |
1267 | cond_resched(); | 1265 | cond_resched(); |
1268 | goto retry; | 1266 | goto retry; |
1269 | } | 1267 | } |
1270 | i->nid = nid; | 1268 | i->nid = nid; |
1271 | i->state = NID_NEW; | 1269 | i->state = NID_NEW; |
1272 | 1270 | ||
1273 | spin_lock(&nm_i->free_nid_list_lock); | 1271 | spin_lock(&nm_i->free_nid_list_lock); |
1274 | if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) { | 1272 | if (__lookup_free_nid_list(nid, &nm_i->free_nid_list)) { |
1275 | spin_unlock(&nm_i->free_nid_list_lock); | 1273 | spin_unlock(&nm_i->free_nid_list_lock); |
1276 | kmem_cache_free(free_nid_slab, i); | 1274 | kmem_cache_free(free_nid_slab, i); |
1277 | return 0; | 1275 | return 0; |
1278 | } | 1276 | } |
1279 | list_add_tail(&i->list, &nm_i->free_nid_list); | 1277 | list_add_tail(&i->list, &nm_i->free_nid_list); |
1280 | nm_i->fcnt++; | 1278 | nm_i->fcnt++; |
1281 | spin_unlock(&nm_i->free_nid_list_lock); | 1279 | spin_unlock(&nm_i->free_nid_list_lock); |
1282 | return 1; | 1280 | return 1; |
1283 | } | 1281 | } |
1284 | 1282 | ||
1285 | static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) | 1283 | static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) |
1286 | { | 1284 | { |
1287 | struct free_nid *i; | 1285 | struct free_nid *i; |
1288 | spin_lock(&nm_i->free_nid_list_lock); | 1286 | spin_lock(&nm_i->free_nid_list_lock); |
1289 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1287 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1290 | if (i && i->state == NID_NEW) { | 1288 | if (i && i->state == NID_NEW) { |
1291 | __del_from_free_nid_list(i); | 1289 | __del_from_free_nid_list(i); |
1292 | nm_i->fcnt--; | 1290 | nm_i->fcnt--; |
1293 | } | 1291 | } |
1294 | spin_unlock(&nm_i->free_nid_list_lock); | 1292 | spin_unlock(&nm_i->free_nid_list_lock); |
1295 | } | 1293 | } |
1296 | 1294 | ||
1297 | static int scan_nat_page(struct f2fs_nm_info *nm_i, | 1295 | static int scan_nat_page(struct f2fs_nm_info *nm_i, |
1298 | struct page *nat_page, nid_t start_nid) | 1296 | struct page *nat_page, nid_t start_nid) |
1299 | { | 1297 | { |
1300 | struct f2fs_nat_block *nat_blk = page_address(nat_page); | 1298 | struct f2fs_nat_block *nat_blk = page_address(nat_page); |
1301 | block_t blk_addr; | 1299 | block_t blk_addr; |
1302 | int fcnt = 0; | 1300 | int fcnt = 0; |
1303 | int i; | 1301 | int i; |
1304 | 1302 | ||
1305 | i = start_nid % NAT_ENTRY_PER_BLOCK; | 1303 | i = start_nid % NAT_ENTRY_PER_BLOCK; |
1306 | 1304 | ||
1307 | for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { | 1305 | for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { |
1308 | if (start_nid >= nm_i->max_nid) | 1306 | if (start_nid >= nm_i->max_nid) |
1309 | break; | 1307 | break; |
1310 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); | 1308 | blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); |
1311 | BUG_ON(blk_addr == NEW_ADDR); | 1309 | BUG_ON(blk_addr == NEW_ADDR); |
1312 | if (blk_addr == NULL_ADDR) | 1310 | if (blk_addr == NULL_ADDR) |
1313 | fcnt += add_free_nid(nm_i, start_nid); | 1311 | fcnt += add_free_nid(nm_i, start_nid); |
1314 | } | 1312 | } |
1315 | return fcnt; | 1313 | return fcnt; |
1316 | } | 1314 | } |
1317 | 1315 | ||
1318 | static void build_free_nids(struct f2fs_sb_info *sbi) | 1316 | static void build_free_nids(struct f2fs_sb_info *sbi) |
1319 | { | 1317 | { |
1320 | struct free_nid *fnid, *next_fnid; | 1318 | struct free_nid *fnid, *next_fnid; |
1321 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1319 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1322 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1320 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
1323 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1321 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1324 | int fcnt = 0, i = 0; | 1322 | int fcnt = 0, i = 0; |
1325 | nid_t nid = nm_i->next_scan_nid; | 1323 | nid_t nid = nm_i->next_scan_nid; |
1326 | 1324 | ||
1327 | /* Enough entries */ | 1325 | /* Enough entries */ |
1328 | if (nm_i->fcnt > NAT_ENTRY_PER_BLOCK) | 1326 | if (nm_i->fcnt > NAT_ENTRY_PER_BLOCK) |
1329 | return; | 1327 | return; |
1330 | 1328 | ||
1331 | /* readahead nat pages to be scanned */ | 1329 | /* readahead nat pages to be scanned */ |
1332 | ra_nat_pages(sbi, nid); | 1330 | ra_nat_pages(sbi, nid); |
1333 | 1331 | ||
1334 | while (1) { | 1332 | while (1) { |
1335 | struct page *page = get_current_nat_page(sbi, nid); | 1333 | struct page *page = get_current_nat_page(sbi, nid); |
1336 | 1334 | ||
1337 | fcnt += scan_nat_page(nm_i, page, nid); | 1335 | fcnt += scan_nat_page(nm_i, page, nid); |
1338 | f2fs_put_page(page, 1); | 1336 | f2fs_put_page(page, 1); |
1339 | 1337 | ||
1340 | nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); | 1338 | nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); |
1341 | if (nid >= nm_i->max_nid) | 1339 | if (nid >= nm_i->max_nid) |
1342 | nid = 0; | 1340 | nid = 0; |
1343 | 1341 | ||
1344 | if (i++ == FREE_NID_PAGES) | 1342 | if (i++ == FREE_NID_PAGES) |
1345 | break; | 1343 | break; |
1346 | } | 1344 | } |
1347 | 1345 | ||
1348 | /* go to the next free nat pages to find free nids abundantly */ | 1346 | /* go to the next free nat pages to find free nids abundantly */ |
1349 | nm_i->next_scan_nid = nid; | 1347 | nm_i->next_scan_nid = nid; |
1350 | 1348 | ||
1351 | /* find free nids from current sum_pages */ | 1349 | /* find free nids from current sum_pages */ |
1352 | mutex_lock(&curseg->curseg_mutex); | 1350 | mutex_lock(&curseg->curseg_mutex); |
1353 | for (i = 0; i < nats_in_cursum(sum); i++) { | 1351 | for (i = 0; i < nats_in_cursum(sum); i++) { |
1354 | block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr); | 1352 | block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr); |
1355 | nid = le32_to_cpu(nid_in_journal(sum, i)); | 1353 | nid = le32_to_cpu(nid_in_journal(sum, i)); |
1356 | if (addr == NULL_ADDR) | 1354 | if (addr == NULL_ADDR) |
1357 | add_free_nid(nm_i, nid); | 1355 | add_free_nid(nm_i, nid); |
1358 | else | 1356 | else |
1359 | remove_free_nid(nm_i, nid); | 1357 | remove_free_nid(nm_i, nid); |
1360 | } | 1358 | } |
1361 | mutex_unlock(&curseg->curseg_mutex); | 1359 | mutex_unlock(&curseg->curseg_mutex); |
1362 | 1360 | ||
1363 | /* remove the free nids from current allocated nids */ | 1361 | /* remove the free nids from current allocated nids */ |
1364 | list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) { | 1362 | list_for_each_entry_safe(fnid, next_fnid, &nm_i->free_nid_list, list) { |
1365 | struct nat_entry *ne; | 1363 | struct nat_entry *ne; |
1366 | 1364 | ||
1367 | read_lock(&nm_i->nat_tree_lock); | 1365 | read_lock(&nm_i->nat_tree_lock); |
1368 | ne = __lookup_nat_cache(nm_i, fnid->nid); | 1366 | ne = __lookup_nat_cache(nm_i, fnid->nid); |
1369 | if (ne && nat_get_blkaddr(ne) != NULL_ADDR) | 1367 | if (ne && nat_get_blkaddr(ne) != NULL_ADDR) |
1370 | remove_free_nid(nm_i, fnid->nid); | 1368 | remove_free_nid(nm_i, fnid->nid); |
1371 | read_unlock(&nm_i->nat_tree_lock); | 1369 | read_unlock(&nm_i->nat_tree_lock); |
1372 | } | 1370 | } |
1373 | } | 1371 | } |
1374 | 1372 | ||
1375 | /* | 1373 | /* |
1376 | * If this function returns success, caller can obtain a new nid | 1374 | * If this function returns success, caller can obtain a new nid |
1377 | * from second parameter of this function. | 1375 | * from second parameter of this function. |
1378 | * The returned nid could be used ino as well as nid when inode is created. | 1376 | * The returned nid could be used ino as well as nid when inode is created. |
1379 | */ | 1377 | */ |
1380 | bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) | 1378 | bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) |
1381 | { | 1379 | { |
1382 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1380 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1383 | struct free_nid *i = NULL; | 1381 | struct free_nid *i = NULL; |
1384 | struct list_head *this; | 1382 | struct list_head *this; |
1385 | retry: | 1383 | retry: |
1386 | if (sbi->total_valid_node_count + 1 >= nm_i->max_nid) | 1384 | if (sbi->total_valid_node_count + 1 >= nm_i->max_nid) |
1387 | return false; | 1385 | return false; |
1388 | 1386 | ||
1389 | spin_lock(&nm_i->free_nid_list_lock); | 1387 | spin_lock(&nm_i->free_nid_list_lock); |
1390 | 1388 | ||
1391 | /* We should not use stale free nids created by build_free_nids */ | 1389 | /* We should not use stale free nids created by build_free_nids */ |
1392 | if (nm_i->fcnt && !sbi->on_build_free_nids) { | 1390 | if (nm_i->fcnt && !sbi->on_build_free_nids) { |
1393 | BUG_ON(list_empty(&nm_i->free_nid_list)); | 1391 | BUG_ON(list_empty(&nm_i->free_nid_list)); |
1394 | list_for_each(this, &nm_i->free_nid_list) { | 1392 | list_for_each(this, &nm_i->free_nid_list) { |
1395 | i = list_entry(this, struct free_nid, list); | 1393 | i = list_entry(this, struct free_nid, list); |
1396 | if (i->state == NID_NEW) | 1394 | if (i->state == NID_NEW) |
1397 | break; | 1395 | break; |
1398 | } | 1396 | } |
1399 | 1397 | ||
1400 | BUG_ON(i->state != NID_NEW); | 1398 | BUG_ON(i->state != NID_NEW); |
1401 | *nid = i->nid; | 1399 | *nid = i->nid; |
1402 | i->state = NID_ALLOC; | 1400 | i->state = NID_ALLOC; |
1403 | nm_i->fcnt--; | 1401 | nm_i->fcnt--; |
1404 | spin_unlock(&nm_i->free_nid_list_lock); | 1402 | spin_unlock(&nm_i->free_nid_list_lock); |
1405 | return true; | 1403 | return true; |
1406 | } | 1404 | } |
1407 | spin_unlock(&nm_i->free_nid_list_lock); | 1405 | spin_unlock(&nm_i->free_nid_list_lock); |
1408 | 1406 | ||
1409 | /* Let's scan nat pages and its caches to get free nids */ | 1407 | /* Let's scan nat pages and its caches to get free nids */ |
1410 | mutex_lock(&nm_i->build_lock); | 1408 | mutex_lock(&nm_i->build_lock); |
1411 | sbi->on_build_free_nids = 1; | 1409 | sbi->on_build_free_nids = 1; |
1412 | build_free_nids(sbi); | 1410 | build_free_nids(sbi); |
1413 | sbi->on_build_free_nids = 0; | 1411 | sbi->on_build_free_nids = 0; |
1414 | mutex_unlock(&nm_i->build_lock); | 1412 | mutex_unlock(&nm_i->build_lock); |
1415 | goto retry; | 1413 | goto retry; |
1416 | } | 1414 | } |
1417 | 1415 | ||
1418 | /* | 1416 | /* |
1419 | * alloc_nid() should be called prior to this function. | 1417 | * alloc_nid() should be called prior to this function. |
1420 | */ | 1418 | */ |
1421 | void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) | 1419 | void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) |
1422 | { | 1420 | { |
1423 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1421 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1424 | struct free_nid *i; | 1422 | struct free_nid *i; |
1425 | 1423 | ||
1426 | spin_lock(&nm_i->free_nid_list_lock); | 1424 | spin_lock(&nm_i->free_nid_list_lock); |
1427 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1425 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1428 | BUG_ON(!i || i->state != NID_ALLOC); | 1426 | BUG_ON(!i || i->state != NID_ALLOC); |
1429 | __del_from_free_nid_list(i); | 1427 | __del_from_free_nid_list(i); |
1430 | spin_unlock(&nm_i->free_nid_list_lock); | 1428 | spin_unlock(&nm_i->free_nid_list_lock); |
1431 | } | 1429 | } |
1432 | 1430 | ||
1433 | /* | 1431 | /* |
1434 | * alloc_nid() should be called prior to this function. | 1432 | * alloc_nid() should be called prior to this function. |
1435 | */ | 1433 | */ |
1436 | void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) | 1434 | void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) |
1437 | { | 1435 | { |
1438 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1436 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1439 | struct free_nid *i; | 1437 | struct free_nid *i; |
1440 | 1438 | ||
1441 | spin_lock(&nm_i->free_nid_list_lock); | 1439 | spin_lock(&nm_i->free_nid_list_lock); |
1442 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); | 1440 | i = __lookup_free_nid_list(nid, &nm_i->free_nid_list); |
1443 | BUG_ON(!i || i->state != NID_ALLOC); | 1441 | BUG_ON(!i || i->state != NID_ALLOC); |
1444 | i->state = NID_NEW; | 1442 | i->state = NID_NEW; |
1445 | nm_i->fcnt++; | 1443 | nm_i->fcnt++; |
1446 | spin_unlock(&nm_i->free_nid_list_lock); | 1444 | spin_unlock(&nm_i->free_nid_list_lock); |
1447 | } | 1445 | } |
1448 | 1446 | ||
1449 | void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, | 1447 | void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, |
1450 | struct f2fs_summary *sum, struct node_info *ni, | 1448 | struct f2fs_summary *sum, struct node_info *ni, |
1451 | block_t new_blkaddr) | 1449 | block_t new_blkaddr) |
1452 | { | 1450 | { |
1453 | rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr); | 1451 | rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr); |
1454 | set_node_addr(sbi, ni, new_blkaddr); | 1452 | set_node_addr(sbi, ni, new_blkaddr); |
1455 | clear_node_page_dirty(page); | 1453 | clear_node_page_dirty(page); |
1456 | } | 1454 | } |
1457 | 1455 | ||
1458 | int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) | 1456 | int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) |
1459 | { | 1457 | { |
1460 | struct address_space *mapping = sbi->node_inode->i_mapping; | 1458 | struct address_space *mapping = sbi->node_inode->i_mapping; |
1461 | struct f2fs_node *src, *dst; | 1459 | struct f2fs_node *src, *dst; |
1462 | nid_t ino = ino_of_node(page); | 1460 | nid_t ino = ino_of_node(page); |
1463 | struct node_info old_ni, new_ni; | 1461 | struct node_info old_ni, new_ni; |
1464 | struct page *ipage; | 1462 | struct page *ipage; |
1465 | 1463 | ||
1466 | ipage = grab_cache_page(mapping, ino); | 1464 | ipage = grab_cache_page(mapping, ino); |
1467 | if (!ipage) | 1465 | if (!ipage) |
1468 | return -ENOMEM; | 1466 | return -ENOMEM; |
1469 | 1467 | ||
1470 | /* Should not use this inode from free nid list */ | 1468 | /* Should not use this inode from free nid list */ |
1471 | remove_free_nid(NM_I(sbi), ino); | 1469 | remove_free_nid(NM_I(sbi), ino); |
1472 | 1470 | ||
1473 | get_node_info(sbi, ino, &old_ni); | 1471 | get_node_info(sbi, ino, &old_ni); |
1474 | SetPageUptodate(ipage); | 1472 | SetPageUptodate(ipage); |
1475 | fill_node_footer(ipage, ino, ino, 0, true); | 1473 | fill_node_footer(ipage, ino, ino, 0, true); |
1476 | 1474 | ||
1477 | src = (struct f2fs_node *)page_address(page); | 1475 | src = (struct f2fs_node *)page_address(page); |
1478 | dst = (struct f2fs_node *)page_address(ipage); | 1476 | dst = (struct f2fs_node *)page_address(ipage); |
1479 | 1477 | ||
1480 | memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i); | 1478 | memcpy(dst, src, (unsigned long)&src->i.i_ext - (unsigned long)&src->i); |
1481 | dst->i.i_size = 0; | 1479 | dst->i.i_size = 0; |
1482 | dst->i.i_blocks = cpu_to_le64(1); | 1480 | dst->i.i_blocks = cpu_to_le64(1); |
1483 | dst->i.i_links = cpu_to_le32(1); | 1481 | dst->i.i_links = cpu_to_le32(1); |
1484 | dst->i.i_xattr_nid = 0; | 1482 | dst->i.i_xattr_nid = 0; |
1485 | 1483 | ||
1486 | new_ni = old_ni; | 1484 | new_ni = old_ni; |
1487 | new_ni.ino = ino; | 1485 | new_ni.ino = ino; |
1488 | 1486 | ||
1489 | set_node_addr(sbi, &new_ni, NEW_ADDR); | 1487 | set_node_addr(sbi, &new_ni, NEW_ADDR); |
1490 | inc_valid_inode_count(sbi); | 1488 | inc_valid_inode_count(sbi); |
1491 | 1489 | ||
1492 | f2fs_put_page(ipage, 1); | 1490 | f2fs_put_page(ipage, 1); |
1493 | return 0; | 1491 | return 0; |
1494 | } | 1492 | } |
1495 | 1493 | ||
1496 | int restore_node_summary(struct f2fs_sb_info *sbi, | 1494 | int restore_node_summary(struct f2fs_sb_info *sbi, |
1497 | unsigned int segno, struct f2fs_summary_block *sum) | 1495 | unsigned int segno, struct f2fs_summary_block *sum) |
1498 | { | 1496 | { |
1499 | struct f2fs_node *rn; | 1497 | struct f2fs_node *rn; |
1500 | struct f2fs_summary *sum_entry; | 1498 | struct f2fs_summary *sum_entry; |
1501 | struct page *page; | 1499 | struct page *page; |
1502 | block_t addr; | 1500 | block_t addr; |
1503 | int i, last_offset; | 1501 | int i, last_offset; |
1504 | 1502 | ||
1505 | /* alloc temporal page for read node */ | 1503 | /* alloc temporal page for read node */ |
1506 | page = alloc_page(GFP_NOFS | __GFP_ZERO); | 1504 | page = alloc_page(GFP_NOFS | __GFP_ZERO); |
1507 | if (IS_ERR(page)) | 1505 | if (IS_ERR(page)) |
1508 | return PTR_ERR(page); | 1506 | return PTR_ERR(page); |
1509 | lock_page(page); | 1507 | lock_page(page); |
1510 | 1508 | ||
1511 | /* scan the node segment */ | 1509 | /* scan the node segment */ |
1512 | last_offset = sbi->blocks_per_seg; | 1510 | last_offset = sbi->blocks_per_seg; |
1513 | addr = START_BLOCK(sbi, segno); | 1511 | addr = START_BLOCK(sbi, segno); |
1514 | sum_entry = &sum->entries[0]; | 1512 | sum_entry = &sum->entries[0]; |
1515 | 1513 | ||
1516 | for (i = 0; i < last_offset; i++, sum_entry++) { | 1514 | for (i = 0; i < last_offset; i++, sum_entry++) { |
1517 | /* | 1515 | /* |
1518 | * In order to read next node page, | 1516 | * In order to read next node page, |
1519 | * we must clear PageUptodate flag. | 1517 | * we must clear PageUptodate flag. |
1520 | */ | 1518 | */ |
1521 | ClearPageUptodate(page); | 1519 | ClearPageUptodate(page); |
1522 | 1520 | ||
1523 | if (f2fs_readpage(sbi, page, addr, READ_SYNC)) | 1521 | if (f2fs_readpage(sbi, page, addr, READ_SYNC)) |
1524 | goto out; | 1522 | goto out; |
1525 | 1523 | ||
1526 | lock_page(page); | 1524 | lock_page(page); |
1527 | rn = (struct f2fs_node *)page_address(page); | 1525 | rn = (struct f2fs_node *)page_address(page); |
1528 | sum_entry->nid = rn->footer.nid; | 1526 | sum_entry->nid = rn->footer.nid; |
1529 | sum_entry->version = 0; | 1527 | sum_entry->version = 0; |
1530 | sum_entry->ofs_in_node = 0; | 1528 | sum_entry->ofs_in_node = 0; |
1531 | addr++; | 1529 | addr++; |
1532 | } | 1530 | } |
1533 | unlock_page(page); | 1531 | unlock_page(page); |
1534 | out: | 1532 | out: |
1535 | __free_pages(page, 0); | 1533 | __free_pages(page, 0); |
1536 | return 0; | 1534 | return 0; |
1537 | } | 1535 | } |
1538 | 1536 | ||
1539 | static bool flush_nats_in_journal(struct f2fs_sb_info *sbi) | 1537 | static bool flush_nats_in_journal(struct f2fs_sb_info *sbi) |
1540 | { | 1538 | { |
1541 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1539 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1542 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1540 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
1543 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1541 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1544 | int i; | 1542 | int i; |
1545 | 1543 | ||
1546 | mutex_lock(&curseg->curseg_mutex); | 1544 | mutex_lock(&curseg->curseg_mutex); |
1547 | 1545 | ||
1548 | if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) { | 1546 | if (nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) { |
1549 | mutex_unlock(&curseg->curseg_mutex); | 1547 | mutex_unlock(&curseg->curseg_mutex); |
1550 | return false; | 1548 | return false; |
1551 | } | 1549 | } |
1552 | 1550 | ||
1553 | for (i = 0; i < nats_in_cursum(sum); i++) { | 1551 | for (i = 0; i < nats_in_cursum(sum); i++) { |
1554 | struct nat_entry *ne; | 1552 | struct nat_entry *ne; |
1555 | struct f2fs_nat_entry raw_ne; | 1553 | struct f2fs_nat_entry raw_ne; |
1556 | nid_t nid = le32_to_cpu(nid_in_journal(sum, i)); | 1554 | nid_t nid = le32_to_cpu(nid_in_journal(sum, i)); |
1557 | 1555 | ||
1558 | raw_ne = nat_in_journal(sum, i); | 1556 | raw_ne = nat_in_journal(sum, i); |
1559 | retry: | 1557 | retry: |
1560 | write_lock(&nm_i->nat_tree_lock); | 1558 | write_lock(&nm_i->nat_tree_lock); |
1561 | ne = __lookup_nat_cache(nm_i, nid); | 1559 | ne = __lookup_nat_cache(nm_i, nid); |
1562 | if (ne) { | 1560 | if (ne) { |
1563 | __set_nat_cache_dirty(nm_i, ne); | 1561 | __set_nat_cache_dirty(nm_i, ne); |
1564 | write_unlock(&nm_i->nat_tree_lock); | 1562 | write_unlock(&nm_i->nat_tree_lock); |
1565 | continue; | 1563 | continue; |
1566 | } | 1564 | } |
1567 | ne = grab_nat_entry(nm_i, nid); | 1565 | ne = grab_nat_entry(nm_i, nid); |
1568 | if (!ne) { | 1566 | if (!ne) { |
1569 | write_unlock(&nm_i->nat_tree_lock); | 1567 | write_unlock(&nm_i->nat_tree_lock); |
1570 | goto retry; | 1568 | goto retry; |
1571 | } | 1569 | } |
1572 | nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr)); | 1570 | nat_set_blkaddr(ne, le32_to_cpu(raw_ne.block_addr)); |
1573 | nat_set_ino(ne, le32_to_cpu(raw_ne.ino)); | 1571 | nat_set_ino(ne, le32_to_cpu(raw_ne.ino)); |
1574 | nat_set_version(ne, raw_ne.version); | 1572 | nat_set_version(ne, raw_ne.version); |
1575 | __set_nat_cache_dirty(nm_i, ne); | 1573 | __set_nat_cache_dirty(nm_i, ne); |
1576 | write_unlock(&nm_i->nat_tree_lock); | 1574 | write_unlock(&nm_i->nat_tree_lock); |
1577 | } | 1575 | } |
1578 | update_nats_in_cursum(sum, -i); | 1576 | update_nats_in_cursum(sum, -i); |
1579 | mutex_unlock(&curseg->curseg_mutex); | 1577 | mutex_unlock(&curseg->curseg_mutex); |
1580 | return true; | 1578 | return true; |
1581 | } | 1579 | } |
1582 | 1580 | ||
1583 | /* | 1581 | /* |
1584 | * This function is called during the checkpointing process. | 1582 | * This function is called during the checkpointing process. |
1585 | */ | 1583 | */ |
1586 | void flush_nat_entries(struct f2fs_sb_info *sbi) | 1584 | void flush_nat_entries(struct f2fs_sb_info *sbi) |
1587 | { | 1585 | { |
1588 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1586 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1589 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1587 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
1590 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1588 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1591 | struct list_head *cur, *n; | 1589 | struct list_head *cur, *n; |
1592 | struct page *page = NULL; | 1590 | struct page *page = NULL; |
1593 | struct f2fs_nat_block *nat_blk = NULL; | 1591 | struct f2fs_nat_block *nat_blk = NULL; |
1594 | nid_t start_nid = 0, end_nid = 0; | 1592 | nid_t start_nid = 0, end_nid = 0; |
1595 | bool flushed; | 1593 | bool flushed; |
1596 | 1594 | ||
1597 | flushed = flush_nats_in_journal(sbi); | 1595 | flushed = flush_nats_in_journal(sbi); |
1598 | 1596 | ||
1599 | if (!flushed) | 1597 | if (!flushed) |
1600 | mutex_lock(&curseg->curseg_mutex); | 1598 | mutex_lock(&curseg->curseg_mutex); |
1601 | 1599 | ||
1602 | /* 1) flush dirty nat caches */ | 1600 | /* 1) flush dirty nat caches */ |
1603 | list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) { | 1601 | list_for_each_safe(cur, n, &nm_i->dirty_nat_entries) { |
1604 | struct nat_entry *ne; | 1602 | struct nat_entry *ne; |
1605 | nid_t nid; | 1603 | nid_t nid; |
1606 | struct f2fs_nat_entry raw_ne; | 1604 | struct f2fs_nat_entry raw_ne; |
1607 | int offset = -1; | 1605 | int offset = -1; |
1608 | block_t new_blkaddr; | 1606 | block_t new_blkaddr; |
1609 | 1607 | ||
1610 | ne = list_entry(cur, struct nat_entry, list); | 1608 | ne = list_entry(cur, struct nat_entry, list); |
1611 | nid = nat_get_nid(ne); | 1609 | nid = nat_get_nid(ne); |
1612 | 1610 | ||
1613 | if (nat_get_blkaddr(ne) == NEW_ADDR) | 1611 | if (nat_get_blkaddr(ne) == NEW_ADDR) |
1614 | continue; | 1612 | continue; |
1615 | if (flushed) | 1613 | if (flushed) |
1616 | goto to_nat_page; | 1614 | goto to_nat_page; |
1617 | 1615 | ||
1618 | /* if there is room for nat enries in curseg->sumpage */ | 1616 | /* if there is room for nat enries in curseg->sumpage */ |
1619 | offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1); | 1617 | offset = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 1); |
1620 | if (offset >= 0) { | 1618 | if (offset >= 0) { |
1621 | raw_ne = nat_in_journal(sum, offset); | 1619 | raw_ne = nat_in_journal(sum, offset); |
1622 | goto flush_now; | 1620 | goto flush_now; |
1623 | } | 1621 | } |
1624 | to_nat_page: | 1622 | to_nat_page: |
1625 | if (!page || (start_nid > nid || nid > end_nid)) { | 1623 | if (!page || (start_nid > nid || nid > end_nid)) { |
1626 | if (page) { | 1624 | if (page) { |
1627 | f2fs_put_page(page, 1); | 1625 | f2fs_put_page(page, 1); |
1628 | page = NULL; | 1626 | page = NULL; |
1629 | } | 1627 | } |
1630 | start_nid = START_NID(nid); | 1628 | start_nid = START_NID(nid); |
1631 | end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1; | 1629 | end_nid = start_nid + NAT_ENTRY_PER_BLOCK - 1; |
1632 | 1630 | ||
1633 | /* | 1631 | /* |
1634 | * get nat block with dirty flag, increased reference | 1632 | * get nat block with dirty flag, increased reference |
1635 | * count, mapped and lock | 1633 | * count, mapped and lock |
1636 | */ | 1634 | */ |
1637 | page = get_next_nat_page(sbi, start_nid); | 1635 | page = get_next_nat_page(sbi, start_nid); |
1638 | nat_blk = page_address(page); | 1636 | nat_blk = page_address(page); |
1639 | } | 1637 | } |
1640 | 1638 | ||
1641 | BUG_ON(!nat_blk); | 1639 | BUG_ON(!nat_blk); |
1642 | raw_ne = nat_blk->entries[nid - start_nid]; | 1640 | raw_ne = nat_blk->entries[nid - start_nid]; |
1643 | flush_now: | 1641 | flush_now: |
1644 | new_blkaddr = nat_get_blkaddr(ne); | 1642 | new_blkaddr = nat_get_blkaddr(ne); |
1645 | 1643 | ||
1646 | raw_ne.ino = cpu_to_le32(nat_get_ino(ne)); | 1644 | raw_ne.ino = cpu_to_le32(nat_get_ino(ne)); |
1647 | raw_ne.block_addr = cpu_to_le32(new_blkaddr); | 1645 | raw_ne.block_addr = cpu_to_le32(new_blkaddr); |
1648 | raw_ne.version = nat_get_version(ne); | 1646 | raw_ne.version = nat_get_version(ne); |
1649 | 1647 | ||
1650 | if (offset < 0) { | 1648 | if (offset < 0) { |
1651 | nat_blk->entries[nid - start_nid] = raw_ne; | 1649 | nat_blk->entries[nid - start_nid] = raw_ne; |
1652 | } else { | 1650 | } else { |
1653 | nat_in_journal(sum, offset) = raw_ne; | 1651 | nat_in_journal(sum, offset) = raw_ne; |
1654 | nid_in_journal(sum, offset) = cpu_to_le32(nid); | 1652 | nid_in_journal(sum, offset) = cpu_to_le32(nid); |
1655 | } | 1653 | } |
1656 | 1654 | ||
1657 | if (nat_get_blkaddr(ne) == NULL_ADDR && | 1655 | if (nat_get_blkaddr(ne) == NULL_ADDR && |
1658 | !add_free_nid(NM_I(sbi), nid)) { | 1656 | !add_free_nid(NM_I(sbi), nid)) { |
1659 | write_lock(&nm_i->nat_tree_lock); | 1657 | write_lock(&nm_i->nat_tree_lock); |
1660 | __del_from_nat_cache(nm_i, ne); | 1658 | __del_from_nat_cache(nm_i, ne); |
1661 | write_unlock(&nm_i->nat_tree_lock); | 1659 | write_unlock(&nm_i->nat_tree_lock); |
1662 | } else { | 1660 | } else { |
1663 | write_lock(&nm_i->nat_tree_lock); | 1661 | write_lock(&nm_i->nat_tree_lock); |
1664 | __clear_nat_cache_dirty(nm_i, ne); | 1662 | __clear_nat_cache_dirty(nm_i, ne); |
1665 | ne->checkpointed = true; | 1663 | ne->checkpointed = true; |
1666 | write_unlock(&nm_i->nat_tree_lock); | 1664 | write_unlock(&nm_i->nat_tree_lock); |
1667 | } | 1665 | } |
1668 | } | 1666 | } |
1669 | if (!flushed) | 1667 | if (!flushed) |
1670 | mutex_unlock(&curseg->curseg_mutex); | 1668 | mutex_unlock(&curseg->curseg_mutex); |
1671 | f2fs_put_page(page, 1); | 1669 | f2fs_put_page(page, 1); |
1672 | 1670 | ||
1673 | /* 2) shrink nat caches if necessary */ | 1671 | /* 2) shrink nat caches if necessary */ |
1674 | try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD); | 1672 | try_to_free_nats(sbi, nm_i->nat_cnt - NM_WOUT_THRESHOLD); |
1675 | } | 1673 | } |
1676 | 1674 | ||
1677 | static int init_node_manager(struct f2fs_sb_info *sbi) | 1675 | static int init_node_manager(struct f2fs_sb_info *sbi) |
1678 | { | 1676 | { |
1679 | struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); | 1677 | struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); |
1680 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1678 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1681 | unsigned char *version_bitmap; | 1679 | unsigned char *version_bitmap; |
1682 | unsigned int nat_segs, nat_blocks; | 1680 | unsigned int nat_segs, nat_blocks; |
1683 | 1681 | ||
1684 | nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); | 1682 | nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); |
1685 | 1683 | ||
1686 | /* segment_count_nat includes pair segment so divide to 2. */ | 1684 | /* segment_count_nat includes pair segment so divide to 2. */ |
1687 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; | 1685 | nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; |
1688 | nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); | 1686 | nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); |
1689 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; | 1687 | nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; |
1690 | nm_i->fcnt = 0; | 1688 | nm_i->fcnt = 0; |
1691 | nm_i->nat_cnt = 0; | 1689 | nm_i->nat_cnt = 0; |
1692 | 1690 | ||
1693 | INIT_LIST_HEAD(&nm_i->free_nid_list); | 1691 | INIT_LIST_HEAD(&nm_i->free_nid_list); |
1694 | INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC); | 1692 | INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC); |
1695 | INIT_LIST_HEAD(&nm_i->nat_entries); | 1693 | INIT_LIST_HEAD(&nm_i->nat_entries); |
1696 | INIT_LIST_HEAD(&nm_i->dirty_nat_entries); | 1694 | INIT_LIST_HEAD(&nm_i->dirty_nat_entries); |
1697 | 1695 | ||
1698 | mutex_init(&nm_i->build_lock); | 1696 | mutex_init(&nm_i->build_lock); |
1699 | spin_lock_init(&nm_i->free_nid_list_lock); | 1697 | spin_lock_init(&nm_i->free_nid_list_lock); |
1700 | rwlock_init(&nm_i->nat_tree_lock); | 1698 | rwlock_init(&nm_i->nat_tree_lock); |
1701 | 1699 | ||
1702 | nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); | 1700 | nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); |
1703 | nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); | 1701 | nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); |
1704 | version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); | 1702 | version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); |
1705 | if (!version_bitmap) | 1703 | if (!version_bitmap) |
1706 | return -EFAULT; | 1704 | return -EFAULT; |
1707 | 1705 | ||
1708 | nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, | 1706 | nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, |
1709 | GFP_KERNEL); | 1707 | GFP_KERNEL); |
1710 | if (!nm_i->nat_bitmap) | 1708 | if (!nm_i->nat_bitmap) |
1711 | return -ENOMEM; | 1709 | return -ENOMEM; |
1712 | return 0; | 1710 | return 0; |
1713 | } | 1711 | } |
1714 | 1712 | ||
1715 | int build_node_manager(struct f2fs_sb_info *sbi) | 1713 | int build_node_manager(struct f2fs_sb_info *sbi) |
1716 | { | 1714 | { |
1717 | int err; | 1715 | int err; |
1718 | 1716 | ||
1719 | sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL); | 1717 | sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL); |
1720 | if (!sbi->nm_info) | 1718 | if (!sbi->nm_info) |
1721 | return -ENOMEM; | 1719 | return -ENOMEM; |
1722 | 1720 | ||
1723 | err = init_node_manager(sbi); | 1721 | err = init_node_manager(sbi); |
1724 | if (err) | 1722 | if (err) |
1725 | return err; | 1723 | return err; |
1726 | 1724 | ||
1727 | build_free_nids(sbi); | 1725 | build_free_nids(sbi); |
1728 | return 0; | 1726 | return 0; |
1729 | } | 1727 | } |
1730 | 1728 | ||
1731 | void destroy_node_manager(struct f2fs_sb_info *sbi) | 1729 | void destroy_node_manager(struct f2fs_sb_info *sbi) |
1732 | { | 1730 | { |
1733 | struct f2fs_nm_info *nm_i = NM_I(sbi); | 1731 | struct f2fs_nm_info *nm_i = NM_I(sbi); |
1734 | struct free_nid *i, *next_i; | 1732 | struct free_nid *i, *next_i; |
1735 | struct nat_entry *natvec[NATVEC_SIZE]; | 1733 | struct nat_entry *natvec[NATVEC_SIZE]; |
1736 | nid_t nid = 0; | 1734 | nid_t nid = 0; |
1737 | unsigned int found; | 1735 | unsigned int found; |
1738 | 1736 | ||
1739 | if (!nm_i) | 1737 | if (!nm_i) |
1740 | return; | 1738 | return; |
1741 | 1739 | ||
1742 | /* destroy free nid list */ | 1740 | /* destroy free nid list */ |
1743 | spin_lock(&nm_i->free_nid_list_lock); | 1741 | spin_lock(&nm_i->free_nid_list_lock); |
1744 | list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { | 1742 | list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { |
1745 | BUG_ON(i->state == NID_ALLOC); | 1743 | BUG_ON(i->state == NID_ALLOC); |
1746 | __del_from_free_nid_list(i); | 1744 | __del_from_free_nid_list(i); |
1747 | nm_i->fcnt--; | 1745 | nm_i->fcnt--; |
1748 | } | 1746 | } |
1749 | BUG_ON(nm_i->fcnt); | 1747 | BUG_ON(nm_i->fcnt); |
1750 | spin_unlock(&nm_i->free_nid_list_lock); | 1748 | spin_unlock(&nm_i->free_nid_list_lock); |
1751 | 1749 | ||
1752 | /* destroy nat cache */ | 1750 | /* destroy nat cache */ |
1753 | write_lock(&nm_i->nat_tree_lock); | 1751 | write_lock(&nm_i->nat_tree_lock); |
1754 | while ((found = __gang_lookup_nat_cache(nm_i, | 1752 | while ((found = __gang_lookup_nat_cache(nm_i, |
1755 | nid, NATVEC_SIZE, natvec))) { | 1753 | nid, NATVEC_SIZE, natvec))) { |
1756 | unsigned idx; | 1754 | unsigned idx; |
1757 | for (idx = 0; idx < found; idx++) { | 1755 | for (idx = 0; idx < found; idx++) { |
1758 | struct nat_entry *e = natvec[idx]; | 1756 | struct nat_entry *e = natvec[idx]; |
1759 | nid = nat_get_nid(e) + 1; | 1757 | nid = nat_get_nid(e) + 1; |
1760 | __del_from_nat_cache(nm_i, e); | 1758 | __del_from_nat_cache(nm_i, e); |
1761 | } | 1759 | } |
1762 | } | 1760 | } |
1763 | BUG_ON(nm_i->nat_cnt); | 1761 | BUG_ON(nm_i->nat_cnt); |
1764 | write_unlock(&nm_i->nat_tree_lock); | 1762 | write_unlock(&nm_i->nat_tree_lock); |
1765 | 1763 | ||
1766 | kfree(nm_i->nat_bitmap); | 1764 | kfree(nm_i->nat_bitmap); |
1767 | sbi->nm_info = NULL; | 1765 | sbi->nm_info = NULL; |
1768 | kfree(nm_i); | 1766 | kfree(nm_i); |
1769 | } | 1767 | } |
1770 | 1768 | ||
1771 | int __init create_node_manager_caches(void) | 1769 | int __init create_node_manager_caches(void) |
1772 | { | 1770 | { |
1773 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", | 1771 | nat_entry_slab = f2fs_kmem_cache_create("nat_entry", |
1774 | sizeof(struct nat_entry), NULL); | 1772 | sizeof(struct nat_entry), NULL); |
1775 | if (!nat_entry_slab) | 1773 | if (!nat_entry_slab) |
1776 | return -ENOMEM; | 1774 | return -ENOMEM; |
1777 | 1775 | ||
1778 | free_nid_slab = f2fs_kmem_cache_create("free_nid", | 1776 | free_nid_slab = f2fs_kmem_cache_create("free_nid", |
1779 | sizeof(struct free_nid), NULL); | 1777 | sizeof(struct free_nid), NULL); |
1780 | if (!free_nid_slab) { | 1778 | if (!free_nid_slab) { |
1781 | kmem_cache_destroy(nat_entry_slab); | 1779 | kmem_cache_destroy(nat_entry_slab); |
1782 | return -ENOMEM; | 1780 | return -ENOMEM; |
1783 | } | 1781 | } |
1784 | return 0; | 1782 | return 0; |
1785 | } | 1783 | } |
1786 | 1784 | ||
1787 | void destroy_node_manager_caches(void) | 1785 | void destroy_node_manager_caches(void) |
1788 | { | 1786 | { |
1789 | kmem_cache_destroy(free_nid_slab); | 1787 | kmem_cache_destroy(free_nid_slab); |
1790 | kmem_cache_destroy(nat_entry_slab); | 1788 | kmem_cache_destroy(nat_entry_slab); |
1791 | } | 1789 | } |
1792 | 1790 |
fs/f2fs/segment.c
1 | /* | 1 | /* |
2 | * fs/f2fs/segment.c | 2 | * fs/f2fs/segment.c |
3 | * | 3 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 5 | * http://www.samsung.com/ |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/f2fs_fs.h> | 12 | #include <linux/f2fs_fs.h> |
13 | #include <linux/bio.h> | 13 | #include <linux/bio.h> |
14 | #include <linux/blkdev.h> | 14 | #include <linux/blkdev.h> |
15 | #include <linux/prefetch.h> | 15 | #include <linux/prefetch.h> |
16 | #include <linux/vmalloc.h> | 16 | #include <linux/vmalloc.h> |
17 | 17 | ||
18 | #include "f2fs.h" | 18 | #include "f2fs.h" |
19 | #include "segment.h" | 19 | #include "segment.h" |
20 | #include "node.h" | 20 | #include "node.h" |
21 | #include <trace/events/f2fs.h> | 21 | #include <trace/events/f2fs.h> |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * This function balances dirty node and dentry pages. | 24 | * This function balances dirty node and dentry pages. |
25 | * In addition, it controls garbage collection. | 25 | * In addition, it controls garbage collection. |
26 | */ | 26 | */ |
27 | void f2fs_balance_fs(struct f2fs_sb_info *sbi) | 27 | void f2fs_balance_fs(struct f2fs_sb_info *sbi) |
28 | { | 28 | { |
29 | /* | 29 | /* |
30 | * We should do GC or end up with checkpoint, if there are so many dirty | 30 | * We should do GC or end up with checkpoint, if there are so many dirty |
31 | * dir/node pages without enough free segments. | 31 | * dir/node pages without enough free segments. |
32 | */ | 32 | */ |
33 | if (has_not_enough_free_secs(sbi, 0)) { | 33 | if (has_not_enough_free_secs(sbi, 0)) { |
34 | mutex_lock(&sbi->gc_mutex); | 34 | mutex_lock(&sbi->gc_mutex); |
35 | f2fs_gc(sbi); | 35 | f2fs_gc(sbi); |
36 | } | 36 | } |
37 | } | 37 | } |
38 | 38 | ||
39 | static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | 39 | static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, |
40 | enum dirty_type dirty_type) | 40 | enum dirty_type dirty_type) |
41 | { | 41 | { |
42 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 42 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
43 | 43 | ||
44 | /* need not be added */ | 44 | /* need not be added */ |
45 | if (IS_CURSEG(sbi, segno)) | 45 | if (IS_CURSEG(sbi, segno)) |
46 | return; | 46 | return; |
47 | 47 | ||
48 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) | 48 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) |
49 | dirty_i->nr_dirty[dirty_type]++; | 49 | dirty_i->nr_dirty[dirty_type]++; |
50 | 50 | ||
51 | if (dirty_type == DIRTY) { | 51 | if (dirty_type == DIRTY) { |
52 | struct seg_entry *sentry = get_seg_entry(sbi, segno); | 52 | struct seg_entry *sentry = get_seg_entry(sbi, segno); |
53 | enum dirty_type t = DIRTY_HOT_DATA; | 53 | enum dirty_type t = DIRTY_HOT_DATA; |
54 | 54 | ||
55 | dirty_type = sentry->type; | 55 | dirty_type = sentry->type; |
56 | 56 | ||
57 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) | 57 | if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) |
58 | dirty_i->nr_dirty[dirty_type]++; | 58 | dirty_i->nr_dirty[dirty_type]++; |
59 | 59 | ||
60 | /* Only one bitmap should be set */ | 60 | /* Only one bitmap should be set */ |
61 | for (; t <= DIRTY_COLD_NODE; t++) { | 61 | for (; t <= DIRTY_COLD_NODE; t++) { |
62 | if (t == dirty_type) | 62 | if (t == dirty_type) |
63 | continue; | 63 | continue; |
64 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) | 64 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) |
65 | dirty_i->nr_dirty[t]--; | 65 | dirty_i->nr_dirty[t]--; |
66 | } | 66 | } |
67 | } | 67 | } |
68 | } | 68 | } |
69 | 69 | ||
70 | static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, | 70 | static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, |
71 | enum dirty_type dirty_type) | 71 | enum dirty_type dirty_type) |
72 | { | 72 | { |
73 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 73 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
74 | 74 | ||
75 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) | 75 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) |
76 | dirty_i->nr_dirty[dirty_type]--; | 76 | dirty_i->nr_dirty[dirty_type]--; |
77 | 77 | ||
78 | if (dirty_type == DIRTY) { | 78 | if (dirty_type == DIRTY) { |
79 | enum dirty_type t = DIRTY_HOT_DATA; | 79 | enum dirty_type t = DIRTY_HOT_DATA; |
80 | 80 | ||
81 | /* clear all the bitmaps */ | 81 | /* clear all the bitmaps */ |
82 | for (; t <= DIRTY_COLD_NODE; t++) | 82 | for (; t <= DIRTY_COLD_NODE; t++) |
83 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) | 83 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) |
84 | dirty_i->nr_dirty[t]--; | 84 | dirty_i->nr_dirty[t]--; |
85 | 85 | ||
86 | if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) | 86 | if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) |
87 | clear_bit(GET_SECNO(sbi, segno), | 87 | clear_bit(GET_SECNO(sbi, segno), |
88 | dirty_i->victim_secmap); | 88 | dirty_i->victim_secmap); |
89 | } | 89 | } |
90 | } | 90 | } |
91 | 91 | ||
92 | /* | 92 | /* |
93 | * Should not occur error such as -ENOMEM. | 93 | * Should not occur error such as -ENOMEM. |
94 | * Adding dirty entry into seglist is not critical operation. | 94 | * Adding dirty entry into seglist is not critical operation. |
95 | * If a given segment is one of current working segments, it won't be added. | 95 | * If a given segment is one of current working segments, it won't be added. |
96 | */ | 96 | */ |
97 | void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) | 97 | void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) |
98 | { | 98 | { |
99 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 99 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
100 | unsigned short valid_blocks; | 100 | unsigned short valid_blocks; |
101 | 101 | ||
102 | if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno)) | 102 | if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno)) |
103 | return; | 103 | return; |
104 | 104 | ||
105 | mutex_lock(&dirty_i->seglist_lock); | 105 | mutex_lock(&dirty_i->seglist_lock); |
106 | 106 | ||
107 | valid_blocks = get_valid_blocks(sbi, segno, 0); | 107 | valid_blocks = get_valid_blocks(sbi, segno, 0); |
108 | 108 | ||
109 | if (valid_blocks == 0) { | 109 | if (valid_blocks == 0) { |
110 | __locate_dirty_segment(sbi, segno, PRE); | 110 | __locate_dirty_segment(sbi, segno, PRE); |
111 | __remove_dirty_segment(sbi, segno, DIRTY); | 111 | __remove_dirty_segment(sbi, segno, DIRTY); |
112 | } else if (valid_blocks < sbi->blocks_per_seg) { | 112 | } else if (valid_blocks < sbi->blocks_per_seg) { |
113 | __locate_dirty_segment(sbi, segno, DIRTY); | 113 | __locate_dirty_segment(sbi, segno, DIRTY); |
114 | } else { | 114 | } else { |
115 | /* Recovery routine with SSR needs this */ | 115 | /* Recovery routine with SSR needs this */ |
116 | __remove_dirty_segment(sbi, segno, DIRTY); | 116 | __remove_dirty_segment(sbi, segno, DIRTY); |
117 | } | 117 | } |
118 | 118 | ||
119 | mutex_unlock(&dirty_i->seglist_lock); | 119 | mutex_unlock(&dirty_i->seglist_lock); |
120 | return; | 120 | return; |
121 | } | 121 | } |
122 | 122 | ||
123 | /* | 123 | /* |
124 | * Should call clear_prefree_segments after checkpoint is done. | 124 | * Should call clear_prefree_segments after checkpoint is done. |
125 | */ | 125 | */ |
126 | static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) | 126 | static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) |
127 | { | 127 | { |
128 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 128 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
129 | unsigned int segno, offset = 0; | 129 | unsigned int segno, offset = 0; |
130 | unsigned int total_segs = TOTAL_SEGS(sbi); | 130 | unsigned int total_segs = TOTAL_SEGS(sbi); |
131 | 131 | ||
132 | mutex_lock(&dirty_i->seglist_lock); | 132 | mutex_lock(&dirty_i->seglist_lock); |
133 | while (1) { | 133 | while (1) { |
134 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, | 134 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, |
135 | offset); | 135 | offset); |
136 | if (segno >= total_segs) | 136 | if (segno >= total_segs) |
137 | break; | 137 | break; |
138 | __set_test_and_free(sbi, segno); | 138 | __set_test_and_free(sbi, segno); |
139 | offset = segno + 1; | 139 | offset = segno + 1; |
140 | } | 140 | } |
141 | mutex_unlock(&dirty_i->seglist_lock); | 141 | mutex_unlock(&dirty_i->seglist_lock); |
142 | } | 142 | } |
143 | 143 | ||
144 | void clear_prefree_segments(struct f2fs_sb_info *sbi) | 144 | void clear_prefree_segments(struct f2fs_sb_info *sbi) |
145 | { | 145 | { |
146 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 146 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
147 | unsigned int segno, offset = 0; | 147 | unsigned int segno, offset = 0; |
148 | unsigned int total_segs = TOTAL_SEGS(sbi); | 148 | unsigned int total_segs = TOTAL_SEGS(sbi); |
149 | 149 | ||
150 | mutex_lock(&dirty_i->seglist_lock); | 150 | mutex_lock(&dirty_i->seglist_lock); |
151 | while (1) { | 151 | while (1) { |
152 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, | 152 | segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, |
153 | offset); | 153 | offset); |
154 | if (segno >= total_segs) | 154 | if (segno >= total_segs) |
155 | break; | 155 | break; |
156 | 156 | ||
157 | offset = segno + 1; | 157 | offset = segno + 1; |
158 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) | 158 | if (test_and_clear_bit(segno, dirty_i->dirty_segmap[PRE])) |
159 | dirty_i->nr_dirty[PRE]--; | 159 | dirty_i->nr_dirty[PRE]--; |
160 | 160 | ||
161 | /* Let's use trim */ | 161 | /* Let's use trim */ |
162 | if (test_opt(sbi, DISCARD)) | 162 | if (test_opt(sbi, DISCARD)) |
163 | blkdev_issue_discard(sbi->sb->s_bdev, | 163 | blkdev_issue_discard(sbi->sb->s_bdev, |
164 | START_BLOCK(sbi, segno) << | 164 | START_BLOCK(sbi, segno) << |
165 | sbi->log_sectors_per_block, | 165 | sbi->log_sectors_per_block, |
166 | 1 << (sbi->log_sectors_per_block + | 166 | 1 << (sbi->log_sectors_per_block + |
167 | sbi->log_blocks_per_seg), | 167 | sbi->log_blocks_per_seg), |
168 | GFP_NOFS, 0); | 168 | GFP_NOFS, 0); |
169 | } | 169 | } |
170 | mutex_unlock(&dirty_i->seglist_lock); | 170 | mutex_unlock(&dirty_i->seglist_lock); |
171 | } | 171 | } |
172 | 172 | ||
173 | static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) | 173 | static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) |
174 | { | 174 | { |
175 | struct sit_info *sit_i = SIT_I(sbi); | 175 | struct sit_info *sit_i = SIT_I(sbi); |
176 | if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap)) | 176 | if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap)) |
177 | sit_i->dirty_sentries++; | 177 | sit_i->dirty_sentries++; |
178 | } | 178 | } |
179 | 179 | ||
180 | static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type, | 180 | static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type, |
181 | unsigned int segno, int modified) | 181 | unsigned int segno, int modified) |
182 | { | 182 | { |
183 | struct seg_entry *se = get_seg_entry(sbi, segno); | 183 | struct seg_entry *se = get_seg_entry(sbi, segno); |
184 | se->type = type; | 184 | se->type = type; |
185 | if (modified) | 185 | if (modified) |
186 | __mark_sit_entry_dirty(sbi, segno); | 186 | __mark_sit_entry_dirty(sbi, segno); |
187 | } | 187 | } |
188 | 188 | ||
189 | static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) | 189 | static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) |
190 | { | 190 | { |
191 | struct seg_entry *se; | 191 | struct seg_entry *se; |
192 | unsigned int segno, offset; | 192 | unsigned int segno, offset; |
193 | long int new_vblocks; | 193 | long int new_vblocks; |
194 | 194 | ||
195 | segno = GET_SEGNO(sbi, blkaddr); | 195 | segno = GET_SEGNO(sbi, blkaddr); |
196 | 196 | ||
197 | se = get_seg_entry(sbi, segno); | 197 | se = get_seg_entry(sbi, segno); |
198 | new_vblocks = se->valid_blocks + del; | 198 | new_vblocks = se->valid_blocks + del; |
199 | offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1); | 199 | offset = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) & (sbi->blocks_per_seg - 1); |
200 | 200 | ||
201 | BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) || | 201 | BUG_ON((new_vblocks >> (sizeof(unsigned short) << 3) || |
202 | (new_vblocks > sbi->blocks_per_seg))); | 202 | (new_vblocks > sbi->blocks_per_seg))); |
203 | 203 | ||
204 | se->valid_blocks = new_vblocks; | 204 | se->valid_blocks = new_vblocks; |
205 | se->mtime = get_mtime(sbi); | 205 | se->mtime = get_mtime(sbi); |
206 | SIT_I(sbi)->max_mtime = se->mtime; | 206 | SIT_I(sbi)->max_mtime = se->mtime; |
207 | 207 | ||
208 | /* Update valid block bitmap */ | 208 | /* Update valid block bitmap */ |
209 | if (del > 0) { | 209 | if (del > 0) { |
210 | if (f2fs_set_bit(offset, se->cur_valid_map)) | 210 | if (f2fs_set_bit(offset, se->cur_valid_map)) |
211 | BUG(); | 211 | BUG(); |
212 | } else { | 212 | } else { |
213 | if (!f2fs_clear_bit(offset, se->cur_valid_map)) | 213 | if (!f2fs_clear_bit(offset, se->cur_valid_map)) |
214 | BUG(); | 214 | BUG(); |
215 | } | 215 | } |
216 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) | 216 | if (!f2fs_test_bit(offset, se->ckpt_valid_map)) |
217 | se->ckpt_valid_blocks += del; | 217 | se->ckpt_valid_blocks += del; |
218 | 218 | ||
219 | __mark_sit_entry_dirty(sbi, segno); | 219 | __mark_sit_entry_dirty(sbi, segno); |
220 | 220 | ||
221 | /* update total number of valid blocks to be written in ckpt area */ | 221 | /* update total number of valid blocks to be written in ckpt area */ |
222 | SIT_I(sbi)->written_valid_blocks += del; | 222 | SIT_I(sbi)->written_valid_blocks += del; |
223 | 223 | ||
224 | if (sbi->segs_per_sec > 1) | 224 | if (sbi->segs_per_sec > 1) |
225 | get_sec_entry(sbi, segno)->valid_blocks += del; | 225 | get_sec_entry(sbi, segno)->valid_blocks += del; |
226 | } | 226 | } |
227 | 227 | ||
228 | static void refresh_sit_entry(struct f2fs_sb_info *sbi, | 228 | static void refresh_sit_entry(struct f2fs_sb_info *sbi, |
229 | block_t old_blkaddr, block_t new_blkaddr) | 229 | block_t old_blkaddr, block_t new_blkaddr) |
230 | { | 230 | { |
231 | update_sit_entry(sbi, new_blkaddr, 1); | 231 | update_sit_entry(sbi, new_blkaddr, 1); |
232 | if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) | 232 | if (GET_SEGNO(sbi, old_blkaddr) != NULL_SEGNO) |
233 | update_sit_entry(sbi, old_blkaddr, -1); | 233 | update_sit_entry(sbi, old_blkaddr, -1); |
234 | } | 234 | } |
235 | 235 | ||
236 | void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) | 236 | void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) |
237 | { | 237 | { |
238 | unsigned int segno = GET_SEGNO(sbi, addr); | 238 | unsigned int segno = GET_SEGNO(sbi, addr); |
239 | struct sit_info *sit_i = SIT_I(sbi); | 239 | struct sit_info *sit_i = SIT_I(sbi); |
240 | 240 | ||
241 | BUG_ON(addr == NULL_ADDR); | 241 | BUG_ON(addr == NULL_ADDR); |
242 | if (addr == NEW_ADDR) | 242 | if (addr == NEW_ADDR) |
243 | return; | 243 | return; |
244 | 244 | ||
245 | /* add it into sit main buffer */ | 245 | /* add it into sit main buffer */ |
246 | mutex_lock(&sit_i->sentry_lock); | 246 | mutex_lock(&sit_i->sentry_lock); |
247 | 247 | ||
248 | update_sit_entry(sbi, addr, -1); | 248 | update_sit_entry(sbi, addr, -1); |
249 | 249 | ||
250 | /* add it into dirty seglist */ | 250 | /* add it into dirty seglist */ |
251 | locate_dirty_segment(sbi, segno); | 251 | locate_dirty_segment(sbi, segno); |
252 | 252 | ||
253 | mutex_unlock(&sit_i->sentry_lock); | 253 | mutex_unlock(&sit_i->sentry_lock); |
254 | } | 254 | } |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * This function should be resided under the curseg_mutex lock | 257 | * This function should be resided under the curseg_mutex lock |
258 | */ | 258 | */ |
259 | static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, | 259 | static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, |
260 | struct f2fs_summary *sum, unsigned short offset) | 260 | struct f2fs_summary *sum, unsigned short offset) |
261 | { | 261 | { |
262 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 262 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
263 | void *addr = curseg->sum_blk; | 263 | void *addr = curseg->sum_blk; |
264 | addr += offset * sizeof(struct f2fs_summary); | 264 | addr += offset * sizeof(struct f2fs_summary); |
265 | memcpy(addr, sum, sizeof(struct f2fs_summary)); | 265 | memcpy(addr, sum, sizeof(struct f2fs_summary)); |
266 | return; | 266 | return; |
267 | } | 267 | } |
268 | 268 | ||
269 | /* | 269 | /* |
270 | * Calculate the number of current summary pages for writing | 270 | * Calculate the number of current summary pages for writing |
271 | */ | 271 | */ |
272 | int npages_for_summary_flush(struct f2fs_sb_info *sbi) | 272 | int npages_for_summary_flush(struct f2fs_sb_info *sbi) |
273 | { | 273 | { |
274 | int total_size_bytes = 0; | 274 | int total_size_bytes = 0; |
275 | int valid_sum_count = 0; | 275 | int valid_sum_count = 0; |
276 | int i, sum_space; | 276 | int i, sum_space; |
277 | 277 | ||
278 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 278 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
279 | if (sbi->ckpt->alloc_type[i] == SSR) | 279 | if (sbi->ckpt->alloc_type[i] == SSR) |
280 | valid_sum_count += sbi->blocks_per_seg; | 280 | valid_sum_count += sbi->blocks_per_seg; |
281 | else | 281 | else |
282 | valid_sum_count += curseg_blkoff(sbi, i); | 282 | valid_sum_count += curseg_blkoff(sbi, i); |
283 | } | 283 | } |
284 | 284 | ||
285 | total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1) | 285 | total_size_bytes = valid_sum_count * (SUMMARY_SIZE + 1) |
286 | + sizeof(struct nat_journal) + 2 | 286 | + sizeof(struct nat_journal) + 2 |
287 | + sizeof(struct sit_journal) + 2; | 287 | + sizeof(struct sit_journal) + 2; |
288 | sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE; | 288 | sum_space = PAGE_CACHE_SIZE - SUM_FOOTER_SIZE; |
289 | if (total_size_bytes < sum_space) | 289 | if (total_size_bytes < sum_space) |
290 | return 1; | 290 | return 1; |
291 | else if (total_size_bytes < 2 * sum_space) | 291 | else if (total_size_bytes < 2 * sum_space) |
292 | return 2; | 292 | return 2; |
293 | return 3; | 293 | return 3; |
294 | } | 294 | } |
295 | 295 | ||
296 | /* | 296 | /* |
297 | * Caller should put this summary page | 297 | * Caller should put this summary page |
298 | */ | 298 | */ |
299 | struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) | 299 | struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) |
300 | { | 300 | { |
301 | return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno)); | 301 | return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno)); |
302 | } | 302 | } |
303 | 303 | ||
304 | static void write_sum_page(struct f2fs_sb_info *sbi, | 304 | static void write_sum_page(struct f2fs_sb_info *sbi, |
305 | struct f2fs_summary_block *sum_blk, block_t blk_addr) | 305 | struct f2fs_summary_block *sum_blk, block_t blk_addr) |
306 | { | 306 | { |
307 | struct page *page = grab_meta_page(sbi, blk_addr); | 307 | struct page *page = grab_meta_page(sbi, blk_addr); |
308 | void *kaddr = page_address(page); | 308 | void *kaddr = page_address(page); |
309 | memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE); | 309 | memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE); |
310 | set_page_dirty(page); | 310 | set_page_dirty(page); |
311 | f2fs_put_page(page, 1); | 311 | f2fs_put_page(page, 1); |
312 | } | 312 | } |
313 | 313 | ||
314 | static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi, int type) | 314 | static unsigned int check_prefree_segments(struct f2fs_sb_info *sbi, int type) |
315 | { | 315 | { |
316 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 316 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
317 | unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE]; | 317 | unsigned long *prefree_segmap = dirty_i->dirty_segmap[PRE]; |
318 | unsigned int segno; | 318 | unsigned int segno; |
319 | unsigned int ofs = 0; | 319 | unsigned int ofs = 0; |
320 | 320 | ||
321 | /* | 321 | /* |
322 | * If there is not enough reserved sections, | 322 | * If there is not enough reserved sections, |
323 | * we should not reuse prefree segments. | 323 | * we should not reuse prefree segments. |
324 | */ | 324 | */ |
325 | if (has_not_enough_free_secs(sbi, 0)) | 325 | if (has_not_enough_free_secs(sbi, 0)) |
326 | return NULL_SEGNO; | 326 | return NULL_SEGNO; |
327 | 327 | ||
328 | /* | 328 | /* |
329 | * NODE page should not reuse prefree segment, | 329 | * NODE page should not reuse prefree segment, |
330 | * since those information is used for SPOR. | 330 | * since those information is used for SPOR. |
331 | */ | 331 | */ |
332 | if (IS_NODESEG(type)) | 332 | if (IS_NODESEG(type)) |
333 | return NULL_SEGNO; | 333 | return NULL_SEGNO; |
334 | next: | 334 | next: |
335 | segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs); | 335 | segno = find_next_bit(prefree_segmap, TOTAL_SEGS(sbi), ofs); |
336 | ofs += sbi->segs_per_sec; | 336 | ofs += sbi->segs_per_sec; |
337 | 337 | ||
338 | if (segno < TOTAL_SEGS(sbi)) { | 338 | if (segno < TOTAL_SEGS(sbi)) { |
339 | int i; | 339 | int i; |
340 | 340 | ||
341 | /* skip intermediate segments in a section */ | 341 | /* skip intermediate segments in a section */ |
342 | if (segno % sbi->segs_per_sec) | 342 | if (segno % sbi->segs_per_sec) |
343 | goto next; | 343 | goto next; |
344 | 344 | ||
345 | /* skip if the section is currently used */ | 345 | /* skip if the section is currently used */ |
346 | if (sec_usage_check(sbi, GET_SECNO(sbi, segno))) | 346 | if (sec_usage_check(sbi, GET_SECNO(sbi, segno))) |
347 | goto next; | 347 | goto next; |
348 | 348 | ||
349 | /* skip if whole section is not prefree */ | 349 | /* skip if whole section is not prefree */ |
350 | for (i = 1; i < sbi->segs_per_sec; i++) | 350 | for (i = 1; i < sbi->segs_per_sec; i++) |
351 | if (!test_bit(segno + i, prefree_segmap)) | 351 | if (!test_bit(segno + i, prefree_segmap)) |
352 | goto next; | 352 | goto next; |
353 | 353 | ||
354 | /* skip if whole section was not free at the last checkpoint */ | 354 | /* skip if whole section was not free at the last checkpoint */ |
355 | for (i = 0; i < sbi->segs_per_sec; i++) | 355 | for (i = 0; i < sbi->segs_per_sec; i++) |
356 | if (get_seg_entry(sbi, segno + i)->ckpt_valid_blocks) | 356 | if (get_seg_entry(sbi, segno + i)->ckpt_valid_blocks) |
357 | goto next; | 357 | goto next; |
358 | 358 | ||
359 | return segno; | 359 | return segno; |
360 | } | 360 | } |
361 | return NULL_SEGNO; | 361 | return NULL_SEGNO; |
362 | } | 362 | } |
363 | 363 | ||
364 | static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) | 364 | static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) |
365 | { | 365 | { |
366 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 366 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
367 | unsigned int segno = curseg->segno; | 367 | unsigned int segno = curseg->segno; |
368 | struct free_segmap_info *free_i = FREE_I(sbi); | 368 | struct free_segmap_info *free_i = FREE_I(sbi); |
369 | 369 | ||
370 | if (segno + 1 < TOTAL_SEGS(sbi) && (segno + 1) % sbi->segs_per_sec) | 370 | if (segno + 1 < TOTAL_SEGS(sbi) && (segno + 1) % sbi->segs_per_sec) |
371 | return !test_bit(segno + 1, free_i->free_segmap); | 371 | return !test_bit(segno + 1, free_i->free_segmap); |
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
374 | 374 | ||
375 | /* | 375 | /* |
376 | * Find a new segment from the free segments bitmap to right order | 376 | * Find a new segment from the free segments bitmap to right order |
377 | * This function should be returned with success, otherwise BUG | 377 | * This function should be returned with success, otherwise BUG |
378 | */ | 378 | */ |
379 | static void get_new_segment(struct f2fs_sb_info *sbi, | 379 | static void get_new_segment(struct f2fs_sb_info *sbi, |
380 | unsigned int *newseg, bool new_sec, int dir) | 380 | unsigned int *newseg, bool new_sec, int dir) |
381 | { | 381 | { |
382 | struct free_segmap_info *free_i = FREE_I(sbi); | 382 | struct free_segmap_info *free_i = FREE_I(sbi); |
383 | unsigned int segno, secno, zoneno; | 383 | unsigned int segno, secno, zoneno; |
384 | unsigned int total_zones = TOTAL_SECS(sbi) / sbi->secs_per_zone; | 384 | unsigned int total_zones = TOTAL_SECS(sbi) / sbi->secs_per_zone; |
385 | unsigned int hint = *newseg / sbi->segs_per_sec; | 385 | unsigned int hint = *newseg / sbi->segs_per_sec; |
386 | unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg); | 386 | unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg); |
387 | unsigned int left_start = hint; | 387 | unsigned int left_start = hint; |
388 | bool init = true; | 388 | bool init = true; |
389 | int go_left = 0; | 389 | int go_left = 0; |
390 | int i; | 390 | int i; |
391 | 391 | ||
392 | write_lock(&free_i->segmap_lock); | 392 | write_lock(&free_i->segmap_lock); |
393 | 393 | ||
394 | if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) { | 394 | if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) { |
395 | segno = find_next_zero_bit(free_i->free_segmap, | 395 | segno = find_next_zero_bit(free_i->free_segmap, |
396 | TOTAL_SEGS(sbi), *newseg + 1); | 396 | TOTAL_SEGS(sbi), *newseg + 1); |
397 | if (segno - *newseg < sbi->segs_per_sec - | 397 | if (segno - *newseg < sbi->segs_per_sec - |
398 | (*newseg % sbi->segs_per_sec)) | 398 | (*newseg % sbi->segs_per_sec)) |
399 | goto got_it; | 399 | goto got_it; |
400 | } | 400 | } |
401 | find_other_zone: | 401 | find_other_zone: |
402 | secno = find_next_zero_bit(free_i->free_secmap, TOTAL_SECS(sbi), hint); | 402 | secno = find_next_zero_bit(free_i->free_secmap, TOTAL_SECS(sbi), hint); |
403 | if (secno >= TOTAL_SECS(sbi)) { | 403 | if (secno >= TOTAL_SECS(sbi)) { |
404 | if (dir == ALLOC_RIGHT) { | 404 | if (dir == ALLOC_RIGHT) { |
405 | secno = find_next_zero_bit(free_i->free_secmap, | 405 | secno = find_next_zero_bit(free_i->free_secmap, |
406 | TOTAL_SECS(sbi), 0); | 406 | TOTAL_SECS(sbi), 0); |
407 | BUG_ON(secno >= TOTAL_SECS(sbi)); | 407 | BUG_ON(secno >= TOTAL_SECS(sbi)); |
408 | } else { | 408 | } else { |
409 | go_left = 1; | 409 | go_left = 1; |
410 | left_start = hint - 1; | 410 | left_start = hint - 1; |
411 | } | 411 | } |
412 | } | 412 | } |
413 | if (go_left == 0) | 413 | if (go_left == 0) |
414 | goto skip_left; | 414 | goto skip_left; |
415 | 415 | ||
416 | while (test_bit(left_start, free_i->free_secmap)) { | 416 | while (test_bit(left_start, free_i->free_secmap)) { |
417 | if (left_start > 0) { | 417 | if (left_start > 0) { |
418 | left_start--; | 418 | left_start--; |
419 | continue; | 419 | continue; |
420 | } | 420 | } |
421 | left_start = find_next_zero_bit(free_i->free_secmap, | 421 | left_start = find_next_zero_bit(free_i->free_secmap, |
422 | TOTAL_SECS(sbi), 0); | 422 | TOTAL_SECS(sbi), 0); |
423 | BUG_ON(left_start >= TOTAL_SECS(sbi)); | 423 | BUG_ON(left_start >= TOTAL_SECS(sbi)); |
424 | break; | 424 | break; |
425 | } | 425 | } |
426 | secno = left_start; | 426 | secno = left_start; |
427 | skip_left: | 427 | skip_left: |
428 | hint = secno; | 428 | hint = secno; |
429 | segno = secno * sbi->segs_per_sec; | 429 | segno = secno * sbi->segs_per_sec; |
430 | zoneno = secno / sbi->secs_per_zone; | 430 | zoneno = secno / sbi->secs_per_zone; |
431 | 431 | ||
432 | /* give up on finding another zone */ | 432 | /* give up on finding another zone */ |
433 | if (!init) | 433 | if (!init) |
434 | goto got_it; | 434 | goto got_it; |
435 | if (sbi->secs_per_zone == 1) | 435 | if (sbi->secs_per_zone == 1) |
436 | goto got_it; | 436 | goto got_it; |
437 | if (zoneno == old_zoneno) | 437 | if (zoneno == old_zoneno) |
438 | goto got_it; | 438 | goto got_it; |
439 | if (dir == ALLOC_LEFT) { | 439 | if (dir == ALLOC_LEFT) { |
440 | if (!go_left && zoneno + 1 >= total_zones) | 440 | if (!go_left && zoneno + 1 >= total_zones) |
441 | goto got_it; | 441 | goto got_it; |
442 | if (go_left && zoneno == 0) | 442 | if (go_left && zoneno == 0) |
443 | goto got_it; | 443 | goto got_it; |
444 | } | 444 | } |
445 | for (i = 0; i < NR_CURSEG_TYPE; i++) | 445 | for (i = 0; i < NR_CURSEG_TYPE; i++) |
446 | if (CURSEG_I(sbi, i)->zone == zoneno) | 446 | if (CURSEG_I(sbi, i)->zone == zoneno) |
447 | break; | 447 | break; |
448 | 448 | ||
449 | if (i < NR_CURSEG_TYPE) { | 449 | if (i < NR_CURSEG_TYPE) { |
450 | /* zone is in user, try another */ | 450 | /* zone is in user, try another */ |
451 | if (go_left) | 451 | if (go_left) |
452 | hint = zoneno * sbi->secs_per_zone - 1; | 452 | hint = zoneno * sbi->secs_per_zone - 1; |
453 | else if (zoneno + 1 >= total_zones) | 453 | else if (zoneno + 1 >= total_zones) |
454 | hint = 0; | 454 | hint = 0; |
455 | else | 455 | else |
456 | hint = (zoneno + 1) * sbi->secs_per_zone; | 456 | hint = (zoneno + 1) * sbi->secs_per_zone; |
457 | init = false; | 457 | init = false; |
458 | goto find_other_zone; | 458 | goto find_other_zone; |
459 | } | 459 | } |
460 | got_it: | 460 | got_it: |
461 | /* set it as dirty segment in free segmap */ | 461 | /* set it as dirty segment in free segmap */ |
462 | BUG_ON(test_bit(segno, free_i->free_segmap)); | 462 | BUG_ON(test_bit(segno, free_i->free_segmap)); |
463 | __set_inuse(sbi, segno); | 463 | __set_inuse(sbi, segno); |
464 | *newseg = segno; | 464 | *newseg = segno; |
465 | write_unlock(&free_i->segmap_lock); | 465 | write_unlock(&free_i->segmap_lock); |
466 | } | 466 | } |
467 | 467 | ||
468 | static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) | 468 | static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) |
469 | { | 469 | { |
470 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 470 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
471 | struct summary_footer *sum_footer; | 471 | struct summary_footer *sum_footer; |
472 | 472 | ||
473 | curseg->segno = curseg->next_segno; | 473 | curseg->segno = curseg->next_segno; |
474 | curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); | 474 | curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); |
475 | curseg->next_blkoff = 0; | 475 | curseg->next_blkoff = 0; |
476 | curseg->next_segno = NULL_SEGNO; | 476 | curseg->next_segno = NULL_SEGNO; |
477 | 477 | ||
478 | sum_footer = &(curseg->sum_blk->footer); | 478 | sum_footer = &(curseg->sum_blk->footer); |
479 | memset(sum_footer, 0, sizeof(struct summary_footer)); | 479 | memset(sum_footer, 0, sizeof(struct summary_footer)); |
480 | if (IS_DATASEG(type)) | 480 | if (IS_DATASEG(type)) |
481 | SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); | 481 | SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); |
482 | if (IS_NODESEG(type)) | 482 | if (IS_NODESEG(type)) |
483 | SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); | 483 | SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); |
484 | __set_sit_entry_type(sbi, type, curseg->segno, modified); | 484 | __set_sit_entry_type(sbi, type, curseg->segno, modified); |
485 | } | 485 | } |
486 | 486 | ||
487 | /* | 487 | /* |
488 | * Allocate a current working segment. | 488 | * Allocate a current working segment. |
489 | * This function always allocates a free segment in LFS manner. | 489 | * This function always allocates a free segment in LFS manner. |
490 | */ | 490 | */ |
491 | static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) | 491 | static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) |
492 | { | 492 | { |
493 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 493 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
494 | unsigned int segno = curseg->segno; | 494 | unsigned int segno = curseg->segno; |
495 | int dir = ALLOC_LEFT; | 495 | int dir = ALLOC_LEFT; |
496 | 496 | ||
497 | write_sum_page(sbi, curseg->sum_blk, | 497 | write_sum_page(sbi, curseg->sum_blk, |
498 | GET_SUM_BLOCK(sbi, curseg->segno)); | 498 | GET_SUM_BLOCK(sbi, curseg->segno)); |
499 | if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA) | 499 | if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA) |
500 | dir = ALLOC_RIGHT; | 500 | dir = ALLOC_RIGHT; |
501 | 501 | ||
502 | if (test_opt(sbi, NOHEAP)) | 502 | if (test_opt(sbi, NOHEAP)) |
503 | dir = ALLOC_RIGHT; | 503 | dir = ALLOC_RIGHT; |
504 | 504 | ||
505 | get_new_segment(sbi, &segno, new_sec, dir); | 505 | get_new_segment(sbi, &segno, new_sec, dir); |
506 | curseg->next_segno = segno; | 506 | curseg->next_segno = segno; |
507 | reset_curseg(sbi, type, 1); | 507 | reset_curseg(sbi, type, 1); |
508 | curseg->alloc_type = LFS; | 508 | curseg->alloc_type = LFS; |
509 | } | 509 | } |
510 | 510 | ||
511 | static void __next_free_blkoff(struct f2fs_sb_info *sbi, | 511 | static void __next_free_blkoff(struct f2fs_sb_info *sbi, |
512 | struct curseg_info *seg, block_t start) | 512 | struct curseg_info *seg, block_t start) |
513 | { | 513 | { |
514 | struct seg_entry *se = get_seg_entry(sbi, seg->segno); | 514 | struct seg_entry *se = get_seg_entry(sbi, seg->segno); |
515 | block_t ofs; | 515 | block_t ofs; |
516 | for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) { | 516 | for (ofs = start; ofs < sbi->blocks_per_seg; ofs++) { |
517 | if (!f2fs_test_bit(ofs, se->ckpt_valid_map) | 517 | if (!f2fs_test_bit(ofs, se->ckpt_valid_map) |
518 | && !f2fs_test_bit(ofs, se->cur_valid_map)) | 518 | && !f2fs_test_bit(ofs, se->cur_valid_map)) |
519 | break; | 519 | break; |
520 | } | 520 | } |
521 | seg->next_blkoff = ofs; | 521 | seg->next_blkoff = ofs; |
522 | } | 522 | } |
523 | 523 | ||
524 | /* | 524 | /* |
525 | * If a segment is written by LFS manner, next block offset is just obtained | 525 | * If a segment is written by LFS manner, next block offset is just obtained |
526 | * by increasing the current block offset. However, if a segment is written by | 526 | * by increasing the current block offset. However, if a segment is written by |
527 | * SSR manner, next block offset obtained by calling __next_free_blkoff | 527 | * SSR manner, next block offset obtained by calling __next_free_blkoff |
528 | */ | 528 | */ |
529 | static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, | 529 | static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, |
530 | struct curseg_info *seg) | 530 | struct curseg_info *seg) |
531 | { | 531 | { |
532 | if (seg->alloc_type == SSR) | 532 | if (seg->alloc_type == SSR) |
533 | __next_free_blkoff(sbi, seg, seg->next_blkoff + 1); | 533 | __next_free_blkoff(sbi, seg, seg->next_blkoff + 1); |
534 | else | 534 | else |
535 | seg->next_blkoff++; | 535 | seg->next_blkoff++; |
536 | } | 536 | } |
537 | 537 | ||
538 | /* | 538 | /* |
539 | * This function always allocates a used segment (from dirty seglist) by SSR | 539 | * This function always allocates a used segment (from dirty seglist) by SSR |
540 | * manner, so it should recover the existing segment information of valid blocks | 540 | * manner, so it should recover the existing segment information of valid blocks |
541 | */ | 541 | */ |
542 | static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse) | 542 | static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse) |
543 | { | 543 | { |
544 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 544 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
545 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 545 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
546 | unsigned int new_segno = curseg->next_segno; | 546 | unsigned int new_segno = curseg->next_segno; |
547 | struct f2fs_summary_block *sum_node; | 547 | struct f2fs_summary_block *sum_node; |
548 | struct page *sum_page; | 548 | struct page *sum_page; |
549 | 549 | ||
550 | write_sum_page(sbi, curseg->sum_blk, | 550 | write_sum_page(sbi, curseg->sum_blk, |
551 | GET_SUM_BLOCK(sbi, curseg->segno)); | 551 | GET_SUM_BLOCK(sbi, curseg->segno)); |
552 | __set_test_and_inuse(sbi, new_segno); | 552 | __set_test_and_inuse(sbi, new_segno); |
553 | 553 | ||
554 | mutex_lock(&dirty_i->seglist_lock); | 554 | mutex_lock(&dirty_i->seglist_lock); |
555 | __remove_dirty_segment(sbi, new_segno, PRE); | 555 | __remove_dirty_segment(sbi, new_segno, PRE); |
556 | __remove_dirty_segment(sbi, new_segno, DIRTY); | 556 | __remove_dirty_segment(sbi, new_segno, DIRTY); |
557 | mutex_unlock(&dirty_i->seglist_lock); | 557 | mutex_unlock(&dirty_i->seglist_lock); |
558 | 558 | ||
559 | reset_curseg(sbi, type, 1); | 559 | reset_curseg(sbi, type, 1); |
560 | curseg->alloc_type = SSR; | 560 | curseg->alloc_type = SSR; |
561 | __next_free_blkoff(sbi, curseg, 0); | 561 | __next_free_blkoff(sbi, curseg, 0); |
562 | 562 | ||
563 | if (reuse) { | 563 | if (reuse) { |
564 | sum_page = get_sum_page(sbi, new_segno); | 564 | sum_page = get_sum_page(sbi, new_segno); |
565 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); | 565 | sum_node = (struct f2fs_summary_block *)page_address(sum_page); |
566 | memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); | 566 | memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); |
567 | f2fs_put_page(sum_page, 1); | 567 | f2fs_put_page(sum_page, 1); |
568 | } | 568 | } |
569 | } | 569 | } |
570 | 570 | ||
571 | static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) | 571 | static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) |
572 | { | 572 | { |
573 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 573 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
574 | const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; | 574 | const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; |
575 | 575 | ||
576 | if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0)) | 576 | if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0)) |
577 | return v_ops->get_victim(sbi, | 577 | return v_ops->get_victim(sbi, |
578 | &(curseg)->next_segno, BG_GC, type, SSR); | 578 | &(curseg)->next_segno, BG_GC, type, SSR); |
579 | 579 | ||
580 | /* For data segments, let's do SSR more intensively */ | 580 | /* For data segments, let's do SSR more intensively */ |
581 | for (; type >= CURSEG_HOT_DATA; type--) | 581 | for (; type >= CURSEG_HOT_DATA; type--) |
582 | if (v_ops->get_victim(sbi, &(curseg)->next_segno, | 582 | if (v_ops->get_victim(sbi, &(curseg)->next_segno, |
583 | BG_GC, type, SSR)) | 583 | BG_GC, type, SSR)) |
584 | return 1; | 584 | return 1; |
585 | return 0; | 585 | return 0; |
586 | } | 586 | } |
587 | 587 | ||
588 | /* | 588 | /* |
589 | * flush out current segment and replace it with new segment | 589 | * flush out current segment and replace it with new segment |
590 | * This function should be returned with success, otherwise BUG | 590 | * This function should be returned with success, otherwise BUG |
591 | */ | 591 | */ |
592 | static void allocate_segment_by_default(struct f2fs_sb_info *sbi, | 592 | static void allocate_segment_by_default(struct f2fs_sb_info *sbi, |
593 | int type, bool force) | 593 | int type, bool force) |
594 | { | 594 | { |
595 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 595 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
596 | 596 | ||
597 | if (force) { | 597 | if (force) { |
598 | new_curseg(sbi, type, true); | 598 | new_curseg(sbi, type, true); |
599 | goto out; | 599 | goto out; |
600 | } | 600 | } |
601 | 601 | ||
602 | curseg->next_segno = check_prefree_segments(sbi, type); | 602 | curseg->next_segno = check_prefree_segments(sbi, type); |
603 | 603 | ||
604 | if (curseg->next_segno != NULL_SEGNO) | 604 | if (curseg->next_segno != NULL_SEGNO) |
605 | change_curseg(sbi, type, false); | 605 | change_curseg(sbi, type, false); |
606 | else if (type == CURSEG_WARM_NODE) | 606 | else if (type == CURSEG_WARM_NODE) |
607 | new_curseg(sbi, type, false); | 607 | new_curseg(sbi, type, false); |
608 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) | 608 | else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) |
609 | new_curseg(sbi, type, false); | 609 | new_curseg(sbi, type, false); |
610 | else if (need_SSR(sbi) && get_ssr_segment(sbi, type)) | 610 | else if (need_SSR(sbi) && get_ssr_segment(sbi, type)) |
611 | change_curseg(sbi, type, true); | 611 | change_curseg(sbi, type, true); |
612 | else | 612 | else |
613 | new_curseg(sbi, type, false); | 613 | new_curseg(sbi, type, false); |
614 | out: | 614 | out: |
615 | sbi->segment_count[curseg->alloc_type]++; | 615 | sbi->segment_count[curseg->alloc_type]++; |
616 | } | 616 | } |
617 | 617 | ||
618 | void allocate_new_segments(struct f2fs_sb_info *sbi) | 618 | void allocate_new_segments(struct f2fs_sb_info *sbi) |
619 | { | 619 | { |
620 | struct curseg_info *curseg; | 620 | struct curseg_info *curseg; |
621 | unsigned int old_curseg; | 621 | unsigned int old_curseg; |
622 | int i; | 622 | int i; |
623 | 623 | ||
624 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 624 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
625 | curseg = CURSEG_I(sbi, i); | 625 | curseg = CURSEG_I(sbi, i); |
626 | old_curseg = curseg->segno; | 626 | old_curseg = curseg->segno; |
627 | SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true); | 627 | SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true); |
628 | locate_dirty_segment(sbi, old_curseg); | 628 | locate_dirty_segment(sbi, old_curseg); |
629 | } | 629 | } |
630 | } | 630 | } |
631 | 631 | ||
632 | static const struct segment_allocation default_salloc_ops = { | 632 | static const struct segment_allocation default_salloc_ops = { |
633 | .allocate_segment = allocate_segment_by_default, | 633 | .allocate_segment = allocate_segment_by_default, |
634 | }; | 634 | }; |
635 | 635 | ||
636 | static void f2fs_end_io_write(struct bio *bio, int err) | 636 | static void f2fs_end_io_write(struct bio *bio, int err) |
637 | { | 637 | { |
638 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); | 638 | const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); |
639 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; | 639 | struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; |
640 | struct bio_private *p = bio->bi_private; | 640 | struct bio_private *p = bio->bi_private; |
641 | 641 | ||
642 | do { | 642 | do { |
643 | struct page *page = bvec->bv_page; | 643 | struct page *page = bvec->bv_page; |
644 | 644 | ||
645 | if (--bvec >= bio->bi_io_vec) | 645 | if (--bvec >= bio->bi_io_vec) |
646 | prefetchw(&bvec->bv_page->flags); | 646 | prefetchw(&bvec->bv_page->flags); |
647 | if (!uptodate) { | 647 | if (!uptodate) { |
648 | SetPageError(page); | 648 | SetPageError(page); |
649 | if (page->mapping) | 649 | if (page->mapping) |
650 | set_bit(AS_EIO, &page->mapping->flags); | 650 | set_bit(AS_EIO, &page->mapping->flags); |
651 | set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG); | 651 | set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG); |
652 | p->sbi->sb->s_flags |= MS_RDONLY; | 652 | p->sbi->sb->s_flags |= MS_RDONLY; |
653 | } | 653 | } |
654 | end_page_writeback(page); | 654 | end_page_writeback(page); |
655 | dec_page_count(p->sbi, F2FS_WRITEBACK); | 655 | dec_page_count(p->sbi, F2FS_WRITEBACK); |
656 | } while (bvec >= bio->bi_io_vec); | 656 | } while (bvec >= bio->bi_io_vec); |
657 | 657 | ||
658 | if (p->is_sync) | 658 | if (p->is_sync) |
659 | complete(p->wait); | 659 | complete(p->wait); |
660 | kfree(p); | 660 | kfree(p); |
661 | bio_put(bio); | 661 | bio_put(bio); |
662 | } | 662 | } |
663 | 663 | ||
664 | struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages) | 664 | struct bio *f2fs_bio_alloc(struct block_device *bdev, int npages) |
665 | { | 665 | { |
666 | struct bio *bio; | 666 | struct bio *bio; |
667 | struct bio_private *priv; | 667 | struct bio_private *priv; |
668 | retry: | 668 | retry: |
669 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); | 669 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); |
670 | if (!priv) { | 670 | if (!priv) { |
671 | cond_resched(); | 671 | cond_resched(); |
672 | goto retry; | 672 | goto retry; |
673 | } | 673 | } |
674 | 674 | ||
675 | /* No failure on bio allocation */ | 675 | /* No failure on bio allocation */ |
676 | bio = bio_alloc(GFP_NOIO, npages); | 676 | bio = bio_alloc(GFP_NOIO, npages); |
677 | bio->bi_bdev = bdev; | 677 | bio->bi_bdev = bdev; |
678 | bio->bi_private = priv; | 678 | bio->bi_private = priv; |
679 | return bio; | 679 | return bio; |
680 | } | 680 | } |
681 | 681 | ||
682 | static void do_submit_bio(struct f2fs_sb_info *sbi, | 682 | static void do_submit_bio(struct f2fs_sb_info *sbi, |
683 | enum page_type type, bool sync) | 683 | enum page_type type, bool sync) |
684 | { | 684 | { |
685 | int rw = sync ? WRITE_SYNC : WRITE; | 685 | int rw = sync ? WRITE_SYNC : WRITE; |
686 | enum page_type btype = type > META ? META : type; | 686 | enum page_type btype = type > META ? META : type; |
687 | 687 | ||
688 | if (type >= META_FLUSH) | 688 | if (type >= META_FLUSH) |
689 | rw = WRITE_FLUSH_FUA; | 689 | rw = WRITE_FLUSH_FUA; |
690 | 690 | ||
691 | if (btype == META) | 691 | if (btype == META) |
692 | rw |= REQ_META; | 692 | rw |= REQ_META; |
693 | 693 | ||
694 | if (sbi->bio[btype]) { | 694 | if (sbi->bio[btype]) { |
695 | struct bio_private *p = sbi->bio[btype]->bi_private; | 695 | struct bio_private *p = sbi->bio[btype]->bi_private; |
696 | p->sbi = sbi; | 696 | p->sbi = sbi; |
697 | sbi->bio[btype]->bi_end_io = f2fs_end_io_write; | 697 | sbi->bio[btype]->bi_end_io = f2fs_end_io_write; |
698 | 698 | ||
699 | trace_f2fs_do_submit_bio(sbi->sb, btype, sync, sbi->bio[btype]); | 699 | trace_f2fs_do_submit_bio(sbi->sb, btype, sync, sbi->bio[btype]); |
700 | 700 | ||
701 | if (type == META_FLUSH) { | 701 | if (type == META_FLUSH) { |
702 | DECLARE_COMPLETION_ONSTACK(wait); | 702 | DECLARE_COMPLETION_ONSTACK(wait); |
703 | p->is_sync = true; | 703 | p->is_sync = true; |
704 | p->wait = &wait; | 704 | p->wait = &wait; |
705 | submit_bio(rw, sbi->bio[btype]); | 705 | submit_bio(rw, sbi->bio[btype]); |
706 | wait_for_completion(&wait); | 706 | wait_for_completion(&wait); |
707 | } else { | 707 | } else { |
708 | p->is_sync = false; | 708 | p->is_sync = false; |
709 | submit_bio(rw, sbi->bio[btype]); | 709 | submit_bio(rw, sbi->bio[btype]); |
710 | } | 710 | } |
711 | sbi->bio[btype] = NULL; | 711 | sbi->bio[btype] = NULL; |
712 | } | 712 | } |
713 | } | 713 | } |
714 | 714 | ||
715 | void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync) | 715 | void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync) |
716 | { | 716 | { |
717 | down_write(&sbi->bio_sem); | 717 | down_write(&sbi->bio_sem); |
718 | do_submit_bio(sbi, type, sync); | 718 | do_submit_bio(sbi, type, sync); |
719 | up_write(&sbi->bio_sem); | 719 | up_write(&sbi->bio_sem); |
720 | } | 720 | } |
721 | 721 | ||
722 | static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, | 722 | static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, |
723 | block_t blk_addr, enum page_type type) | 723 | block_t blk_addr, enum page_type type) |
724 | { | 724 | { |
725 | struct block_device *bdev = sbi->sb->s_bdev; | 725 | struct block_device *bdev = sbi->sb->s_bdev; |
726 | 726 | ||
727 | verify_block_addr(sbi, blk_addr); | 727 | verify_block_addr(sbi, blk_addr); |
728 | 728 | ||
729 | down_write(&sbi->bio_sem); | 729 | down_write(&sbi->bio_sem); |
730 | 730 | ||
731 | inc_page_count(sbi, F2FS_WRITEBACK); | 731 | inc_page_count(sbi, F2FS_WRITEBACK); |
732 | 732 | ||
733 | if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1) | 733 | if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1) |
734 | do_submit_bio(sbi, type, false); | 734 | do_submit_bio(sbi, type, false); |
735 | alloc_new: | 735 | alloc_new: |
736 | if (sbi->bio[type] == NULL) { | 736 | if (sbi->bio[type] == NULL) { |
737 | sbi->bio[type] = f2fs_bio_alloc(bdev, bio_get_nr_vecs(bdev)); | 737 | sbi->bio[type] = f2fs_bio_alloc(bdev, max_hw_blocks(sbi)); |
738 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); | 738 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); |
739 | /* | 739 | /* |
740 | * The end_io will be assigned at the sumbission phase. | 740 | * The end_io will be assigned at the sumbission phase. |
741 | * Until then, let bio_add_page() merge consecutive IOs as much | 741 | * Until then, let bio_add_page() merge consecutive IOs as much |
742 | * as possible. | 742 | * as possible. |
743 | */ | 743 | */ |
744 | } | 744 | } |
745 | 745 | ||
746 | if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) < | 746 | if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) < |
747 | PAGE_CACHE_SIZE) { | 747 | PAGE_CACHE_SIZE) { |
748 | do_submit_bio(sbi, type, false); | 748 | do_submit_bio(sbi, type, false); |
749 | goto alloc_new; | 749 | goto alloc_new; |
750 | } | 750 | } |
751 | 751 | ||
752 | sbi->last_block_in_bio[type] = blk_addr; | 752 | sbi->last_block_in_bio[type] = blk_addr; |
753 | 753 | ||
754 | up_write(&sbi->bio_sem); | 754 | up_write(&sbi->bio_sem); |
755 | trace_f2fs_submit_write_page(page, blk_addr, type); | 755 | trace_f2fs_submit_write_page(page, blk_addr, type); |
756 | } | 756 | } |
757 | 757 | ||
758 | static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) | 758 | static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) |
759 | { | 759 | { |
760 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 760 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
761 | if (curseg->next_blkoff < sbi->blocks_per_seg) | 761 | if (curseg->next_blkoff < sbi->blocks_per_seg) |
762 | return true; | 762 | return true; |
763 | return false; | 763 | return false; |
764 | } | 764 | } |
765 | 765 | ||
766 | static int __get_segment_type_2(struct page *page, enum page_type p_type) | 766 | static int __get_segment_type_2(struct page *page, enum page_type p_type) |
767 | { | 767 | { |
768 | if (p_type == DATA) | 768 | if (p_type == DATA) |
769 | return CURSEG_HOT_DATA; | 769 | return CURSEG_HOT_DATA; |
770 | else | 770 | else |
771 | return CURSEG_HOT_NODE; | 771 | return CURSEG_HOT_NODE; |
772 | } | 772 | } |
773 | 773 | ||
774 | static int __get_segment_type_4(struct page *page, enum page_type p_type) | 774 | static int __get_segment_type_4(struct page *page, enum page_type p_type) |
775 | { | 775 | { |
776 | if (p_type == DATA) { | 776 | if (p_type == DATA) { |
777 | struct inode *inode = page->mapping->host; | 777 | struct inode *inode = page->mapping->host; |
778 | 778 | ||
779 | if (S_ISDIR(inode->i_mode)) | 779 | if (S_ISDIR(inode->i_mode)) |
780 | return CURSEG_HOT_DATA; | 780 | return CURSEG_HOT_DATA; |
781 | else | 781 | else |
782 | return CURSEG_COLD_DATA; | 782 | return CURSEG_COLD_DATA; |
783 | } else { | 783 | } else { |
784 | if (IS_DNODE(page) && !is_cold_node(page)) | 784 | if (IS_DNODE(page) && !is_cold_node(page)) |
785 | return CURSEG_HOT_NODE; | 785 | return CURSEG_HOT_NODE; |
786 | else | 786 | else |
787 | return CURSEG_COLD_NODE; | 787 | return CURSEG_COLD_NODE; |
788 | } | 788 | } |
789 | } | 789 | } |
790 | 790 | ||
791 | static int __get_segment_type_6(struct page *page, enum page_type p_type) | 791 | static int __get_segment_type_6(struct page *page, enum page_type p_type) |
792 | { | 792 | { |
793 | if (p_type == DATA) { | 793 | if (p_type == DATA) { |
794 | struct inode *inode = page->mapping->host; | 794 | struct inode *inode = page->mapping->host; |
795 | 795 | ||
796 | if (S_ISDIR(inode->i_mode)) | 796 | if (S_ISDIR(inode->i_mode)) |
797 | return CURSEG_HOT_DATA; | 797 | return CURSEG_HOT_DATA; |
798 | else if (is_cold_data(page) || is_cold_file(inode)) | 798 | else if (is_cold_data(page) || is_cold_file(inode)) |
799 | return CURSEG_COLD_DATA; | 799 | return CURSEG_COLD_DATA; |
800 | else | 800 | else |
801 | return CURSEG_WARM_DATA; | 801 | return CURSEG_WARM_DATA; |
802 | } else { | 802 | } else { |
803 | if (IS_DNODE(page)) | 803 | if (IS_DNODE(page)) |
804 | return is_cold_node(page) ? CURSEG_WARM_NODE : | 804 | return is_cold_node(page) ? CURSEG_WARM_NODE : |
805 | CURSEG_HOT_NODE; | 805 | CURSEG_HOT_NODE; |
806 | else | 806 | else |
807 | return CURSEG_COLD_NODE; | 807 | return CURSEG_COLD_NODE; |
808 | } | 808 | } |
809 | } | 809 | } |
810 | 810 | ||
811 | static int __get_segment_type(struct page *page, enum page_type p_type) | 811 | static int __get_segment_type(struct page *page, enum page_type p_type) |
812 | { | 812 | { |
813 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); | 813 | struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); |
814 | switch (sbi->active_logs) { | 814 | switch (sbi->active_logs) { |
815 | case 2: | 815 | case 2: |
816 | return __get_segment_type_2(page, p_type); | 816 | return __get_segment_type_2(page, p_type); |
817 | case 4: | 817 | case 4: |
818 | return __get_segment_type_4(page, p_type); | 818 | return __get_segment_type_4(page, p_type); |
819 | } | 819 | } |
820 | /* NR_CURSEG_TYPE(6) logs by default */ | 820 | /* NR_CURSEG_TYPE(6) logs by default */ |
821 | BUG_ON(sbi->active_logs != NR_CURSEG_TYPE); | 821 | BUG_ON(sbi->active_logs != NR_CURSEG_TYPE); |
822 | return __get_segment_type_6(page, p_type); | 822 | return __get_segment_type_6(page, p_type); |
823 | } | 823 | } |
824 | 824 | ||
825 | static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, | 825 | static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, |
826 | block_t old_blkaddr, block_t *new_blkaddr, | 826 | block_t old_blkaddr, block_t *new_blkaddr, |
827 | struct f2fs_summary *sum, enum page_type p_type) | 827 | struct f2fs_summary *sum, enum page_type p_type) |
828 | { | 828 | { |
829 | struct sit_info *sit_i = SIT_I(sbi); | 829 | struct sit_info *sit_i = SIT_I(sbi); |
830 | struct curseg_info *curseg; | 830 | struct curseg_info *curseg; |
831 | unsigned int old_cursegno; | 831 | unsigned int old_cursegno; |
832 | int type; | 832 | int type; |
833 | 833 | ||
834 | type = __get_segment_type(page, p_type); | 834 | type = __get_segment_type(page, p_type); |
835 | curseg = CURSEG_I(sbi, type); | 835 | curseg = CURSEG_I(sbi, type); |
836 | 836 | ||
837 | mutex_lock(&curseg->curseg_mutex); | 837 | mutex_lock(&curseg->curseg_mutex); |
838 | 838 | ||
839 | *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); | 839 | *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); |
840 | old_cursegno = curseg->segno; | 840 | old_cursegno = curseg->segno; |
841 | 841 | ||
842 | /* | 842 | /* |
843 | * __add_sum_entry should be resided under the curseg_mutex | 843 | * __add_sum_entry should be resided under the curseg_mutex |
844 | * because, this function updates a summary entry in the | 844 | * because, this function updates a summary entry in the |
845 | * current summary block. | 845 | * current summary block. |
846 | */ | 846 | */ |
847 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 847 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); |
848 | 848 | ||
849 | mutex_lock(&sit_i->sentry_lock); | 849 | mutex_lock(&sit_i->sentry_lock); |
850 | __refresh_next_blkoff(sbi, curseg); | 850 | __refresh_next_blkoff(sbi, curseg); |
851 | sbi->block_count[curseg->alloc_type]++; | 851 | sbi->block_count[curseg->alloc_type]++; |
852 | 852 | ||
853 | /* | 853 | /* |
854 | * SIT information should be updated before segment allocation, | 854 | * SIT information should be updated before segment allocation, |
855 | * since SSR needs latest valid block information. | 855 | * since SSR needs latest valid block information. |
856 | */ | 856 | */ |
857 | refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr); | 857 | refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr); |
858 | 858 | ||
859 | if (!__has_curseg_space(sbi, type)) | 859 | if (!__has_curseg_space(sbi, type)) |
860 | sit_i->s_ops->allocate_segment(sbi, type, false); | 860 | sit_i->s_ops->allocate_segment(sbi, type, false); |
861 | 861 | ||
862 | locate_dirty_segment(sbi, old_cursegno); | 862 | locate_dirty_segment(sbi, old_cursegno); |
863 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); | 863 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); |
864 | mutex_unlock(&sit_i->sentry_lock); | 864 | mutex_unlock(&sit_i->sentry_lock); |
865 | 865 | ||
866 | if (p_type == NODE) | 866 | if (p_type == NODE) |
867 | fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); | 867 | fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); |
868 | 868 | ||
869 | /* writeout dirty page into bdev */ | 869 | /* writeout dirty page into bdev */ |
870 | submit_write_page(sbi, page, *new_blkaddr, p_type); | 870 | submit_write_page(sbi, page, *new_blkaddr, p_type); |
871 | 871 | ||
872 | mutex_unlock(&curseg->curseg_mutex); | 872 | mutex_unlock(&curseg->curseg_mutex); |
873 | } | 873 | } |
874 | 874 | ||
875 | void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) | 875 | void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) |
876 | { | 876 | { |
877 | set_page_writeback(page); | 877 | set_page_writeback(page); |
878 | submit_write_page(sbi, page, page->index, META); | 878 | submit_write_page(sbi, page, page->index, META); |
879 | } | 879 | } |
880 | 880 | ||
881 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, | 881 | void write_node_page(struct f2fs_sb_info *sbi, struct page *page, |
882 | unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) | 882 | unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) |
883 | { | 883 | { |
884 | struct f2fs_summary sum; | 884 | struct f2fs_summary sum; |
885 | set_summary(&sum, nid, 0, 0); | 885 | set_summary(&sum, nid, 0, 0); |
886 | do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE); | 886 | do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, NODE); |
887 | } | 887 | } |
888 | 888 | ||
889 | void write_data_page(struct inode *inode, struct page *page, | 889 | void write_data_page(struct inode *inode, struct page *page, |
890 | struct dnode_of_data *dn, block_t old_blkaddr, | 890 | struct dnode_of_data *dn, block_t old_blkaddr, |
891 | block_t *new_blkaddr) | 891 | block_t *new_blkaddr) |
892 | { | 892 | { |
893 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 893 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
894 | struct f2fs_summary sum; | 894 | struct f2fs_summary sum; |
895 | struct node_info ni; | 895 | struct node_info ni; |
896 | 896 | ||
897 | BUG_ON(old_blkaddr == NULL_ADDR); | 897 | BUG_ON(old_blkaddr == NULL_ADDR); |
898 | get_node_info(sbi, dn->nid, &ni); | 898 | get_node_info(sbi, dn->nid, &ni); |
899 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); | 899 | set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); |
900 | 900 | ||
901 | do_write_page(sbi, page, old_blkaddr, | 901 | do_write_page(sbi, page, old_blkaddr, |
902 | new_blkaddr, &sum, DATA); | 902 | new_blkaddr, &sum, DATA); |
903 | } | 903 | } |
904 | 904 | ||
905 | void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page, | 905 | void rewrite_data_page(struct f2fs_sb_info *sbi, struct page *page, |
906 | block_t old_blk_addr) | 906 | block_t old_blk_addr) |
907 | { | 907 | { |
908 | submit_write_page(sbi, page, old_blk_addr, DATA); | 908 | submit_write_page(sbi, page, old_blk_addr, DATA); |
909 | } | 909 | } |
910 | 910 | ||
911 | void recover_data_page(struct f2fs_sb_info *sbi, | 911 | void recover_data_page(struct f2fs_sb_info *sbi, |
912 | struct page *page, struct f2fs_summary *sum, | 912 | struct page *page, struct f2fs_summary *sum, |
913 | block_t old_blkaddr, block_t new_blkaddr) | 913 | block_t old_blkaddr, block_t new_blkaddr) |
914 | { | 914 | { |
915 | struct sit_info *sit_i = SIT_I(sbi); | 915 | struct sit_info *sit_i = SIT_I(sbi); |
916 | struct curseg_info *curseg; | 916 | struct curseg_info *curseg; |
917 | unsigned int segno, old_cursegno; | 917 | unsigned int segno, old_cursegno; |
918 | struct seg_entry *se; | 918 | struct seg_entry *se; |
919 | int type; | 919 | int type; |
920 | 920 | ||
921 | segno = GET_SEGNO(sbi, new_blkaddr); | 921 | segno = GET_SEGNO(sbi, new_blkaddr); |
922 | se = get_seg_entry(sbi, segno); | 922 | se = get_seg_entry(sbi, segno); |
923 | type = se->type; | 923 | type = se->type; |
924 | 924 | ||
925 | if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) { | 925 | if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) { |
926 | if (old_blkaddr == NULL_ADDR) | 926 | if (old_blkaddr == NULL_ADDR) |
927 | type = CURSEG_COLD_DATA; | 927 | type = CURSEG_COLD_DATA; |
928 | else | 928 | else |
929 | type = CURSEG_WARM_DATA; | 929 | type = CURSEG_WARM_DATA; |
930 | } | 930 | } |
931 | curseg = CURSEG_I(sbi, type); | 931 | curseg = CURSEG_I(sbi, type); |
932 | 932 | ||
933 | mutex_lock(&curseg->curseg_mutex); | 933 | mutex_lock(&curseg->curseg_mutex); |
934 | mutex_lock(&sit_i->sentry_lock); | 934 | mutex_lock(&sit_i->sentry_lock); |
935 | 935 | ||
936 | old_cursegno = curseg->segno; | 936 | old_cursegno = curseg->segno; |
937 | 937 | ||
938 | /* change the current segment */ | 938 | /* change the current segment */ |
939 | if (segno != curseg->segno) { | 939 | if (segno != curseg->segno) { |
940 | curseg->next_segno = segno; | 940 | curseg->next_segno = segno; |
941 | change_curseg(sbi, type, true); | 941 | change_curseg(sbi, type, true); |
942 | } | 942 | } |
943 | 943 | ||
944 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & | 944 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & |
945 | (sbi->blocks_per_seg - 1); | 945 | (sbi->blocks_per_seg - 1); |
946 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 946 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); |
947 | 947 | ||
948 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); | 948 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); |
949 | 949 | ||
950 | locate_dirty_segment(sbi, old_cursegno); | 950 | locate_dirty_segment(sbi, old_cursegno); |
951 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); | 951 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); |
952 | 952 | ||
953 | mutex_unlock(&sit_i->sentry_lock); | 953 | mutex_unlock(&sit_i->sentry_lock); |
954 | mutex_unlock(&curseg->curseg_mutex); | 954 | mutex_unlock(&curseg->curseg_mutex); |
955 | } | 955 | } |
956 | 956 | ||
957 | void rewrite_node_page(struct f2fs_sb_info *sbi, | 957 | void rewrite_node_page(struct f2fs_sb_info *sbi, |
958 | struct page *page, struct f2fs_summary *sum, | 958 | struct page *page, struct f2fs_summary *sum, |
959 | block_t old_blkaddr, block_t new_blkaddr) | 959 | block_t old_blkaddr, block_t new_blkaddr) |
960 | { | 960 | { |
961 | struct sit_info *sit_i = SIT_I(sbi); | 961 | struct sit_info *sit_i = SIT_I(sbi); |
962 | int type = CURSEG_WARM_NODE; | 962 | int type = CURSEG_WARM_NODE; |
963 | struct curseg_info *curseg; | 963 | struct curseg_info *curseg; |
964 | unsigned int segno, old_cursegno; | 964 | unsigned int segno, old_cursegno; |
965 | block_t next_blkaddr = next_blkaddr_of_node(page); | 965 | block_t next_blkaddr = next_blkaddr_of_node(page); |
966 | unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr); | 966 | unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr); |
967 | 967 | ||
968 | curseg = CURSEG_I(sbi, type); | 968 | curseg = CURSEG_I(sbi, type); |
969 | 969 | ||
970 | mutex_lock(&curseg->curseg_mutex); | 970 | mutex_lock(&curseg->curseg_mutex); |
971 | mutex_lock(&sit_i->sentry_lock); | 971 | mutex_lock(&sit_i->sentry_lock); |
972 | 972 | ||
973 | segno = GET_SEGNO(sbi, new_blkaddr); | 973 | segno = GET_SEGNO(sbi, new_blkaddr); |
974 | old_cursegno = curseg->segno; | 974 | old_cursegno = curseg->segno; |
975 | 975 | ||
976 | /* change the current segment */ | 976 | /* change the current segment */ |
977 | if (segno != curseg->segno) { | 977 | if (segno != curseg->segno) { |
978 | curseg->next_segno = segno; | 978 | curseg->next_segno = segno; |
979 | change_curseg(sbi, type, true); | 979 | change_curseg(sbi, type, true); |
980 | } | 980 | } |
981 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & | 981 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, new_blkaddr) & |
982 | (sbi->blocks_per_seg - 1); | 982 | (sbi->blocks_per_seg - 1); |
983 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); | 983 | __add_sum_entry(sbi, type, sum, curseg->next_blkoff); |
984 | 984 | ||
985 | /* change the current log to the next block addr in advance */ | 985 | /* change the current log to the next block addr in advance */ |
986 | if (next_segno != segno) { | 986 | if (next_segno != segno) { |
987 | curseg->next_segno = next_segno; | 987 | curseg->next_segno = next_segno; |
988 | change_curseg(sbi, type, true); | 988 | change_curseg(sbi, type, true); |
989 | } | 989 | } |
990 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) & | 990 | curseg->next_blkoff = GET_SEGOFF_FROM_SEG0(sbi, next_blkaddr) & |
991 | (sbi->blocks_per_seg - 1); | 991 | (sbi->blocks_per_seg - 1); |
992 | 992 | ||
993 | /* rewrite node page */ | 993 | /* rewrite node page */ |
994 | set_page_writeback(page); | 994 | set_page_writeback(page); |
995 | submit_write_page(sbi, page, new_blkaddr, NODE); | 995 | submit_write_page(sbi, page, new_blkaddr, NODE); |
996 | f2fs_submit_bio(sbi, NODE, true); | 996 | f2fs_submit_bio(sbi, NODE, true); |
997 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); | 997 | refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); |
998 | 998 | ||
999 | locate_dirty_segment(sbi, old_cursegno); | 999 | locate_dirty_segment(sbi, old_cursegno); |
1000 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); | 1000 | locate_dirty_segment(sbi, GET_SEGNO(sbi, old_blkaddr)); |
1001 | 1001 | ||
1002 | mutex_unlock(&sit_i->sentry_lock); | 1002 | mutex_unlock(&sit_i->sentry_lock); |
1003 | mutex_unlock(&curseg->curseg_mutex); | 1003 | mutex_unlock(&curseg->curseg_mutex); |
1004 | } | 1004 | } |
1005 | 1005 | ||
1006 | static int read_compacted_summaries(struct f2fs_sb_info *sbi) | 1006 | static int read_compacted_summaries(struct f2fs_sb_info *sbi) |
1007 | { | 1007 | { |
1008 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 1008 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
1009 | struct curseg_info *seg_i; | 1009 | struct curseg_info *seg_i; |
1010 | unsigned char *kaddr; | 1010 | unsigned char *kaddr; |
1011 | struct page *page; | 1011 | struct page *page; |
1012 | block_t start; | 1012 | block_t start; |
1013 | int i, j, offset; | 1013 | int i, j, offset; |
1014 | 1014 | ||
1015 | start = start_sum_block(sbi); | 1015 | start = start_sum_block(sbi); |
1016 | 1016 | ||
1017 | page = get_meta_page(sbi, start++); | 1017 | page = get_meta_page(sbi, start++); |
1018 | kaddr = (unsigned char *)page_address(page); | 1018 | kaddr = (unsigned char *)page_address(page); |
1019 | 1019 | ||
1020 | /* Step 1: restore nat cache */ | 1020 | /* Step 1: restore nat cache */ |
1021 | seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1021 | seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); |
1022 | memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE); | 1022 | memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE); |
1023 | 1023 | ||
1024 | /* Step 2: restore sit cache */ | 1024 | /* Step 2: restore sit cache */ |
1025 | seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1025 | seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); |
1026 | memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, | 1026 | memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, |
1027 | SUM_JOURNAL_SIZE); | 1027 | SUM_JOURNAL_SIZE); |
1028 | offset = 2 * SUM_JOURNAL_SIZE; | 1028 | offset = 2 * SUM_JOURNAL_SIZE; |
1029 | 1029 | ||
1030 | /* Step 3: restore summary entries */ | 1030 | /* Step 3: restore summary entries */ |
1031 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 1031 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
1032 | unsigned short blk_off; | 1032 | unsigned short blk_off; |
1033 | unsigned int segno; | 1033 | unsigned int segno; |
1034 | 1034 | ||
1035 | seg_i = CURSEG_I(sbi, i); | 1035 | seg_i = CURSEG_I(sbi, i); |
1036 | segno = le32_to_cpu(ckpt->cur_data_segno[i]); | 1036 | segno = le32_to_cpu(ckpt->cur_data_segno[i]); |
1037 | blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); | 1037 | blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); |
1038 | seg_i->next_segno = segno; | 1038 | seg_i->next_segno = segno; |
1039 | reset_curseg(sbi, i, 0); | 1039 | reset_curseg(sbi, i, 0); |
1040 | seg_i->alloc_type = ckpt->alloc_type[i]; | 1040 | seg_i->alloc_type = ckpt->alloc_type[i]; |
1041 | seg_i->next_blkoff = blk_off; | 1041 | seg_i->next_blkoff = blk_off; |
1042 | 1042 | ||
1043 | if (seg_i->alloc_type == SSR) | 1043 | if (seg_i->alloc_type == SSR) |
1044 | blk_off = sbi->blocks_per_seg; | 1044 | blk_off = sbi->blocks_per_seg; |
1045 | 1045 | ||
1046 | for (j = 0; j < blk_off; j++) { | 1046 | for (j = 0; j < blk_off; j++) { |
1047 | struct f2fs_summary *s; | 1047 | struct f2fs_summary *s; |
1048 | s = (struct f2fs_summary *)(kaddr + offset); | 1048 | s = (struct f2fs_summary *)(kaddr + offset); |
1049 | seg_i->sum_blk->entries[j] = *s; | 1049 | seg_i->sum_blk->entries[j] = *s; |
1050 | offset += SUMMARY_SIZE; | 1050 | offset += SUMMARY_SIZE; |
1051 | if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE - | 1051 | if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE - |
1052 | SUM_FOOTER_SIZE) | 1052 | SUM_FOOTER_SIZE) |
1053 | continue; | 1053 | continue; |
1054 | 1054 | ||
1055 | f2fs_put_page(page, 1); | 1055 | f2fs_put_page(page, 1); |
1056 | page = NULL; | 1056 | page = NULL; |
1057 | 1057 | ||
1058 | page = get_meta_page(sbi, start++); | 1058 | page = get_meta_page(sbi, start++); |
1059 | kaddr = (unsigned char *)page_address(page); | 1059 | kaddr = (unsigned char *)page_address(page); |
1060 | offset = 0; | 1060 | offset = 0; |
1061 | } | 1061 | } |
1062 | } | 1062 | } |
1063 | f2fs_put_page(page, 1); | 1063 | f2fs_put_page(page, 1); |
1064 | return 0; | 1064 | return 0; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) | 1067 | static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) |
1068 | { | 1068 | { |
1069 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 1069 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
1070 | struct f2fs_summary_block *sum; | 1070 | struct f2fs_summary_block *sum; |
1071 | struct curseg_info *curseg; | 1071 | struct curseg_info *curseg; |
1072 | struct page *new; | 1072 | struct page *new; |
1073 | unsigned short blk_off; | 1073 | unsigned short blk_off; |
1074 | unsigned int segno = 0; | 1074 | unsigned int segno = 0; |
1075 | block_t blk_addr = 0; | 1075 | block_t blk_addr = 0; |
1076 | 1076 | ||
1077 | /* get segment number and block addr */ | 1077 | /* get segment number and block addr */ |
1078 | if (IS_DATASEG(type)) { | 1078 | if (IS_DATASEG(type)) { |
1079 | segno = le32_to_cpu(ckpt->cur_data_segno[type]); | 1079 | segno = le32_to_cpu(ckpt->cur_data_segno[type]); |
1080 | blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - | 1080 | blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - |
1081 | CURSEG_HOT_DATA]); | 1081 | CURSEG_HOT_DATA]); |
1082 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) | 1082 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) |
1083 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); | 1083 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); |
1084 | else | 1084 | else |
1085 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type); | 1085 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type); |
1086 | } else { | 1086 | } else { |
1087 | segno = le32_to_cpu(ckpt->cur_node_segno[type - | 1087 | segno = le32_to_cpu(ckpt->cur_node_segno[type - |
1088 | CURSEG_HOT_NODE]); | 1088 | CURSEG_HOT_NODE]); |
1089 | blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - | 1089 | blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - |
1090 | CURSEG_HOT_NODE]); | 1090 | CURSEG_HOT_NODE]); |
1091 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) | 1091 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) |
1092 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, | 1092 | blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, |
1093 | type - CURSEG_HOT_NODE); | 1093 | type - CURSEG_HOT_NODE); |
1094 | else | 1094 | else |
1095 | blk_addr = GET_SUM_BLOCK(sbi, segno); | 1095 | blk_addr = GET_SUM_BLOCK(sbi, segno); |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | new = get_meta_page(sbi, blk_addr); | 1098 | new = get_meta_page(sbi, blk_addr); |
1099 | sum = (struct f2fs_summary_block *)page_address(new); | 1099 | sum = (struct f2fs_summary_block *)page_address(new); |
1100 | 1100 | ||
1101 | if (IS_NODESEG(type)) { | 1101 | if (IS_NODESEG(type)) { |
1102 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { | 1102 | if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { |
1103 | struct f2fs_summary *ns = &sum->entries[0]; | 1103 | struct f2fs_summary *ns = &sum->entries[0]; |
1104 | int i; | 1104 | int i; |
1105 | for (i = 0; i < sbi->blocks_per_seg; i++, ns++) { | 1105 | for (i = 0; i < sbi->blocks_per_seg; i++, ns++) { |
1106 | ns->version = 0; | 1106 | ns->version = 0; |
1107 | ns->ofs_in_node = 0; | 1107 | ns->ofs_in_node = 0; |
1108 | } | 1108 | } |
1109 | } else { | 1109 | } else { |
1110 | if (restore_node_summary(sbi, segno, sum)) { | 1110 | if (restore_node_summary(sbi, segno, sum)) { |
1111 | f2fs_put_page(new, 1); | 1111 | f2fs_put_page(new, 1); |
1112 | return -EINVAL; | 1112 | return -EINVAL; |
1113 | } | 1113 | } |
1114 | } | 1114 | } |
1115 | } | 1115 | } |
1116 | 1116 | ||
1117 | /* set uncompleted segment to curseg */ | 1117 | /* set uncompleted segment to curseg */ |
1118 | curseg = CURSEG_I(sbi, type); | 1118 | curseg = CURSEG_I(sbi, type); |
1119 | mutex_lock(&curseg->curseg_mutex); | 1119 | mutex_lock(&curseg->curseg_mutex); |
1120 | memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE); | 1120 | memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE); |
1121 | curseg->next_segno = segno; | 1121 | curseg->next_segno = segno; |
1122 | reset_curseg(sbi, type, 0); | 1122 | reset_curseg(sbi, type, 0); |
1123 | curseg->alloc_type = ckpt->alloc_type[type]; | 1123 | curseg->alloc_type = ckpt->alloc_type[type]; |
1124 | curseg->next_blkoff = blk_off; | 1124 | curseg->next_blkoff = blk_off; |
1125 | mutex_unlock(&curseg->curseg_mutex); | 1125 | mutex_unlock(&curseg->curseg_mutex); |
1126 | f2fs_put_page(new, 1); | 1126 | f2fs_put_page(new, 1); |
1127 | return 0; | 1127 | return 0; |
1128 | } | 1128 | } |
1129 | 1129 | ||
1130 | static int restore_curseg_summaries(struct f2fs_sb_info *sbi) | 1130 | static int restore_curseg_summaries(struct f2fs_sb_info *sbi) |
1131 | { | 1131 | { |
1132 | int type = CURSEG_HOT_DATA; | 1132 | int type = CURSEG_HOT_DATA; |
1133 | 1133 | ||
1134 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) { | 1134 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) { |
1135 | /* restore for compacted data summary */ | 1135 | /* restore for compacted data summary */ |
1136 | if (read_compacted_summaries(sbi)) | 1136 | if (read_compacted_summaries(sbi)) |
1137 | return -EINVAL; | 1137 | return -EINVAL; |
1138 | type = CURSEG_HOT_NODE; | 1138 | type = CURSEG_HOT_NODE; |
1139 | } | 1139 | } |
1140 | 1140 | ||
1141 | for (; type <= CURSEG_COLD_NODE; type++) | 1141 | for (; type <= CURSEG_COLD_NODE; type++) |
1142 | if (read_normal_summaries(sbi, type)) | 1142 | if (read_normal_summaries(sbi, type)) |
1143 | return -EINVAL; | 1143 | return -EINVAL; |
1144 | return 0; | 1144 | return 0; |
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr) | 1147 | static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr) |
1148 | { | 1148 | { |
1149 | struct page *page; | 1149 | struct page *page; |
1150 | unsigned char *kaddr; | 1150 | unsigned char *kaddr; |
1151 | struct f2fs_summary *summary; | 1151 | struct f2fs_summary *summary; |
1152 | struct curseg_info *seg_i; | 1152 | struct curseg_info *seg_i; |
1153 | int written_size = 0; | 1153 | int written_size = 0; |
1154 | int i, j; | 1154 | int i, j; |
1155 | 1155 | ||
1156 | page = grab_meta_page(sbi, blkaddr++); | 1156 | page = grab_meta_page(sbi, blkaddr++); |
1157 | kaddr = (unsigned char *)page_address(page); | 1157 | kaddr = (unsigned char *)page_address(page); |
1158 | 1158 | ||
1159 | /* Step 1: write nat cache */ | 1159 | /* Step 1: write nat cache */ |
1160 | seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); | 1160 | seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); |
1161 | memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE); | 1161 | memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE); |
1162 | written_size += SUM_JOURNAL_SIZE; | 1162 | written_size += SUM_JOURNAL_SIZE; |
1163 | 1163 | ||
1164 | /* Step 2: write sit cache */ | 1164 | /* Step 2: write sit cache */ |
1165 | seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1165 | seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); |
1166 | memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits, | 1166 | memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits, |
1167 | SUM_JOURNAL_SIZE); | 1167 | SUM_JOURNAL_SIZE); |
1168 | written_size += SUM_JOURNAL_SIZE; | 1168 | written_size += SUM_JOURNAL_SIZE; |
1169 | 1169 | ||
1170 | set_page_dirty(page); | 1170 | set_page_dirty(page); |
1171 | 1171 | ||
1172 | /* Step 3: write summary entries */ | 1172 | /* Step 3: write summary entries */ |
1173 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { | 1173 | for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { |
1174 | unsigned short blkoff; | 1174 | unsigned short blkoff; |
1175 | seg_i = CURSEG_I(sbi, i); | 1175 | seg_i = CURSEG_I(sbi, i); |
1176 | if (sbi->ckpt->alloc_type[i] == SSR) | 1176 | if (sbi->ckpt->alloc_type[i] == SSR) |
1177 | blkoff = sbi->blocks_per_seg; | 1177 | blkoff = sbi->blocks_per_seg; |
1178 | else | 1178 | else |
1179 | blkoff = curseg_blkoff(sbi, i); | 1179 | blkoff = curseg_blkoff(sbi, i); |
1180 | 1180 | ||
1181 | for (j = 0; j < blkoff; j++) { | 1181 | for (j = 0; j < blkoff; j++) { |
1182 | if (!page) { | 1182 | if (!page) { |
1183 | page = grab_meta_page(sbi, blkaddr++); | 1183 | page = grab_meta_page(sbi, blkaddr++); |
1184 | kaddr = (unsigned char *)page_address(page); | 1184 | kaddr = (unsigned char *)page_address(page); |
1185 | written_size = 0; | 1185 | written_size = 0; |
1186 | } | 1186 | } |
1187 | summary = (struct f2fs_summary *)(kaddr + written_size); | 1187 | summary = (struct f2fs_summary *)(kaddr + written_size); |
1188 | *summary = seg_i->sum_blk->entries[j]; | 1188 | *summary = seg_i->sum_blk->entries[j]; |
1189 | written_size += SUMMARY_SIZE; | 1189 | written_size += SUMMARY_SIZE; |
1190 | set_page_dirty(page); | 1190 | set_page_dirty(page); |
1191 | 1191 | ||
1192 | if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE - | 1192 | if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE - |
1193 | SUM_FOOTER_SIZE) | 1193 | SUM_FOOTER_SIZE) |
1194 | continue; | 1194 | continue; |
1195 | 1195 | ||
1196 | f2fs_put_page(page, 1); | 1196 | f2fs_put_page(page, 1); |
1197 | page = NULL; | 1197 | page = NULL; |
1198 | } | 1198 | } |
1199 | } | 1199 | } |
1200 | if (page) | 1200 | if (page) |
1201 | f2fs_put_page(page, 1); | 1201 | f2fs_put_page(page, 1); |
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | static void write_normal_summaries(struct f2fs_sb_info *sbi, | 1204 | static void write_normal_summaries(struct f2fs_sb_info *sbi, |
1205 | block_t blkaddr, int type) | 1205 | block_t blkaddr, int type) |
1206 | { | 1206 | { |
1207 | int i, end; | 1207 | int i, end; |
1208 | if (IS_DATASEG(type)) | 1208 | if (IS_DATASEG(type)) |
1209 | end = type + NR_CURSEG_DATA_TYPE; | 1209 | end = type + NR_CURSEG_DATA_TYPE; |
1210 | else | 1210 | else |
1211 | end = type + NR_CURSEG_NODE_TYPE; | 1211 | end = type + NR_CURSEG_NODE_TYPE; |
1212 | 1212 | ||
1213 | for (i = type; i < end; i++) { | 1213 | for (i = type; i < end; i++) { |
1214 | struct curseg_info *sum = CURSEG_I(sbi, i); | 1214 | struct curseg_info *sum = CURSEG_I(sbi, i); |
1215 | mutex_lock(&sum->curseg_mutex); | 1215 | mutex_lock(&sum->curseg_mutex); |
1216 | write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type)); | 1216 | write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type)); |
1217 | mutex_unlock(&sum->curseg_mutex); | 1217 | mutex_unlock(&sum->curseg_mutex); |
1218 | } | 1218 | } |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk) | 1221 | void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk) |
1222 | { | 1222 | { |
1223 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) | 1223 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) |
1224 | write_compacted_summaries(sbi, start_blk); | 1224 | write_compacted_summaries(sbi, start_blk); |
1225 | else | 1225 | else |
1226 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA); | 1226 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA); |
1227 | } | 1227 | } |
1228 | 1228 | ||
1229 | void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk) | 1229 | void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk) |
1230 | { | 1230 | { |
1231 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) | 1231 | if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) |
1232 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); | 1232 | write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); |
1233 | return; | 1233 | return; |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, | 1236 | int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, |
1237 | unsigned int val, int alloc) | 1237 | unsigned int val, int alloc) |
1238 | { | 1238 | { |
1239 | int i; | 1239 | int i; |
1240 | 1240 | ||
1241 | if (type == NAT_JOURNAL) { | 1241 | if (type == NAT_JOURNAL) { |
1242 | for (i = 0; i < nats_in_cursum(sum); i++) { | 1242 | for (i = 0; i < nats_in_cursum(sum); i++) { |
1243 | if (le32_to_cpu(nid_in_journal(sum, i)) == val) | 1243 | if (le32_to_cpu(nid_in_journal(sum, i)) == val) |
1244 | return i; | 1244 | return i; |
1245 | } | 1245 | } |
1246 | if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) | 1246 | if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) |
1247 | return update_nats_in_cursum(sum, 1); | 1247 | return update_nats_in_cursum(sum, 1); |
1248 | } else if (type == SIT_JOURNAL) { | 1248 | } else if (type == SIT_JOURNAL) { |
1249 | for (i = 0; i < sits_in_cursum(sum); i++) | 1249 | for (i = 0; i < sits_in_cursum(sum); i++) |
1250 | if (le32_to_cpu(segno_in_journal(sum, i)) == val) | 1250 | if (le32_to_cpu(segno_in_journal(sum, i)) == val) |
1251 | return i; | 1251 | return i; |
1252 | if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES) | 1252 | if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES) |
1253 | return update_sits_in_cursum(sum, 1); | 1253 | return update_sits_in_cursum(sum, 1); |
1254 | } | 1254 | } |
1255 | return -1; | 1255 | return -1; |
1256 | } | 1256 | } |
1257 | 1257 | ||
1258 | static struct page *get_current_sit_page(struct f2fs_sb_info *sbi, | 1258 | static struct page *get_current_sit_page(struct f2fs_sb_info *sbi, |
1259 | unsigned int segno) | 1259 | unsigned int segno) |
1260 | { | 1260 | { |
1261 | struct sit_info *sit_i = SIT_I(sbi); | 1261 | struct sit_info *sit_i = SIT_I(sbi); |
1262 | unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); | 1262 | unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); |
1263 | block_t blk_addr = sit_i->sit_base_addr + offset; | 1263 | block_t blk_addr = sit_i->sit_base_addr + offset; |
1264 | 1264 | ||
1265 | check_seg_range(sbi, segno); | 1265 | check_seg_range(sbi, segno); |
1266 | 1266 | ||
1267 | /* calculate sit block address */ | 1267 | /* calculate sit block address */ |
1268 | if (f2fs_test_bit(offset, sit_i->sit_bitmap)) | 1268 | if (f2fs_test_bit(offset, sit_i->sit_bitmap)) |
1269 | blk_addr += sit_i->sit_blocks; | 1269 | blk_addr += sit_i->sit_blocks; |
1270 | 1270 | ||
1271 | return get_meta_page(sbi, blk_addr); | 1271 | return get_meta_page(sbi, blk_addr); |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, | 1274 | static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, |
1275 | unsigned int start) | 1275 | unsigned int start) |
1276 | { | 1276 | { |
1277 | struct sit_info *sit_i = SIT_I(sbi); | 1277 | struct sit_info *sit_i = SIT_I(sbi); |
1278 | struct page *src_page, *dst_page; | 1278 | struct page *src_page, *dst_page; |
1279 | pgoff_t src_off, dst_off; | 1279 | pgoff_t src_off, dst_off; |
1280 | void *src_addr, *dst_addr; | 1280 | void *src_addr, *dst_addr; |
1281 | 1281 | ||
1282 | src_off = current_sit_addr(sbi, start); | 1282 | src_off = current_sit_addr(sbi, start); |
1283 | dst_off = next_sit_addr(sbi, src_off); | 1283 | dst_off = next_sit_addr(sbi, src_off); |
1284 | 1284 | ||
1285 | /* get current sit block page without lock */ | 1285 | /* get current sit block page without lock */ |
1286 | src_page = get_meta_page(sbi, src_off); | 1286 | src_page = get_meta_page(sbi, src_off); |
1287 | dst_page = grab_meta_page(sbi, dst_off); | 1287 | dst_page = grab_meta_page(sbi, dst_off); |
1288 | BUG_ON(PageDirty(src_page)); | 1288 | BUG_ON(PageDirty(src_page)); |
1289 | 1289 | ||
1290 | src_addr = page_address(src_page); | 1290 | src_addr = page_address(src_page); |
1291 | dst_addr = page_address(dst_page); | 1291 | dst_addr = page_address(dst_page); |
1292 | memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); | 1292 | memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); |
1293 | 1293 | ||
1294 | set_page_dirty(dst_page); | 1294 | set_page_dirty(dst_page); |
1295 | f2fs_put_page(src_page, 1); | 1295 | f2fs_put_page(src_page, 1); |
1296 | 1296 | ||
1297 | set_to_next_sit(sit_i, start); | 1297 | set_to_next_sit(sit_i, start); |
1298 | 1298 | ||
1299 | return dst_page; | 1299 | return dst_page; |
1300 | } | 1300 | } |
1301 | 1301 | ||
1302 | static bool flush_sits_in_journal(struct f2fs_sb_info *sbi) | 1302 | static bool flush_sits_in_journal(struct f2fs_sb_info *sbi) |
1303 | { | 1303 | { |
1304 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1304 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); |
1305 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1305 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1306 | int i; | 1306 | int i; |
1307 | 1307 | ||
1308 | /* | 1308 | /* |
1309 | * If the journal area in the current summary is full of sit entries, | 1309 | * If the journal area in the current summary is full of sit entries, |
1310 | * all the sit entries will be flushed. Otherwise the sit entries | 1310 | * all the sit entries will be flushed. Otherwise the sit entries |
1311 | * are not able to replace with newly hot sit entries. | 1311 | * are not able to replace with newly hot sit entries. |
1312 | */ | 1312 | */ |
1313 | if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) { | 1313 | if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) { |
1314 | for (i = sits_in_cursum(sum) - 1; i >= 0; i--) { | 1314 | for (i = sits_in_cursum(sum) - 1; i >= 0; i--) { |
1315 | unsigned int segno; | 1315 | unsigned int segno; |
1316 | segno = le32_to_cpu(segno_in_journal(sum, i)); | 1316 | segno = le32_to_cpu(segno_in_journal(sum, i)); |
1317 | __mark_sit_entry_dirty(sbi, segno); | 1317 | __mark_sit_entry_dirty(sbi, segno); |
1318 | } | 1318 | } |
1319 | update_sits_in_cursum(sum, -sits_in_cursum(sum)); | 1319 | update_sits_in_cursum(sum, -sits_in_cursum(sum)); |
1320 | return 1; | 1320 | return 1; |
1321 | } | 1321 | } |
1322 | return 0; | 1322 | return 0; |
1323 | } | 1323 | } |
1324 | 1324 | ||
1325 | /* | 1325 | /* |
1326 | * CP calls this function, which flushes SIT entries including sit_journal, | 1326 | * CP calls this function, which flushes SIT entries including sit_journal, |
1327 | * and moves prefree segs to free segs. | 1327 | * and moves prefree segs to free segs. |
1328 | */ | 1328 | */ |
1329 | void flush_sit_entries(struct f2fs_sb_info *sbi) | 1329 | void flush_sit_entries(struct f2fs_sb_info *sbi) |
1330 | { | 1330 | { |
1331 | struct sit_info *sit_i = SIT_I(sbi); | 1331 | struct sit_info *sit_i = SIT_I(sbi); |
1332 | unsigned long *bitmap = sit_i->dirty_sentries_bitmap; | 1332 | unsigned long *bitmap = sit_i->dirty_sentries_bitmap; |
1333 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1333 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); |
1334 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1334 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1335 | unsigned long nsegs = TOTAL_SEGS(sbi); | 1335 | unsigned long nsegs = TOTAL_SEGS(sbi); |
1336 | struct page *page = NULL; | 1336 | struct page *page = NULL; |
1337 | struct f2fs_sit_block *raw_sit = NULL; | 1337 | struct f2fs_sit_block *raw_sit = NULL; |
1338 | unsigned int start = 0, end = 0; | 1338 | unsigned int start = 0, end = 0; |
1339 | unsigned int segno = -1; | 1339 | unsigned int segno = -1; |
1340 | bool flushed; | 1340 | bool flushed; |
1341 | 1341 | ||
1342 | mutex_lock(&curseg->curseg_mutex); | 1342 | mutex_lock(&curseg->curseg_mutex); |
1343 | mutex_lock(&sit_i->sentry_lock); | 1343 | mutex_lock(&sit_i->sentry_lock); |
1344 | 1344 | ||
1345 | /* | 1345 | /* |
1346 | * "flushed" indicates whether sit entries in journal are flushed | 1346 | * "flushed" indicates whether sit entries in journal are flushed |
1347 | * to the SIT area or not. | 1347 | * to the SIT area or not. |
1348 | */ | 1348 | */ |
1349 | flushed = flush_sits_in_journal(sbi); | 1349 | flushed = flush_sits_in_journal(sbi); |
1350 | 1350 | ||
1351 | while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) { | 1351 | while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) { |
1352 | struct seg_entry *se = get_seg_entry(sbi, segno); | 1352 | struct seg_entry *se = get_seg_entry(sbi, segno); |
1353 | int sit_offset, offset; | 1353 | int sit_offset, offset; |
1354 | 1354 | ||
1355 | sit_offset = SIT_ENTRY_OFFSET(sit_i, segno); | 1355 | sit_offset = SIT_ENTRY_OFFSET(sit_i, segno); |
1356 | 1356 | ||
1357 | if (flushed) | 1357 | if (flushed) |
1358 | goto to_sit_page; | 1358 | goto to_sit_page; |
1359 | 1359 | ||
1360 | offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1); | 1360 | offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1); |
1361 | if (offset >= 0) { | 1361 | if (offset >= 0) { |
1362 | segno_in_journal(sum, offset) = cpu_to_le32(segno); | 1362 | segno_in_journal(sum, offset) = cpu_to_le32(segno); |
1363 | seg_info_to_raw_sit(se, &sit_in_journal(sum, offset)); | 1363 | seg_info_to_raw_sit(se, &sit_in_journal(sum, offset)); |
1364 | goto flush_done; | 1364 | goto flush_done; |
1365 | } | 1365 | } |
1366 | to_sit_page: | 1366 | to_sit_page: |
1367 | if (!page || (start > segno) || (segno > end)) { | 1367 | if (!page || (start > segno) || (segno > end)) { |
1368 | if (page) { | 1368 | if (page) { |
1369 | f2fs_put_page(page, 1); | 1369 | f2fs_put_page(page, 1); |
1370 | page = NULL; | 1370 | page = NULL; |
1371 | } | 1371 | } |
1372 | 1372 | ||
1373 | start = START_SEGNO(sit_i, segno); | 1373 | start = START_SEGNO(sit_i, segno); |
1374 | end = start + SIT_ENTRY_PER_BLOCK - 1; | 1374 | end = start + SIT_ENTRY_PER_BLOCK - 1; |
1375 | 1375 | ||
1376 | /* read sit block that will be updated */ | 1376 | /* read sit block that will be updated */ |
1377 | page = get_next_sit_page(sbi, start); | 1377 | page = get_next_sit_page(sbi, start); |
1378 | raw_sit = page_address(page); | 1378 | raw_sit = page_address(page); |
1379 | } | 1379 | } |
1380 | 1380 | ||
1381 | /* udpate entry in SIT block */ | 1381 | /* udpate entry in SIT block */ |
1382 | seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]); | 1382 | seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]); |
1383 | flush_done: | 1383 | flush_done: |
1384 | __clear_bit(segno, bitmap); | 1384 | __clear_bit(segno, bitmap); |
1385 | sit_i->dirty_sentries--; | 1385 | sit_i->dirty_sentries--; |
1386 | } | 1386 | } |
1387 | mutex_unlock(&sit_i->sentry_lock); | 1387 | mutex_unlock(&sit_i->sentry_lock); |
1388 | mutex_unlock(&curseg->curseg_mutex); | 1388 | mutex_unlock(&curseg->curseg_mutex); |
1389 | 1389 | ||
1390 | /* writeout last modified SIT block */ | 1390 | /* writeout last modified SIT block */ |
1391 | f2fs_put_page(page, 1); | 1391 | f2fs_put_page(page, 1); |
1392 | 1392 | ||
1393 | set_prefree_as_free_segments(sbi); | 1393 | set_prefree_as_free_segments(sbi); |
1394 | } | 1394 | } |
1395 | 1395 | ||
1396 | static int build_sit_info(struct f2fs_sb_info *sbi) | 1396 | static int build_sit_info(struct f2fs_sb_info *sbi) |
1397 | { | 1397 | { |
1398 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 1398 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
1399 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 1399 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
1400 | struct sit_info *sit_i; | 1400 | struct sit_info *sit_i; |
1401 | unsigned int sit_segs, start; | 1401 | unsigned int sit_segs, start; |
1402 | char *src_bitmap, *dst_bitmap; | 1402 | char *src_bitmap, *dst_bitmap; |
1403 | unsigned int bitmap_size; | 1403 | unsigned int bitmap_size; |
1404 | 1404 | ||
1405 | /* allocate memory for SIT information */ | 1405 | /* allocate memory for SIT information */ |
1406 | sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL); | 1406 | sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL); |
1407 | if (!sit_i) | 1407 | if (!sit_i) |
1408 | return -ENOMEM; | 1408 | return -ENOMEM; |
1409 | 1409 | ||
1410 | SM_I(sbi)->sit_info = sit_i; | 1410 | SM_I(sbi)->sit_info = sit_i; |
1411 | 1411 | ||
1412 | sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry)); | 1412 | sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry)); |
1413 | if (!sit_i->sentries) | 1413 | if (!sit_i->sentries) |
1414 | return -ENOMEM; | 1414 | return -ENOMEM; |
1415 | 1415 | ||
1416 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); | 1416 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); |
1417 | sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL); | 1417 | sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL); |
1418 | if (!sit_i->dirty_sentries_bitmap) | 1418 | if (!sit_i->dirty_sentries_bitmap) |
1419 | return -ENOMEM; | 1419 | return -ENOMEM; |
1420 | 1420 | ||
1421 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { | 1421 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { |
1422 | sit_i->sentries[start].cur_valid_map | 1422 | sit_i->sentries[start].cur_valid_map |
1423 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); | 1423 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); |
1424 | sit_i->sentries[start].ckpt_valid_map | 1424 | sit_i->sentries[start].ckpt_valid_map |
1425 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); | 1425 | = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); |
1426 | if (!sit_i->sentries[start].cur_valid_map | 1426 | if (!sit_i->sentries[start].cur_valid_map |
1427 | || !sit_i->sentries[start].ckpt_valid_map) | 1427 | || !sit_i->sentries[start].ckpt_valid_map) |
1428 | return -ENOMEM; | 1428 | return -ENOMEM; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | if (sbi->segs_per_sec > 1) { | 1431 | if (sbi->segs_per_sec > 1) { |
1432 | sit_i->sec_entries = vzalloc(TOTAL_SECS(sbi) * | 1432 | sit_i->sec_entries = vzalloc(TOTAL_SECS(sbi) * |
1433 | sizeof(struct sec_entry)); | 1433 | sizeof(struct sec_entry)); |
1434 | if (!sit_i->sec_entries) | 1434 | if (!sit_i->sec_entries) |
1435 | return -ENOMEM; | 1435 | return -ENOMEM; |
1436 | } | 1436 | } |
1437 | 1437 | ||
1438 | /* get information related with SIT */ | 1438 | /* get information related with SIT */ |
1439 | sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1; | 1439 | sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1; |
1440 | 1440 | ||
1441 | /* setup SIT bitmap from ckeckpoint pack */ | 1441 | /* setup SIT bitmap from ckeckpoint pack */ |
1442 | bitmap_size = __bitmap_size(sbi, SIT_BITMAP); | 1442 | bitmap_size = __bitmap_size(sbi, SIT_BITMAP); |
1443 | src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); | 1443 | src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); |
1444 | 1444 | ||
1445 | dst_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); | 1445 | dst_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); |
1446 | if (!dst_bitmap) | 1446 | if (!dst_bitmap) |
1447 | return -ENOMEM; | 1447 | return -ENOMEM; |
1448 | 1448 | ||
1449 | /* init SIT information */ | 1449 | /* init SIT information */ |
1450 | sit_i->s_ops = &default_salloc_ops; | 1450 | sit_i->s_ops = &default_salloc_ops; |
1451 | 1451 | ||
1452 | sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); | 1452 | sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); |
1453 | sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; | 1453 | sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; |
1454 | sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count); | 1454 | sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count); |
1455 | sit_i->sit_bitmap = dst_bitmap; | 1455 | sit_i->sit_bitmap = dst_bitmap; |
1456 | sit_i->bitmap_size = bitmap_size; | 1456 | sit_i->bitmap_size = bitmap_size; |
1457 | sit_i->dirty_sentries = 0; | 1457 | sit_i->dirty_sentries = 0; |
1458 | sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; | 1458 | sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; |
1459 | sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time); | 1459 | sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time); |
1460 | sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec; | 1460 | sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec; |
1461 | mutex_init(&sit_i->sentry_lock); | 1461 | mutex_init(&sit_i->sentry_lock); |
1462 | return 0; | 1462 | return 0; |
1463 | } | 1463 | } |
1464 | 1464 | ||
1465 | static int build_free_segmap(struct f2fs_sb_info *sbi) | 1465 | static int build_free_segmap(struct f2fs_sb_info *sbi) |
1466 | { | 1466 | { |
1467 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 1467 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
1468 | struct free_segmap_info *free_i; | 1468 | struct free_segmap_info *free_i; |
1469 | unsigned int bitmap_size, sec_bitmap_size; | 1469 | unsigned int bitmap_size, sec_bitmap_size; |
1470 | 1470 | ||
1471 | /* allocate memory for free segmap information */ | 1471 | /* allocate memory for free segmap information */ |
1472 | free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL); | 1472 | free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL); |
1473 | if (!free_i) | 1473 | if (!free_i) |
1474 | return -ENOMEM; | 1474 | return -ENOMEM; |
1475 | 1475 | ||
1476 | SM_I(sbi)->free_info = free_i; | 1476 | SM_I(sbi)->free_info = free_i; |
1477 | 1477 | ||
1478 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); | 1478 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); |
1479 | free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL); | 1479 | free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL); |
1480 | if (!free_i->free_segmap) | 1480 | if (!free_i->free_segmap) |
1481 | return -ENOMEM; | 1481 | return -ENOMEM; |
1482 | 1482 | ||
1483 | sec_bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); | 1483 | sec_bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); |
1484 | free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL); | 1484 | free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL); |
1485 | if (!free_i->free_secmap) | 1485 | if (!free_i->free_secmap) |
1486 | return -ENOMEM; | 1486 | return -ENOMEM; |
1487 | 1487 | ||
1488 | /* set all segments as dirty temporarily */ | 1488 | /* set all segments as dirty temporarily */ |
1489 | memset(free_i->free_segmap, 0xff, bitmap_size); | 1489 | memset(free_i->free_segmap, 0xff, bitmap_size); |
1490 | memset(free_i->free_secmap, 0xff, sec_bitmap_size); | 1490 | memset(free_i->free_secmap, 0xff, sec_bitmap_size); |
1491 | 1491 | ||
1492 | /* init free segmap information */ | 1492 | /* init free segmap information */ |
1493 | free_i->start_segno = | 1493 | free_i->start_segno = |
1494 | (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr); | 1494 | (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr); |
1495 | free_i->free_segments = 0; | 1495 | free_i->free_segments = 0; |
1496 | free_i->free_sections = 0; | 1496 | free_i->free_sections = 0; |
1497 | rwlock_init(&free_i->segmap_lock); | 1497 | rwlock_init(&free_i->segmap_lock); |
1498 | return 0; | 1498 | return 0; |
1499 | } | 1499 | } |
1500 | 1500 | ||
1501 | static int build_curseg(struct f2fs_sb_info *sbi) | 1501 | static int build_curseg(struct f2fs_sb_info *sbi) |
1502 | { | 1502 | { |
1503 | struct curseg_info *array; | 1503 | struct curseg_info *array; |
1504 | int i; | 1504 | int i; |
1505 | 1505 | ||
1506 | array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL); | 1506 | array = kzalloc(sizeof(*array) * NR_CURSEG_TYPE, GFP_KERNEL); |
1507 | if (!array) | 1507 | if (!array) |
1508 | return -ENOMEM; | 1508 | return -ENOMEM; |
1509 | 1509 | ||
1510 | SM_I(sbi)->curseg_array = array; | 1510 | SM_I(sbi)->curseg_array = array; |
1511 | 1511 | ||
1512 | for (i = 0; i < NR_CURSEG_TYPE; i++) { | 1512 | for (i = 0; i < NR_CURSEG_TYPE; i++) { |
1513 | mutex_init(&array[i].curseg_mutex); | 1513 | mutex_init(&array[i].curseg_mutex); |
1514 | array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL); | 1514 | array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL); |
1515 | if (!array[i].sum_blk) | 1515 | if (!array[i].sum_blk) |
1516 | return -ENOMEM; | 1516 | return -ENOMEM; |
1517 | array[i].segno = NULL_SEGNO; | 1517 | array[i].segno = NULL_SEGNO; |
1518 | array[i].next_blkoff = 0; | 1518 | array[i].next_blkoff = 0; |
1519 | } | 1519 | } |
1520 | return restore_curseg_summaries(sbi); | 1520 | return restore_curseg_summaries(sbi); |
1521 | } | 1521 | } |
1522 | 1522 | ||
1523 | static void build_sit_entries(struct f2fs_sb_info *sbi) | 1523 | static void build_sit_entries(struct f2fs_sb_info *sbi) |
1524 | { | 1524 | { |
1525 | struct sit_info *sit_i = SIT_I(sbi); | 1525 | struct sit_info *sit_i = SIT_I(sbi); |
1526 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); | 1526 | struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); |
1527 | struct f2fs_summary_block *sum = curseg->sum_blk; | 1527 | struct f2fs_summary_block *sum = curseg->sum_blk; |
1528 | unsigned int start; | 1528 | unsigned int start; |
1529 | 1529 | ||
1530 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { | 1530 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { |
1531 | struct seg_entry *se = &sit_i->sentries[start]; | 1531 | struct seg_entry *se = &sit_i->sentries[start]; |
1532 | struct f2fs_sit_block *sit_blk; | 1532 | struct f2fs_sit_block *sit_blk; |
1533 | struct f2fs_sit_entry sit; | 1533 | struct f2fs_sit_entry sit; |
1534 | struct page *page; | 1534 | struct page *page; |
1535 | int i; | 1535 | int i; |
1536 | 1536 | ||
1537 | mutex_lock(&curseg->curseg_mutex); | 1537 | mutex_lock(&curseg->curseg_mutex); |
1538 | for (i = 0; i < sits_in_cursum(sum); i++) { | 1538 | for (i = 0; i < sits_in_cursum(sum); i++) { |
1539 | if (le32_to_cpu(segno_in_journal(sum, i)) == start) { | 1539 | if (le32_to_cpu(segno_in_journal(sum, i)) == start) { |
1540 | sit = sit_in_journal(sum, i); | 1540 | sit = sit_in_journal(sum, i); |
1541 | mutex_unlock(&curseg->curseg_mutex); | 1541 | mutex_unlock(&curseg->curseg_mutex); |
1542 | goto got_it; | 1542 | goto got_it; |
1543 | } | 1543 | } |
1544 | } | 1544 | } |
1545 | mutex_unlock(&curseg->curseg_mutex); | 1545 | mutex_unlock(&curseg->curseg_mutex); |
1546 | page = get_current_sit_page(sbi, start); | 1546 | page = get_current_sit_page(sbi, start); |
1547 | sit_blk = (struct f2fs_sit_block *)page_address(page); | 1547 | sit_blk = (struct f2fs_sit_block *)page_address(page); |
1548 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; | 1548 | sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; |
1549 | f2fs_put_page(page, 1); | 1549 | f2fs_put_page(page, 1); |
1550 | got_it: | 1550 | got_it: |
1551 | check_block_count(sbi, start, &sit); | 1551 | check_block_count(sbi, start, &sit); |
1552 | seg_info_from_raw_sit(se, &sit); | 1552 | seg_info_from_raw_sit(se, &sit); |
1553 | if (sbi->segs_per_sec > 1) { | 1553 | if (sbi->segs_per_sec > 1) { |
1554 | struct sec_entry *e = get_sec_entry(sbi, start); | 1554 | struct sec_entry *e = get_sec_entry(sbi, start); |
1555 | e->valid_blocks += se->valid_blocks; | 1555 | e->valid_blocks += se->valid_blocks; |
1556 | } | 1556 | } |
1557 | } | 1557 | } |
1558 | } | 1558 | } |
1559 | 1559 | ||
1560 | static void init_free_segmap(struct f2fs_sb_info *sbi) | 1560 | static void init_free_segmap(struct f2fs_sb_info *sbi) |
1561 | { | 1561 | { |
1562 | unsigned int start; | 1562 | unsigned int start; |
1563 | int type; | 1563 | int type; |
1564 | 1564 | ||
1565 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { | 1565 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { |
1566 | struct seg_entry *sentry = get_seg_entry(sbi, start); | 1566 | struct seg_entry *sentry = get_seg_entry(sbi, start); |
1567 | if (!sentry->valid_blocks) | 1567 | if (!sentry->valid_blocks) |
1568 | __set_free(sbi, start); | 1568 | __set_free(sbi, start); |
1569 | } | 1569 | } |
1570 | 1570 | ||
1571 | /* set use the current segments */ | 1571 | /* set use the current segments */ |
1572 | for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) { | 1572 | for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) { |
1573 | struct curseg_info *curseg_t = CURSEG_I(sbi, type); | 1573 | struct curseg_info *curseg_t = CURSEG_I(sbi, type); |
1574 | __set_test_and_inuse(sbi, curseg_t->segno); | 1574 | __set_test_and_inuse(sbi, curseg_t->segno); |
1575 | } | 1575 | } |
1576 | } | 1576 | } |
1577 | 1577 | ||
1578 | static void init_dirty_segmap(struct f2fs_sb_info *sbi) | 1578 | static void init_dirty_segmap(struct f2fs_sb_info *sbi) |
1579 | { | 1579 | { |
1580 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1580 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1581 | struct free_segmap_info *free_i = FREE_I(sbi); | 1581 | struct free_segmap_info *free_i = FREE_I(sbi); |
1582 | unsigned int segno = 0, offset = 0; | 1582 | unsigned int segno = 0, offset = 0; |
1583 | unsigned short valid_blocks; | 1583 | unsigned short valid_blocks; |
1584 | 1584 | ||
1585 | while (segno < TOTAL_SEGS(sbi)) { | 1585 | while (segno < TOTAL_SEGS(sbi)) { |
1586 | /* find dirty segment based on free segmap */ | 1586 | /* find dirty segment based on free segmap */ |
1587 | segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset); | 1587 | segno = find_next_inuse(free_i, TOTAL_SEGS(sbi), offset); |
1588 | if (segno >= TOTAL_SEGS(sbi)) | 1588 | if (segno >= TOTAL_SEGS(sbi)) |
1589 | break; | 1589 | break; |
1590 | offset = segno + 1; | 1590 | offset = segno + 1; |
1591 | valid_blocks = get_valid_blocks(sbi, segno, 0); | 1591 | valid_blocks = get_valid_blocks(sbi, segno, 0); |
1592 | if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks) | 1592 | if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks) |
1593 | continue; | 1593 | continue; |
1594 | mutex_lock(&dirty_i->seglist_lock); | 1594 | mutex_lock(&dirty_i->seglist_lock); |
1595 | __locate_dirty_segment(sbi, segno, DIRTY); | 1595 | __locate_dirty_segment(sbi, segno, DIRTY); |
1596 | mutex_unlock(&dirty_i->seglist_lock); | 1596 | mutex_unlock(&dirty_i->seglist_lock); |
1597 | } | 1597 | } |
1598 | } | 1598 | } |
1599 | 1599 | ||
1600 | static int init_victim_secmap(struct f2fs_sb_info *sbi) | 1600 | static int init_victim_secmap(struct f2fs_sb_info *sbi) |
1601 | { | 1601 | { |
1602 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1602 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1603 | unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); | 1603 | unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); |
1604 | 1604 | ||
1605 | dirty_i->victim_secmap = kzalloc(bitmap_size, GFP_KERNEL); | 1605 | dirty_i->victim_secmap = kzalloc(bitmap_size, GFP_KERNEL); |
1606 | if (!dirty_i->victim_secmap) | 1606 | if (!dirty_i->victim_secmap) |
1607 | return -ENOMEM; | 1607 | return -ENOMEM; |
1608 | return 0; | 1608 | return 0; |
1609 | } | 1609 | } |
1610 | 1610 | ||
1611 | static int build_dirty_segmap(struct f2fs_sb_info *sbi) | 1611 | static int build_dirty_segmap(struct f2fs_sb_info *sbi) |
1612 | { | 1612 | { |
1613 | struct dirty_seglist_info *dirty_i; | 1613 | struct dirty_seglist_info *dirty_i; |
1614 | unsigned int bitmap_size, i; | 1614 | unsigned int bitmap_size, i; |
1615 | 1615 | ||
1616 | /* allocate memory for dirty segments list information */ | 1616 | /* allocate memory for dirty segments list information */ |
1617 | dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL); | 1617 | dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL); |
1618 | if (!dirty_i) | 1618 | if (!dirty_i) |
1619 | return -ENOMEM; | 1619 | return -ENOMEM; |
1620 | 1620 | ||
1621 | SM_I(sbi)->dirty_info = dirty_i; | 1621 | SM_I(sbi)->dirty_info = dirty_i; |
1622 | mutex_init(&dirty_i->seglist_lock); | 1622 | mutex_init(&dirty_i->seglist_lock); |
1623 | 1623 | ||
1624 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); | 1624 | bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); |
1625 | 1625 | ||
1626 | for (i = 0; i < NR_DIRTY_TYPE; i++) { | 1626 | for (i = 0; i < NR_DIRTY_TYPE; i++) { |
1627 | dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL); | 1627 | dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL); |
1628 | if (!dirty_i->dirty_segmap[i]) | 1628 | if (!dirty_i->dirty_segmap[i]) |
1629 | return -ENOMEM; | 1629 | return -ENOMEM; |
1630 | } | 1630 | } |
1631 | 1631 | ||
1632 | init_dirty_segmap(sbi); | 1632 | init_dirty_segmap(sbi); |
1633 | return init_victim_secmap(sbi); | 1633 | return init_victim_secmap(sbi); |
1634 | } | 1634 | } |
1635 | 1635 | ||
1636 | /* | 1636 | /* |
1637 | * Update min, max modified time for cost-benefit GC algorithm | 1637 | * Update min, max modified time for cost-benefit GC algorithm |
1638 | */ | 1638 | */ |
1639 | static void init_min_max_mtime(struct f2fs_sb_info *sbi) | 1639 | static void init_min_max_mtime(struct f2fs_sb_info *sbi) |
1640 | { | 1640 | { |
1641 | struct sit_info *sit_i = SIT_I(sbi); | 1641 | struct sit_info *sit_i = SIT_I(sbi); |
1642 | unsigned int segno; | 1642 | unsigned int segno; |
1643 | 1643 | ||
1644 | mutex_lock(&sit_i->sentry_lock); | 1644 | mutex_lock(&sit_i->sentry_lock); |
1645 | 1645 | ||
1646 | sit_i->min_mtime = LLONG_MAX; | 1646 | sit_i->min_mtime = LLONG_MAX; |
1647 | 1647 | ||
1648 | for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) { | 1648 | for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) { |
1649 | unsigned int i; | 1649 | unsigned int i; |
1650 | unsigned long long mtime = 0; | 1650 | unsigned long long mtime = 0; |
1651 | 1651 | ||
1652 | for (i = 0; i < sbi->segs_per_sec; i++) | 1652 | for (i = 0; i < sbi->segs_per_sec; i++) |
1653 | mtime += get_seg_entry(sbi, segno + i)->mtime; | 1653 | mtime += get_seg_entry(sbi, segno + i)->mtime; |
1654 | 1654 | ||
1655 | mtime = div_u64(mtime, sbi->segs_per_sec); | 1655 | mtime = div_u64(mtime, sbi->segs_per_sec); |
1656 | 1656 | ||
1657 | if (sit_i->min_mtime > mtime) | 1657 | if (sit_i->min_mtime > mtime) |
1658 | sit_i->min_mtime = mtime; | 1658 | sit_i->min_mtime = mtime; |
1659 | } | 1659 | } |
1660 | sit_i->max_mtime = get_mtime(sbi); | 1660 | sit_i->max_mtime = get_mtime(sbi); |
1661 | mutex_unlock(&sit_i->sentry_lock); | 1661 | mutex_unlock(&sit_i->sentry_lock); |
1662 | } | 1662 | } |
1663 | 1663 | ||
1664 | int build_segment_manager(struct f2fs_sb_info *sbi) | 1664 | int build_segment_manager(struct f2fs_sb_info *sbi) |
1665 | { | 1665 | { |
1666 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); | 1666 | struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); |
1667 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); | 1667 | struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); |
1668 | struct f2fs_sm_info *sm_info; | 1668 | struct f2fs_sm_info *sm_info; |
1669 | int err; | 1669 | int err; |
1670 | 1670 | ||
1671 | sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL); | 1671 | sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL); |
1672 | if (!sm_info) | 1672 | if (!sm_info) |
1673 | return -ENOMEM; | 1673 | return -ENOMEM; |
1674 | 1674 | ||
1675 | /* init sm info */ | 1675 | /* init sm info */ |
1676 | sbi->sm_info = sm_info; | 1676 | sbi->sm_info = sm_info; |
1677 | INIT_LIST_HEAD(&sm_info->wblist_head); | 1677 | INIT_LIST_HEAD(&sm_info->wblist_head); |
1678 | spin_lock_init(&sm_info->wblist_lock); | 1678 | spin_lock_init(&sm_info->wblist_lock); |
1679 | sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); | 1679 | sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); |
1680 | sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr); | 1680 | sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr); |
1681 | sm_info->segment_count = le32_to_cpu(raw_super->segment_count); | 1681 | sm_info->segment_count = le32_to_cpu(raw_super->segment_count); |
1682 | sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count); | 1682 | sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count); |
1683 | sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); | 1683 | sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); |
1684 | sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main); | 1684 | sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main); |
1685 | sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); | 1685 | sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); |
1686 | 1686 | ||
1687 | err = build_sit_info(sbi); | 1687 | err = build_sit_info(sbi); |
1688 | if (err) | 1688 | if (err) |
1689 | return err; | 1689 | return err; |
1690 | err = build_free_segmap(sbi); | 1690 | err = build_free_segmap(sbi); |
1691 | if (err) | 1691 | if (err) |
1692 | return err; | 1692 | return err; |
1693 | err = build_curseg(sbi); | 1693 | err = build_curseg(sbi); |
1694 | if (err) | 1694 | if (err) |
1695 | return err; | 1695 | return err; |
1696 | 1696 | ||
1697 | /* reinit free segmap based on SIT */ | 1697 | /* reinit free segmap based on SIT */ |
1698 | build_sit_entries(sbi); | 1698 | build_sit_entries(sbi); |
1699 | 1699 | ||
1700 | init_free_segmap(sbi); | 1700 | init_free_segmap(sbi); |
1701 | err = build_dirty_segmap(sbi); | 1701 | err = build_dirty_segmap(sbi); |
1702 | if (err) | 1702 | if (err) |
1703 | return err; | 1703 | return err; |
1704 | 1704 | ||
1705 | init_min_max_mtime(sbi); | 1705 | init_min_max_mtime(sbi); |
1706 | return 0; | 1706 | return 0; |
1707 | } | 1707 | } |
1708 | 1708 | ||
1709 | static void discard_dirty_segmap(struct f2fs_sb_info *sbi, | 1709 | static void discard_dirty_segmap(struct f2fs_sb_info *sbi, |
1710 | enum dirty_type dirty_type) | 1710 | enum dirty_type dirty_type) |
1711 | { | 1711 | { |
1712 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1712 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1713 | 1713 | ||
1714 | mutex_lock(&dirty_i->seglist_lock); | 1714 | mutex_lock(&dirty_i->seglist_lock); |
1715 | kfree(dirty_i->dirty_segmap[dirty_type]); | 1715 | kfree(dirty_i->dirty_segmap[dirty_type]); |
1716 | dirty_i->nr_dirty[dirty_type] = 0; | 1716 | dirty_i->nr_dirty[dirty_type] = 0; |
1717 | mutex_unlock(&dirty_i->seglist_lock); | 1717 | mutex_unlock(&dirty_i->seglist_lock); |
1718 | } | 1718 | } |
1719 | 1719 | ||
1720 | static void destroy_victim_secmap(struct f2fs_sb_info *sbi) | 1720 | static void destroy_victim_secmap(struct f2fs_sb_info *sbi) |
1721 | { | 1721 | { |
1722 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1722 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1723 | kfree(dirty_i->victim_secmap); | 1723 | kfree(dirty_i->victim_secmap); |
1724 | } | 1724 | } |
1725 | 1725 | ||
1726 | static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) | 1726 | static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) |
1727 | { | 1727 | { |
1728 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); | 1728 | struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); |
1729 | int i; | 1729 | int i; |
1730 | 1730 | ||
1731 | if (!dirty_i) | 1731 | if (!dirty_i) |
1732 | return; | 1732 | return; |
1733 | 1733 | ||
1734 | /* discard pre-free/dirty segments list */ | 1734 | /* discard pre-free/dirty segments list */ |
1735 | for (i = 0; i < NR_DIRTY_TYPE; i++) | 1735 | for (i = 0; i < NR_DIRTY_TYPE; i++) |
1736 | discard_dirty_segmap(sbi, i); | 1736 | discard_dirty_segmap(sbi, i); |
1737 | 1737 | ||
1738 | destroy_victim_secmap(sbi); | 1738 | destroy_victim_secmap(sbi); |
1739 | SM_I(sbi)->dirty_info = NULL; | 1739 | SM_I(sbi)->dirty_info = NULL; |
1740 | kfree(dirty_i); | 1740 | kfree(dirty_i); |
1741 | } | 1741 | } |
1742 | 1742 | ||
1743 | static void destroy_curseg(struct f2fs_sb_info *sbi) | 1743 | static void destroy_curseg(struct f2fs_sb_info *sbi) |
1744 | { | 1744 | { |
1745 | struct curseg_info *array = SM_I(sbi)->curseg_array; | 1745 | struct curseg_info *array = SM_I(sbi)->curseg_array; |
1746 | int i; | 1746 | int i; |
1747 | 1747 | ||
1748 | if (!array) | 1748 | if (!array) |
1749 | return; | 1749 | return; |
1750 | SM_I(sbi)->curseg_array = NULL; | 1750 | SM_I(sbi)->curseg_array = NULL; |
1751 | for (i = 0; i < NR_CURSEG_TYPE; i++) | 1751 | for (i = 0; i < NR_CURSEG_TYPE; i++) |
1752 | kfree(array[i].sum_blk); | 1752 | kfree(array[i].sum_blk); |
1753 | kfree(array); | 1753 | kfree(array); |
1754 | } | 1754 | } |
1755 | 1755 | ||
1756 | static void destroy_free_segmap(struct f2fs_sb_info *sbi) | 1756 | static void destroy_free_segmap(struct f2fs_sb_info *sbi) |
1757 | { | 1757 | { |
1758 | struct free_segmap_info *free_i = SM_I(sbi)->free_info; | 1758 | struct free_segmap_info *free_i = SM_I(sbi)->free_info; |
1759 | if (!free_i) | 1759 | if (!free_i) |
1760 | return; | 1760 | return; |
1761 | SM_I(sbi)->free_info = NULL; | 1761 | SM_I(sbi)->free_info = NULL; |
1762 | kfree(free_i->free_segmap); | 1762 | kfree(free_i->free_segmap); |
1763 | kfree(free_i->free_secmap); | 1763 | kfree(free_i->free_secmap); |
1764 | kfree(free_i); | 1764 | kfree(free_i); |
1765 | } | 1765 | } |
1766 | 1766 | ||
1767 | static void destroy_sit_info(struct f2fs_sb_info *sbi) | 1767 | static void destroy_sit_info(struct f2fs_sb_info *sbi) |
1768 | { | 1768 | { |
1769 | struct sit_info *sit_i = SIT_I(sbi); | 1769 | struct sit_info *sit_i = SIT_I(sbi); |
1770 | unsigned int start; | 1770 | unsigned int start; |
1771 | 1771 | ||
1772 | if (!sit_i) | 1772 | if (!sit_i) |
1773 | return; | 1773 | return; |
1774 | 1774 | ||
1775 | if (sit_i->sentries) { | 1775 | if (sit_i->sentries) { |
1776 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { | 1776 | for (start = 0; start < TOTAL_SEGS(sbi); start++) { |
1777 | kfree(sit_i->sentries[start].cur_valid_map); | 1777 | kfree(sit_i->sentries[start].cur_valid_map); |
1778 | kfree(sit_i->sentries[start].ckpt_valid_map); | 1778 | kfree(sit_i->sentries[start].ckpt_valid_map); |
1779 | } | 1779 | } |
1780 | } | 1780 | } |
1781 | vfree(sit_i->sentries); | 1781 | vfree(sit_i->sentries); |
1782 | vfree(sit_i->sec_entries); | 1782 | vfree(sit_i->sec_entries); |
1783 | kfree(sit_i->dirty_sentries_bitmap); | 1783 | kfree(sit_i->dirty_sentries_bitmap); |
1784 | 1784 | ||
1785 | SM_I(sbi)->sit_info = NULL; | 1785 | SM_I(sbi)->sit_info = NULL; |
1786 | kfree(sit_i->sit_bitmap); | 1786 | kfree(sit_i->sit_bitmap); |
1787 | kfree(sit_i); | 1787 | kfree(sit_i); |
1788 | } | 1788 | } |
1789 | 1789 | ||
1790 | void destroy_segment_manager(struct f2fs_sb_info *sbi) | 1790 | void destroy_segment_manager(struct f2fs_sb_info *sbi) |
1791 | { | 1791 | { |
1792 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 1792 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
1793 | destroy_dirty_segmap(sbi); | 1793 | destroy_dirty_segmap(sbi); |
1794 | destroy_curseg(sbi); | 1794 | destroy_curseg(sbi); |
1795 | destroy_free_segmap(sbi); | 1795 | destroy_free_segmap(sbi); |
1796 | destroy_sit_info(sbi); | 1796 | destroy_sit_info(sbi); |
1797 | sbi->sm_info = NULL; | 1797 | sbi->sm_info = NULL; |
1798 | kfree(sm_info); | 1798 | kfree(sm_info); |
1799 | } | 1799 | } |
1800 | 1800 |
fs/f2fs/segment.h
1 | /* | 1 | /* |
2 | * fs/f2fs/segment.h | 2 | * fs/f2fs/segment.h |
3 | * | 3 | * |
4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. | 4 | * Copyright (c) 2012 Samsung Electronics Co., Ltd. |
5 | * http://www.samsung.com/ | 5 | * http://www.samsung.com/ |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License version 2 as | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | #include <linux/blkdev.h> | ||
12 | |||
11 | /* constant macro */ | 13 | /* constant macro */ |
12 | #define NULL_SEGNO ((unsigned int)(~0)) | 14 | #define NULL_SEGNO ((unsigned int)(~0)) |
13 | #define NULL_SECNO ((unsigned int)(~0)) | 15 | #define NULL_SECNO ((unsigned int)(~0)) |
14 | 16 | ||
15 | /* L: Logical segment # in volume, R: Relative segment # in main area */ | 17 | /* L: Logical segment # in volume, R: Relative segment # in main area */ |
16 | #define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno) | 18 | #define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno) |
17 | #define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno) | 19 | #define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno) |
18 | 20 | ||
19 | #define IS_DATASEG(t) \ | 21 | #define IS_DATASEG(t) \ |
20 | ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) || \ | 22 | ((t == CURSEG_HOT_DATA) || (t == CURSEG_COLD_DATA) || \ |
21 | (t == CURSEG_WARM_DATA)) | 23 | (t == CURSEG_WARM_DATA)) |
22 | 24 | ||
23 | #define IS_NODESEG(t) \ | 25 | #define IS_NODESEG(t) \ |
24 | ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) || \ | 26 | ((t == CURSEG_HOT_NODE) || (t == CURSEG_COLD_NODE) || \ |
25 | (t == CURSEG_WARM_NODE)) | 27 | (t == CURSEG_WARM_NODE)) |
26 | 28 | ||
27 | #define IS_CURSEG(sbi, seg) \ | 29 | #define IS_CURSEG(sbi, seg) \ |
28 | ((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \ | 30 | ((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \ |
29 | (seg == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \ | 31 | (seg == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \ |
30 | (seg == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \ | 32 | (seg == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \ |
31 | (seg == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \ | 33 | (seg == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \ |
32 | (seg == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \ | 34 | (seg == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \ |
33 | (seg == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno)) | 35 | (seg == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno)) |
34 | 36 | ||
35 | #define IS_CURSEC(sbi, secno) \ | 37 | #define IS_CURSEC(sbi, secno) \ |
36 | ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \ | 38 | ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \ |
37 | sbi->segs_per_sec) || \ | 39 | sbi->segs_per_sec) || \ |
38 | (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \ | 40 | (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \ |
39 | sbi->segs_per_sec) || \ | 41 | sbi->segs_per_sec) || \ |
40 | (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \ | 42 | (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \ |
41 | sbi->segs_per_sec) || \ | 43 | sbi->segs_per_sec) || \ |
42 | (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \ | 44 | (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \ |
43 | sbi->segs_per_sec) || \ | 45 | sbi->segs_per_sec) || \ |
44 | (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \ | 46 | (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \ |
45 | sbi->segs_per_sec) || \ | 47 | sbi->segs_per_sec) || \ |
46 | (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \ | 48 | (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \ |
47 | sbi->segs_per_sec)) \ | 49 | sbi->segs_per_sec)) \ |
48 | 50 | ||
49 | #define START_BLOCK(sbi, segno) \ | 51 | #define START_BLOCK(sbi, segno) \ |
50 | (SM_I(sbi)->seg0_blkaddr + \ | 52 | (SM_I(sbi)->seg0_blkaddr + \ |
51 | (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg)) | 53 | (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg)) |
52 | #define NEXT_FREE_BLKADDR(sbi, curseg) \ | 54 | #define NEXT_FREE_BLKADDR(sbi, curseg) \ |
53 | (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff) | 55 | (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff) |
54 | 56 | ||
55 | #define MAIN_BASE_BLOCK(sbi) (SM_I(sbi)->main_blkaddr) | 57 | #define MAIN_BASE_BLOCK(sbi) (SM_I(sbi)->main_blkaddr) |
56 | 58 | ||
57 | #define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) \ | 59 | #define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) \ |
58 | ((blk_addr) - SM_I(sbi)->seg0_blkaddr) | 60 | ((blk_addr) - SM_I(sbi)->seg0_blkaddr) |
59 | #define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \ | 61 | #define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \ |
60 | (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg) | 62 | (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg) |
61 | #define GET_SEGNO(sbi, blk_addr) \ | 63 | #define GET_SEGNO(sbi, blk_addr) \ |
62 | (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ? \ | 64 | (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ? \ |
63 | NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \ | 65 | NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \ |
64 | GET_SEGNO_FROM_SEG0(sbi, blk_addr))) | 66 | GET_SEGNO_FROM_SEG0(sbi, blk_addr))) |
65 | #define GET_SECNO(sbi, segno) \ | 67 | #define GET_SECNO(sbi, segno) \ |
66 | ((segno) / sbi->segs_per_sec) | 68 | ((segno) / sbi->segs_per_sec) |
67 | #define GET_ZONENO_FROM_SEGNO(sbi, segno) \ | 69 | #define GET_ZONENO_FROM_SEGNO(sbi, segno) \ |
68 | ((segno / sbi->segs_per_sec) / sbi->secs_per_zone) | 70 | ((segno / sbi->segs_per_sec) / sbi->secs_per_zone) |
69 | 71 | ||
70 | #define GET_SUM_BLOCK(sbi, segno) \ | 72 | #define GET_SUM_BLOCK(sbi, segno) \ |
71 | ((sbi->sm_info->ssa_blkaddr) + segno) | 73 | ((sbi->sm_info->ssa_blkaddr) + segno) |
72 | 74 | ||
73 | #define GET_SUM_TYPE(footer) ((footer)->entry_type) | 75 | #define GET_SUM_TYPE(footer) ((footer)->entry_type) |
74 | #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type) | 76 | #define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type) |
75 | 77 | ||
76 | #define SIT_ENTRY_OFFSET(sit_i, segno) \ | 78 | #define SIT_ENTRY_OFFSET(sit_i, segno) \ |
77 | (segno % sit_i->sents_per_block) | 79 | (segno % sit_i->sents_per_block) |
78 | #define SIT_BLOCK_OFFSET(sit_i, segno) \ | 80 | #define SIT_BLOCK_OFFSET(sit_i, segno) \ |
79 | (segno / SIT_ENTRY_PER_BLOCK) | 81 | (segno / SIT_ENTRY_PER_BLOCK) |
80 | #define START_SEGNO(sit_i, segno) \ | 82 | #define START_SEGNO(sit_i, segno) \ |
81 | (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK) | 83 | (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK) |
82 | #define f2fs_bitmap_size(nr) \ | 84 | #define f2fs_bitmap_size(nr) \ |
83 | (BITS_TO_LONGS(nr) * sizeof(unsigned long)) | 85 | (BITS_TO_LONGS(nr) * sizeof(unsigned long)) |
84 | #define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) | 86 | #define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) |
85 | #define TOTAL_SECS(sbi) (sbi->total_sections) | 87 | #define TOTAL_SECS(sbi) (sbi->total_sections) |
86 | 88 | ||
87 | #define SECTOR_FROM_BLOCK(sbi, blk_addr) \ | 89 | #define SECTOR_FROM_BLOCK(sbi, blk_addr) \ |
88 | (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) | 90 | (blk_addr << ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) |
91 | #define SECTOR_TO_BLOCK(sbi, sectors) \ | ||
92 | (sectors >> ((sbi)->log_blocksize - F2FS_LOG_SECTOR_SIZE)) | ||
89 | 93 | ||
90 | /* during checkpoint, bio_private is used to synchronize the last bio */ | 94 | /* during checkpoint, bio_private is used to synchronize the last bio */ |
91 | struct bio_private { | 95 | struct bio_private { |
92 | struct f2fs_sb_info *sbi; | 96 | struct f2fs_sb_info *sbi; |
93 | bool is_sync; | 97 | bool is_sync; |
94 | void *wait; | 98 | void *wait; |
95 | }; | 99 | }; |
96 | 100 | ||
97 | /* | 101 | /* |
98 | * indicate a block allocation direction: RIGHT and LEFT. | 102 | * indicate a block allocation direction: RIGHT and LEFT. |
99 | * RIGHT means allocating new sections towards the end of volume. | 103 | * RIGHT means allocating new sections towards the end of volume. |
100 | * LEFT means the opposite direction. | 104 | * LEFT means the opposite direction. |
101 | */ | 105 | */ |
102 | enum { | 106 | enum { |
103 | ALLOC_RIGHT = 0, | 107 | ALLOC_RIGHT = 0, |
104 | ALLOC_LEFT | 108 | ALLOC_LEFT |
105 | }; | 109 | }; |
106 | 110 | ||
107 | /* | 111 | /* |
108 | * In the victim_sel_policy->alloc_mode, there are two block allocation modes. | 112 | * In the victim_sel_policy->alloc_mode, there are two block allocation modes. |
109 | * LFS writes data sequentially with cleaning operations. | 113 | * LFS writes data sequentially with cleaning operations. |
110 | * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations. | 114 | * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations. |
111 | */ | 115 | */ |
112 | enum { | 116 | enum { |
113 | LFS = 0, | 117 | LFS = 0, |
114 | SSR | 118 | SSR |
115 | }; | 119 | }; |
116 | 120 | ||
117 | /* | 121 | /* |
118 | * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes. | 122 | * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes. |
119 | * GC_CB is based on cost-benefit algorithm. | 123 | * GC_CB is based on cost-benefit algorithm. |
120 | * GC_GREEDY is based on greedy algorithm. | 124 | * GC_GREEDY is based on greedy algorithm. |
121 | */ | 125 | */ |
122 | enum { | 126 | enum { |
123 | GC_CB = 0, | 127 | GC_CB = 0, |
124 | GC_GREEDY | 128 | GC_GREEDY |
125 | }; | 129 | }; |
126 | 130 | ||
127 | /* | 131 | /* |
128 | * BG_GC means the background cleaning job. | 132 | * BG_GC means the background cleaning job. |
129 | * FG_GC means the on-demand cleaning job. | 133 | * FG_GC means the on-demand cleaning job. |
130 | */ | 134 | */ |
131 | enum { | 135 | enum { |
132 | BG_GC = 0, | 136 | BG_GC = 0, |
133 | FG_GC | 137 | FG_GC |
134 | }; | 138 | }; |
135 | 139 | ||
136 | /* for a function parameter to select a victim segment */ | 140 | /* for a function parameter to select a victim segment */ |
137 | struct victim_sel_policy { | 141 | struct victim_sel_policy { |
138 | int alloc_mode; /* LFS or SSR */ | 142 | int alloc_mode; /* LFS or SSR */ |
139 | int gc_mode; /* GC_CB or GC_GREEDY */ | 143 | int gc_mode; /* GC_CB or GC_GREEDY */ |
140 | unsigned long *dirty_segmap; /* dirty segment bitmap */ | 144 | unsigned long *dirty_segmap; /* dirty segment bitmap */ |
141 | unsigned int offset; /* last scanned bitmap offset */ | 145 | unsigned int offset; /* last scanned bitmap offset */ |
142 | unsigned int ofs_unit; /* bitmap search unit */ | 146 | unsigned int ofs_unit; /* bitmap search unit */ |
143 | unsigned int min_cost; /* minimum cost */ | 147 | unsigned int min_cost; /* minimum cost */ |
144 | unsigned int min_segno; /* segment # having min. cost */ | 148 | unsigned int min_segno; /* segment # having min. cost */ |
145 | }; | 149 | }; |
146 | 150 | ||
147 | struct seg_entry { | 151 | struct seg_entry { |
148 | unsigned short valid_blocks; /* # of valid blocks */ | 152 | unsigned short valid_blocks; /* # of valid blocks */ |
149 | unsigned char *cur_valid_map; /* validity bitmap of blocks */ | 153 | unsigned char *cur_valid_map; /* validity bitmap of blocks */ |
150 | /* | 154 | /* |
151 | * # of valid blocks and the validity bitmap stored in the the last | 155 | * # of valid blocks and the validity bitmap stored in the the last |
152 | * checkpoint pack. This information is used by the SSR mode. | 156 | * checkpoint pack. This information is used by the SSR mode. |
153 | */ | 157 | */ |
154 | unsigned short ckpt_valid_blocks; | 158 | unsigned short ckpt_valid_blocks; |
155 | unsigned char *ckpt_valid_map; | 159 | unsigned char *ckpt_valid_map; |
156 | unsigned char type; /* segment type like CURSEG_XXX_TYPE */ | 160 | unsigned char type; /* segment type like CURSEG_XXX_TYPE */ |
157 | unsigned long long mtime; /* modification time of the segment */ | 161 | unsigned long long mtime; /* modification time of the segment */ |
158 | }; | 162 | }; |
159 | 163 | ||
160 | struct sec_entry { | 164 | struct sec_entry { |
161 | unsigned int valid_blocks; /* # of valid blocks in a section */ | 165 | unsigned int valid_blocks; /* # of valid blocks in a section */ |
162 | }; | 166 | }; |
163 | 167 | ||
164 | struct segment_allocation { | 168 | struct segment_allocation { |
165 | void (*allocate_segment)(struct f2fs_sb_info *, int, bool); | 169 | void (*allocate_segment)(struct f2fs_sb_info *, int, bool); |
166 | }; | 170 | }; |
167 | 171 | ||
168 | struct sit_info { | 172 | struct sit_info { |
169 | const struct segment_allocation *s_ops; | 173 | const struct segment_allocation *s_ops; |
170 | 174 | ||
171 | block_t sit_base_addr; /* start block address of SIT area */ | 175 | block_t sit_base_addr; /* start block address of SIT area */ |
172 | block_t sit_blocks; /* # of blocks used by SIT area */ | 176 | block_t sit_blocks; /* # of blocks used by SIT area */ |
173 | block_t written_valid_blocks; /* # of valid blocks in main area */ | 177 | block_t written_valid_blocks; /* # of valid blocks in main area */ |
174 | char *sit_bitmap; /* SIT bitmap pointer */ | 178 | char *sit_bitmap; /* SIT bitmap pointer */ |
175 | unsigned int bitmap_size; /* SIT bitmap size */ | 179 | unsigned int bitmap_size; /* SIT bitmap size */ |
176 | 180 | ||
177 | unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */ | 181 | unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */ |
178 | unsigned int dirty_sentries; /* # of dirty sentries */ | 182 | unsigned int dirty_sentries; /* # of dirty sentries */ |
179 | unsigned int sents_per_block; /* # of SIT entries per block */ | 183 | unsigned int sents_per_block; /* # of SIT entries per block */ |
180 | struct mutex sentry_lock; /* to protect SIT cache */ | 184 | struct mutex sentry_lock; /* to protect SIT cache */ |
181 | struct seg_entry *sentries; /* SIT segment-level cache */ | 185 | struct seg_entry *sentries; /* SIT segment-level cache */ |
182 | struct sec_entry *sec_entries; /* SIT section-level cache */ | 186 | struct sec_entry *sec_entries; /* SIT section-level cache */ |
183 | 187 | ||
184 | /* for cost-benefit algorithm in cleaning procedure */ | 188 | /* for cost-benefit algorithm in cleaning procedure */ |
185 | unsigned long long elapsed_time; /* elapsed time after mount */ | 189 | unsigned long long elapsed_time; /* elapsed time after mount */ |
186 | unsigned long long mounted_time; /* mount time */ | 190 | unsigned long long mounted_time; /* mount time */ |
187 | unsigned long long min_mtime; /* min. modification time */ | 191 | unsigned long long min_mtime; /* min. modification time */ |
188 | unsigned long long max_mtime; /* max. modification time */ | 192 | unsigned long long max_mtime; /* max. modification time */ |
189 | }; | 193 | }; |
190 | 194 | ||
191 | struct free_segmap_info { | 195 | struct free_segmap_info { |
192 | unsigned int start_segno; /* start segment number logically */ | 196 | unsigned int start_segno; /* start segment number logically */ |
193 | unsigned int free_segments; /* # of free segments */ | 197 | unsigned int free_segments; /* # of free segments */ |
194 | unsigned int free_sections; /* # of free sections */ | 198 | unsigned int free_sections; /* # of free sections */ |
195 | rwlock_t segmap_lock; /* free segmap lock */ | 199 | rwlock_t segmap_lock; /* free segmap lock */ |
196 | unsigned long *free_segmap; /* free segment bitmap */ | 200 | unsigned long *free_segmap; /* free segment bitmap */ |
197 | unsigned long *free_secmap; /* free section bitmap */ | 201 | unsigned long *free_secmap; /* free section bitmap */ |
198 | }; | 202 | }; |
199 | 203 | ||
200 | /* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */ | 204 | /* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */ |
201 | enum dirty_type { | 205 | enum dirty_type { |
202 | DIRTY_HOT_DATA, /* dirty segments assigned as hot data logs */ | 206 | DIRTY_HOT_DATA, /* dirty segments assigned as hot data logs */ |
203 | DIRTY_WARM_DATA, /* dirty segments assigned as warm data logs */ | 207 | DIRTY_WARM_DATA, /* dirty segments assigned as warm data logs */ |
204 | DIRTY_COLD_DATA, /* dirty segments assigned as cold data logs */ | 208 | DIRTY_COLD_DATA, /* dirty segments assigned as cold data logs */ |
205 | DIRTY_HOT_NODE, /* dirty segments assigned as hot node logs */ | 209 | DIRTY_HOT_NODE, /* dirty segments assigned as hot node logs */ |
206 | DIRTY_WARM_NODE, /* dirty segments assigned as warm node logs */ | 210 | DIRTY_WARM_NODE, /* dirty segments assigned as warm node logs */ |
207 | DIRTY_COLD_NODE, /* dirty segments assigned as cold node logs */ | 211 | DIRTY_COLD_NODE, /* dirty segments assigned as cold node logs */ |
208 | DIRTY, /* to count # of dirty segments */ | 212 | DIRTY, /* to count # of dirty segments */ |
209 | PRE, /* to count # of entirely obsolete segments */ | 213 | PRE, /* to count # of entirely obsolete segments */ |
210 | NR_DIRTY_TYPE | 214 | NR_DIRTY_TYPE |
211 | }; | 215 | }; |
212 | 216 | ||
213 | struct dirty_seglist_info { | 217 | struct dirty_seglist_info { |
214 | const struct victim_selection *v_ops; /* victim selction operation */ | 218 | const struct victim_selection *v_ops; /* victim selction operation */ |
215 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; | 219 | unsigned long *dirty_segmap[NR_DIRTY_TYPE]; |
216 | struct mutex seglist_lock; /* lock for segment bitmaps */ | 220 | struct mutex seglist_lock; /* lock for segment bitmaps */ |
217 | int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ | 221 | int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ |
218 | unsigned long *victim_secmap; /* background GC victims */ | 222 | unsigned long *victim_secmap; /* background GC victims */ |
219 | }; | 223 | }; |
220 | 224 | ||
221 | /* victim selection function for cleaning and SSR */ | 225 | /* victim selection function for cleaning and SSR */ |
222 | struct victim_selection { | 226 | struct victim_selection { |
223 | int (*get_victim)(struct f2fs_sb_info *, unsigned int *, | 227 | int (*get_victim)(struct f2fs_sb_info *, unsigned int *, |
224 | int, int, char); | 228 | int, int, char); |
225 | }; | 229 | }; |
226 | 230 | ||
227 | /* for active log information */ | 231 | /* for active log information */ |
228 | struct curseg_info { | 232 | struct curseg_info { |
229 | struct mutex curseg_mutex; /* lock for consistency */ | 233 | struct mutex curseg_mutex; /* lock for consistency */ |
230 | struct f2fs_summary_block *sum_blk; /* cached summary block */ | 234 | struct f2fs_summary_block *sum_blk; /* cached summary block */ |
231 | unsigned char alloc_type; /* current allocation type */ | 235 | unsigned char alloc_type; /* current allocation type */ |
232 | unsigned int segno; /* current segment number */ | 236 | unsigned int segno; /* current segment number */ |
233 | unsigned short next_blkoff; /* next block offset to write */ | 237 | unsigned short next_blkoff; /* next block offset to write */ |
234 | unsigned int zone; /* current zone number */ | 238 | unsigned int zone; /* current zone number */ |
235 | unsigned int next_segno; /* preallocated segment */ | 239 | unsigned int next_segno; /* preallocated segment */ |
236 | }; | 240 | }; |
237 | 241 | ||
238 | /* | 242 | /* |
239 | * inline functions | 243 | * inline functions |
240 | */ | 244 | */ |
241 | static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) | 245 | static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) |
242 | { | 246 | { |
243 | return (struct curseg_info *)(SM_I(sbi)->curseg_array + type); | 247 | return (struct curseg_info *)(SM_I(sbi)->curseg_array + type); |
244 | } | 248 | } |
245 | 249 | ||
246 | static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, | 250 | static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, |
247 | unsigned int segno) | 251 | unsigned int segno) |
248 | { | 252 | { |
249 | struct sit_info *sit_i = SIT_I(sbi); | 253 | struct sit_info *sit_i = SIT_I(sbi); |
250 | return &sit_i->sentries[segno]; | 254 | return &sit_i->sentries[segno]; |
251 | } | 255 | } |
252 | 256 | ||
253 | static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi, | 257 | static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi, |
254 | unsigned int segno) | 258 | unsigned int segno) |
255 | { | 259 | { |
256 | struct sit_info *sit_i = SIT_I(sbi); | 260 | struct sit_info *sit_i = SIT_I(sbi); |
257 | return &sit_i->sec_entries[GET_SECNO(sbi, segno)]; | 261 | return &sit_i->sec_entries[GET_SECNO(sbi, segno)]; |
258 | } | 262 | } |
259 | 263 | ||
260 | static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, | 264 | static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, |
261 | unsigned int segno, int section) | 265 | unsigned int segno, int section) |
262 | { | 266 | { |
263 | /* | 267 | /* |
264 | * In order to get # of valid blocks in a section instantly from many | 268 | * In order to get # of valid blocks in a section instantly from many |
265 | * segments, f2fs manages two counting structures separately. | 269 | * segments, f2fs manages two counting structures separately. |
266 | */ | 270 | */ |
267 | if (section > 1) | 271 | if (section > 1) |
268 | return get_sec_entry(sbi, segno)->valid_blocks; | 272 | return get_sec_entry(sbi, segno)->valid_blocks; |
269 | else | 273 | else |
270 | return get_seg_entry(sbi, segno)->valid_blocks; | 274 | return get_seg_entry(sbi, segno)->valid_blocks; |
271 | } | 275 | } |
272 | 276 | ||
273 | static inline void seg_info_from_raw_sit(struct seg_entry *se, | 277 | static inline void seg_info_from_raw_sit(struct seg_entry *se, |
274 | struct f2fs_sit_entry *rs) | 278 | struct f2fs_sit_entry *rs) |
275 | { | 279 | { |
276 | se->valid_blocks = GET_SIT_VBLOCKS(rs); | 280 | se->valid_blocks = GET_SIT_VBLOCKS(rs); |
277 | se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs); | 281 | se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs); |
278 | memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); | 282 | memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); |
279 | memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); | 283 | memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); |
280 | se->type = GET_SIT_TYPE(rs); | 284 | se->type = GET_SIT_TYPE(rs); |
281 | se->mtime = le64_to_cpu(rs->mtime); | 285 | se->mtime = le64_to_cpu(rs->mtime); |
282 | } | 286 | } |
283 | 287 | ||
284 | static inline void seg_info_to_raw_sit(struct seg_entry *se, | 288 | static inline void seg_info_to_raw_sit(struct seg_entry *se, |
285 | struct f2fs_sit_entry *rs) | 289 | struct f2fs_sit_entry *rs) |
286 | { | 290 | { |
287 | unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) | | 291 | unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) | |
288 | se->valid_blocks; | 292 | se->valid_blocks; |
289 | rs->vblocks = cpu_to_le16(raw_vblocks); | 293 | rs->vblocks = cpu_to_le16(raw_vblocks); |
290 | memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); | 294 | memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); |
291 | memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); | 295 | memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); |
292 | se->ckpt_valid_blocks = se->valid_blocks; | 296 | se->ckpt_valid_blocks = se->valid_blocks; |
293 | rs->mtime = cpu_to_le64(se->mtime); | 297 | rs->mtime = cpu_to_le64(se->mtime); |
294 | } | 298 | } |
295 | 299 | ||
296 | static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, | 300 | static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, |
297 | unsigned int max, unsigned int segno) | 301 | unsigned int max, unsigned int segno) |
298 | { | 302 | { |
299 | unsigned int ret; | 303 | unsigned int ret; |
300 | read_lock(&free_i->segmap_lock); | 304 | read_lock(&free_i->segmap_lock); |
301 | ret = find_next_bit(free_i->free_segmap, max, segno); | 305 | ret = find_next_bit(free_i->free_segmap, max, segno); |
302 | read_unlock(&free_i->segmap_lock); | 306 | read_unlock(&free_i->segmap_lock); |
303 | return ret; | 307 | return ret; |
304 | } | 308 | } |
305 | 309 | ||
306 | static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno) | 310 | static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno) |
307 | { | 311 | { |
308 | struct free_segmap_info *free_i = FREE_I(sbi); | 312 | struct free_segmap_info *free_i = FREE_I(sbi); |
309 | unsigned int secno = segno / sbi->segs_per_sec; | 313 | unsigned int secno = segno / sbi->segs_per_sec; |
310 | unsigned int start_segno = secno * sbi->segs_per_sec; | 314 | unsigned int start_segno = secno * sbi->segs_per_sec; |
311 | unsigned int next; | 315 | unsigned int next; |
312 | 316 | ||
313 | write_lock(&free_i->segmap_lock); | 317 | write_lock(&free_i->segmap_lock); |
314 | clear_bit(segno, free_i->free_segmap); | 318 | clear_bit(segno, free_i->free_segmap); |
315 | free_i->free_segments++; | 319 | free_i->free_segments++; |
316 | 320 | ||
317 | next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno); | 321 | next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno); |
318 | if (next >= start_segno + sbi->segs_per_sec) { | 322 | if (next >= start_segno + sbi->segs_per_sec) { |
319 | clear_bit(secno, free_i->free_secmap); | 323 | clear_bit(secno, free_i->free_secmap); |
320 | free_i->free_sections++; | 324 | free_i->free_sections++; |
321 | } | 325 | } |
322 | write_unlock(&free_i->segmap_lock); | 326 | write_unlock(&free_i->segmap_lock); |
323 | } | 327 | } |
324 | 328 | ||
325 | static inline void __set_inuse(struct f2fs_sb_info *sbi, | 329 | static inline void __set_inuse(struct f2fs_sb_info *sbi, |
326 | unsigned int segno) | 330 | unsigned int segno) |
327 | { | 331 | { |
328 | struct free_segmap_info *free_i = FREE_I(sbi); | 332 | struct free_segmap_info *free_i = FREE_I(sbi); |
329 | unsigned int secno = segno / sbi->segs_per_sec; | 333 | unsigned int secno = segno / sbi->segs_per_sec; |
330 | set_bit(segno, free_i->free_segmap); | 334 | set_bit(segno, free_i->free_segmap); |
331 | free_i->free_segments--; | 335 | free_i->free_segments--; |
332 | if (!test_and_set_bit(secno, free_i->free_secmap)) | 336 | if (!test_and_set_bit(secno, free_i->free_secmap)) |
333 | free_i->free_sections--; | 337 | free_i->free_sections--; |
334 | } | 338 | } |
335 | 339 | ||
336 | static inline void __set_test_and_free(struct f2fs_sb_info *sbi, | 340 | static inline void __set_test_and_free(struct f2fs_sb_info *sbi, |
337 | unsigned int segno) | 341 | unsigned int segno) |
338 | { | 342 | { |
339 | struct free_segmap_info *free_i = FREE_I(sbi); | 343 | struct free_segmap_info *free_i = FREE_I(sbi); |
340 | unsigned int secno = segno / sbi->segs_per_sec; | 344 | unsigned int secno = segno / sbi->segs_per_sec; |
341 | unsigned int start_segno = secno * sbi->segs_per_sec; | 345 | unsigned int start_segno = secno * sbi->segs_per_sec; |
342 | unsigned int next; | 346 | unsigned int next; |
343 | 347 | ||
344 | write_lock(&free_i->segmap_lock); | 348 | write_lock(&free_i->segmap_lock); |
345 | if (test_and_clear_bit(segno, free_i->free_segmap)) { | 349 | if (test_and_clear_bit(segno, free_i->free_segmap)) { |
346 | free_i->free_segments++; | 350 | free_i->free_segments++; |
347 | 351 | ||
348 | next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), | 352 | next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), |
349 | start_segno); | 353 | start_segno); |
350 | if (next >= start_segno + sbi->segs_per_sec) { | 354 | if (next >= start_segno + sbi->segs_per_sec) { |
351 | if (test_and_clear_bit(secno, free_i->free_secmap)) | 355 | if (test_and_clear_bit(secno, free_i->free_secmap)) |
352 | free_i->free_sections++; | 356 | free_i->free_sections++; |
353 | } | 357 | } |
354 | } | 358 | } |
355 | write_unlock(&free_i->segmap_lock); | 359 | write_unlock(&free_i->segmap_lock); |
356 | } | 360 | } |
357 | 361 | ||
358 | static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi, | 362 | static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi, |
359 | unsigned int segno) | 363 | unsigned int segno) |
360 | { | 364 | { |
361 | struct free_segmap_info *free_i = FREE_I(sbi); | 365 | struct free_segmap_info *free_i = FREE_I(sbi); |
362 | unsigned int secno = segno / sbi->segs_per_sec; | 366 | unsigned int secno = segno / sbi->segs_per_sec; |
363 | write_lock(&free_i->segmap_lock); | 367 | write_lock(&free_i->segmap_lock); |
364 | if (!test_and_set_bit(segno, free_i->free_segmap)) { | 368 | if (!test_and_set_bit(segno, free_i->free_segmap)) { |
365 | free_i->free_segments--; | 369 | free_i->free_segments--; |
366 | if (!test_and_set_bit(secno, free_i->free_secmap)) | 370 | if (!test_and_set_bit(secno, free_i->free_secmap)) |
367 | free_i->free_sections--; | 371 | free_i->free_sections--; |
368 | } | 372 | } |
369 | write_unlock(&free_i->segmap_lock); | 373 | write_unlock(&free_i->segmap_lock); |
370 | } | 374 | } |
371 | 375 | ||
372 | static inline void get_sit_bitmap(struct f2fs_sb_info *sbi, | 376 | static inline void get_sit_bitmap(struct f2fs_sb_info *sbi, |
373 | void *dst_addr) | 377 | void *dst_addr) |
374 | { | 378 | { |
375 | struct sit_info *sit_i = SIT_I(sbi); | 379 | struct sit_info *sit_i = SIT_I(sbi); |
376 | memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size); | 380 | memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size); |
377 | } | 381 | } |
378 | 382 | ||
379 | static inline block_t written_block_count(struct f2fs_sb_info *sbi) | 383 | static inline block_t written_block_count(struct f2fs_sb_info *sbi) |
380 | { | 384 | { |
381 | struct sit_info *sit_i = SIT_I(sbi); | 385 | struct sit_info *sit_i = SIT_I(sbi); |
382 | block_t vblocks; | 386 | block_t vblocks; |
383 | 387 | ||
384 | mutex_lock(&sit_i->sentry_lock); | 388 | mutex_lock(&sit_i->sentry_lock); |
385 | vblocks = sit_i->written_valid_blocks; | 389 | vblocks = sit_i->written_valid_blocks; |
386 | mutex_unlock(&sit_i->sentry_lock); | 390 | mutex_unlock(&sit_i->sentry_lock); |
387 | 391 | ||
388 | return vblocks; | 392 | return vblocks; |
389 | } | 393 | } |
390 | 394 | ||
391 | static inline unsigned int free_segments(struct f2fs_sb_info *sbi) | 395 | static inline unsigned int free_segments(struct f2fs_sb_info *sbi) |
392 | { | 396 | { |
393 | struct free_segmap_info *free_i = FREE_I(sbi); | 397 | struct free_segmap_info *free_i = FREE_I(sbi); |
394 | unsigned int free_segs; | 398 | unsigned int free_segs; |
395 | 399 | ||
396 | read_lock(&free_i->segmap_lock); | 400 | read_lock(&free_i->segmap_lock); |
397 | free_segs = free_i->free_segments; | 401 | free_segs = free_i->free_segments; |
398 | read_unlock(&free_i->segmap_lock); | 402 | read_unlock(&free_i->segmap_lock); |
399 | 403 | ||
400 | return free_segs; | 404 | return free_segs; |
401 | } | 405 | } |
402 | 406 | ||
403 | static inline int reserved_segments(struct f2fs_sb_info *sbi) | 407 | static inline int reserved_segments(struct f2fs_sb_info *sbi) |
404 | { | 408 | { |
405 | return SM_I(sbi)->reserved_segments; | 409 | return SM_I(sbi)->reserved_segments; |
406 | } | 410 | } |
407 | 411 | ||
408 | static inline unsigned int free_sections(struct f2fs_sb_info *sbi) | 412 | static inline unsigned int free_sections(struct f2fs_sb_info *sbi) |
409 | { | 413 | { |
410 | struct free_segmap_info *free_i = FREE_I(sbi); | 414 | struct free_segmap_info *free_i = FREE_I(sbi); |
411 | unsigned int free_secs; | 415 | unsigned int free_secs; |
412 | 416 | ||
413 | read_lock(&free_i->segmap_lock); | 417 | read_lock(&free_i->segmap_lock); |
414 | free_secs = free_i->free_sections; | 418 | free_secs = free_i->free_sections; |
415 | read_unlock(&free_i->segmap_lock); | 419 | read_unlock(&free_i->segmap_lock); |
416 | 420 | ||
417 | return free_secs; | 421 | return free_secs; |
418 | } | 422 | } |
419 | 423 | ||
420 | static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi) | 424 | static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi) |
421 | { | 425 | { |
422 | return DIRTY_I(sbi)->nr_dirty[PRE]; | 426 | return DIRTY_I(sbi)->nr_dirty[PRE]; |
423 | } | 427 | } |
424 | 428 | ||
425 | static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi) | 429 | static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi) |
426 | { | 430 | { |
427 | return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] + | 431 | return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] + |
428 | DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] + | 432 | DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] + |
429 | DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] + | 433 | DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] + |
430 | DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] + | 434 | DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] + |
431 | DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] + | 435 | DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] + |
432 | DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE]; | 436 | DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE]; |
433 | } | 437 | } |
434 | 438 | ||
435 | static inline int overprovision_segments(struct f2fs_sb_info *sbi) | 439 | static inline int overprovision_segments(struct f2fs_sb_info *sbi) |
436 | { | 440 | { |
437 | return SM_I(sbi)->ovp_segments; | 441 | return SM_I(sbi)->ovp_segments; |
438 | } | 442 | } |
439 | 443 | ||
440 | static inline int overprovision_sections(struct f2fs_sb_info *sbi) | 444 | static inline int overprovision_sections(struct f2fs_sb_info *sbi) |
441 | { | 445 | { |
442 | return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec; | 446 | return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec; |
443 | } | 447 | } |
444 | 448 | ||
445 | static inline int reserved_sections(struct f2fs_sb_info *sbi) | 449 | static inline int reserved_sections(struct f2fs_sb_info *sbi) |
446 | { | 450 | { |
447 | return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec; | 451 | return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec; |
448 | } | 452 | } |
449 | 453 | ||
450 | static inline bool need_SSR(struct f2fs_sb_info *sbi) | 454 | static inline bool need_SSR(struct f2fs_sb_info *sbi) |
451 | { | 455 | { |
452 | return (free_sections(sbi) < overprovision_sections(sbi)); | 456 | return (free_sections(sbi) < overprovision_sections(sbi)); |
453 | } | 457 | } |
454 | 458 | ||
455 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) | 459 | static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) |
456 | { | 460 | { |
457 | int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); | 461 | int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); |
458 | int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); | 462 | int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); |
459 | 463 | ||
460 | if (sbi->por_doing) | 464 | if (sbi->por_doing) |
461 | return false; | 465 | return false; |
462 | 466 | ||
463 | return ((free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs + | 467 | return ((free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs + |
464 | reserved_sections(sbi))); | 468 | reserved_sections(sbi))); |
465 | } | 469 | } |
466 | 470 | ||
467 | static inline int utilization(struct f2fs_sb_info *sbi) | 471 | static inline int utilization(struct f2fs_sb_info *sbi) |
468 | { | 472 | { |
469 | return div_u64(valid_user_blocks(sbi) * 100, sbi->user_block_count); | 473 | return div_u64(valid_user_blocks(sbi) * 100, sbi->user_block_count); |
470 | } | 474 | } |
471 | 475 | ||
472 | /* | 476 | /* |
473 | * Sometimes f2fs may be better to drop out-of-place update policy. | 477 | * Sometimes f2fs may be better to drop out-of-place update policy. |
474 | * So, if fs utilization is over MIN_IPU_UTIL, then f2fs tries to write | 478 | * So, if fs utilization is over MIN_IPU_UTIL, then f2fs tries to write |
475 | * data in the original place likewise other traditional file systems. | 479 | * data in the original place likewise other traditional file systems. |
476 | * But, currently set 100 in percentage, which means it is disabled. | 480 | * But, currently set 100 in percentage, which means it is disabled. |
477 | * See below need_inplace_update(). | 481 | * See below need_inplace_update(). |
478 | */ | 482 | */ |
479 | #define MIN_IPU_UTIL 100 | 483 | #define MIN_IPU_UTIL 100 |
480 | static inline bool need_inplace_update(struct inode *inode) | 484 | static inline bool need_inplace_update(struct inode *inode) |
481 | { | 485 | { |
482 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 486 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
483 | if (S_ISDIR(inode->i_mode)) | 487 | if (S_ISDIR(inode->i_mode)) |
484 | return false; | 488 | return false; |
485 | if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL) | 489 | if (need_SSR(sbi) && utilization(sbi) > MIN_IPU_UTIL) |
486 | return true; | 490 | return true; |
487 | return false; | 491 | return false; |
488 | } | 492 | } |
489 | 493 | ||
490 | static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, | 494 | static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, |
491 | int type) | 495 | int type) |
492 | { | 496 | { |
493 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 497 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
494 | return curseg->segno; | 498 | return curseg->segno; |
495 | } | 499 | } |
496 | 500 | ||
497 | static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi, | 501 | static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi, |
498 | int type) | 502 | int type) |
499 | { | 503 | { |
500 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 504 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
501 | return curseg->alloc_type; | 505 | return curseg->alloc_type; |
502 | } | 506 | } |
503 | 507 | ||
504 | static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type) | 508 | static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type) |
505 | { | 509 | { |
506 | struct curseg_info *curseg = CURSEG_I(sbi, type); | 510 | struct curseg_info *curseg = CURSEG_I(sbi, type); |
507 | return curseg->next_blkoff; | 511 | return curseg->next_blkoff; |
508 | } | 512 | } |
509 | 513 | ||
510 | static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) | 514 | static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) |
511 | { | 515 | { |
512 | unsigned int end_segno = SM_I(sbi)->segment_count - 1; | 516 | unsigned int end_segno = SM_I(sbi)->segment_count - 1; |
513 | BUG_ON(segno > end_segno); | 517 | BUG_ON(segno > end_segno); |
514 | } | 518 | } |
515 | 519 | ||
516 | /* | 520 | /* |
517 | * This function is used for only debugging. | 521 | * This function is used for only debugging. |
518 | * NOTE: In future, we have to remove this function. | 522 | * NOTE: In future, we have to remove this function. |
519 | */ | 523 | */ |
520 | static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) | 524 | static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) |
521 | { | 525 | { |
522 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 526 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
523 | block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg; | 527 | block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg; |
524 | block_t start_addr = sm_info->seg0_blkaddr; | 528 | block_t start_addr = sm_info->seg0_blkaddr; |
525 | block_t end_addr = start_addr + total_blks - 1; | 529 | block_t end_addr = start_addr + total_blks - 1; |
526 | BUG_ON(blk_addr < start_addr); | 530 | BUG_ON(blk_addr < start_addr); |
527 | BUG_ON(blk_addr > end_addr); | 531 | BUG_ON(blk_addr > end_addr); |
528 | } | 532 | } |
529 | 533 | ||
530 | /* | 534 | /* |
531 | * Summary block is always treated as invalid block | 535 | * Summary block is always treated as invalid block |
532 | */ | 536 | */ |
533 | static inline void check_block_count(struct f2fs_sb_info *sbi, | 537 | static inline void check_block_count(struct f2fs_sb_info *sbi, |
534 | int segno, struct f2fs_sit_entry *raw_sit) | 538 | int segno, struct f2fs_sit_entry *raw_sit) |
535 | { | 539 | { |
536 | struct f2fs_sm_info *sm_info = SM_I(sbi); | 540 | struct f2fs_sm_info *sm_info = SM_I(sbi); |
537 | unsigned int end_segno = sm_info->segment_count - 1; | 541 | unsigned int end_segno = sm_info->segment_count - 1; |
538 | int valid_blocks = 0; | 542 | int valid_blocks = 0; |
539 | int i; | 543 | int i; |
540 | 544 | ||
541 | /* check segment usage */ | 545 | /* check segment usage */ |
542 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg); | 546 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg); |
543 | 547 | ||
544 | /* check boundary of a given segment number */ | 548 | /* check boundary of a given segment number */ |
545 | BUG_ON(segno > end_segno); | 549 | BUG_ON(segno > end_segno); |
546 | 550 | ||
547 | /* check bitmap with valid block count */ | 551 | /* check bitmap with valid block count */ |
548 | for (i = 0; i < sbi->blocks_per_seg; i++) | 552 | for (i = 0; i < sbi->blocks_per_seg; i++) |
549 | if (f2fs_test_bit(i, raw_sit->valid_map)) | 553 | if (f2fs_test_bit(i, raw_sit->valid_map)) |
550 | valid_blocks++; | 554 | valid_blocks++; |
551 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); | 555 | BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); |
552 | } | 556 | } |
553 | 557 | ||
554 | static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, | 558 | static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, |
555 | unsigned int start) | 559 | unsigned int start) |
556 | { | 560 | { |
557 | struct sit_info *sit_i = SIT_I(sbi); | 561 | struct sit_info *sit_i = SIT_I(sbi); |
558 | unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start); | 562 | unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start); |
559 | block_t blk_addr = sit_i->sit_base_addr + offset; | 563 | block_t blk_addr = sit_i->sit_base_addr + offset; |
560 | 564 | ||
561 | check_seg_range(sbi, start); | 565 | check_seg_range(sbi, start); |
562 | 566 | ||
563 | /* calculate sit block address */ | 567 | /* calculate sit block address */ |
564 | if (f2fs_test_bit(offset, sit_i->sit_bitmap)) | 568 | if (f2fs_test_bit(offset, sit_i->sit_bitmap)) |
565 | blk_addr += sit_i->sit_blocks; | 569 | blk_addr += sit_i->sit_blocks; |
566 | 570 | ||
567 | return blk_addr; | 571 | return blk_addr; |
568 | } | 572 | } |
569 | 573 | ||
570 | static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, | 574 | static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, |
571 | pgoff_t block_addr) | 575 | pgoff_t block_addr) |
572 | { | 576 | { |
573 | struct sit_info *sit_i = SIT_I(sbi); | 577 | struct sit_info *sit_i = SIT_I(sbi); |
574 | block_addr -= sit_i->sit_base_addr; | 578 | block_addr -= sit_i->sit_base_addr; |
575 | if (block_addr < sit_i->sit_blocks) | 579 | if (block_addr < sit_i->sit_blocks) |
576 | block_addr += sit_i->sit_blocks; | 580 | block_addr += sit_i->sit_blocks; |
577 | else | 581 | else |
578 | block_addr -= sit_i->sit_blocks; | 582 | block_addr -= sit_i->sit_blocks; |
579 | 583 | ||
580 | return block_addr + sit_i->sit_base_addr; | 584 | return block_addr + sit_i->sit_base_addr; |
581 | } | 585 | } |
582 | 586 | ||
583 | static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) | 587 | static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) |
584 | { | 588 | { |
585 | unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start); | 589 | unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start); |
586 | 590 | ||
587 | if (f2fs_test_bit(block_off, sit_i->sit_bitmap)) | 591 | if (f2fs_test_bit(block_off, sit_i->sit_bitmap)) |
588 | f2fs_clear_bit(block_off, sit_i->sit_bitmap); | 592 | f2fs_clear_bit(block_off, sit_i->sit_bitmap); |
589 | else | 593 | else |
590 | f2fs_set_bit(block_off, sit_i->sit_bitmap); | 594 | f2fs_set_bit(block_off, sit_i->sit_bitmap); |
591 | } | 595 | } |
592 | 596 | ||
593 | static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi) | 597 | static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi) |
594 | { | 598 | { |
595 | struct sit_info *sit_i = SIT_I(sbi); | 599 | struct sit_info *sit_i = SIT_I(sbi); |
596 | return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec - | 600 | return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec - |
597 | sit_i->mounted_time; | 601 | sit_i->mounted_time; |
598 | } | 602 | } |
599 | 603 | ||
600 | static inline void set_summary(struct f2fs_summary *sum, nid_t nid, | 604 | static inline void set_summary(struct f2fs_summary *sum, nid_t nid, |
601 | unsigned int ofs_in_node, unsigned char version) | 605 | unsigned int ofs_in_node, unsigned char version) |
602 | { | 606 | { |
603 | sum->nid = cpu_to_le32(nid); | 607 | sum->nid = cpu_to_le32(nid); |
604 | sum->ofs_in_node = cpu_to_le16(ofs_in_node); | 608 | sum->ofs_in_node = cpu_to_le16(ofs_in_node); |
605 | sum->version = version; | 609 | sum->version = version; |
606 | } | 610 | } |
607 | 611 | ||
608 | static inline block_t start_sum_block(struct f2fs_sb_info *sbi) | 612 | static inline block_t start_sum_block(struct f2fs_sb_info *sbi) |
609 | { | 613 | { |
610 | return __start_cp_addr(sbi) + | 614 | return __start_cp_addr(sbi) + |
611 | le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); | 615 | le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); |
612 | } | 616 | } |
613 | 617 | ||
614 | static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type) | 618 | static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type) |
615 | { | 619 | { |
616 | return __start_cp_addr(sbi) + | 620 | return __start_cp_addr(sbi) + |
617 | le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count) | 621 | le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count) |
618 | - (base + 1) + type; | 622 | - (base + 1) + type; |
619 | } | 623 | } |
620 | 624 | ||
621 | static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno) | 625 | static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno) |
622 | { | 626 | { |
623 | if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno)) | 627 | if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno)) |
624 | return true; | 628 | return true; |
625 | return false; | 629 | return false; |
630 | } | ||
631 | |||
632 | static inline unsigned int max_hw_blocks(struct f2fs_sb_info *sbi) | ||
633 | { | ||
634 | struct block_device *bdev = sbi->sb->s_bdev; | ||
635 | struct request_queue *q = bdev_get_queue(bdev); | ||
636 | return SECTOR_TO_BLOCK(sbi, queue_max_sectors(q)); | ||
626 | } | 637 | } |
627 | 638 |