Blame view
fs/f2fs/node.c
56.8 KB
0a8165d7c f2fs: adjust kern... |
1 |
/* |
e05df3b11 f2fs: add node op... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
* fs/f2fs/node.c * * Copyright (c) 2012 Samsung Electronics Co., Ltd. * http://www.samsung.com/ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */ #include <linux/fs.h> #include <linux/f2fs_fs.h> #include <linux/mpage.h> #include <linux/backing-dev.h> #include <linux/blkdev.h> #include <linux/pagevec.h> #include <linux/swap.h> #include "f2fs.h" #include "node.h" #include "segment.h" |
9e4ded3f3 f2fs: activate f2... |
22 |
#include "trace.h" |
51dd62493 f2fs: add tracepo... |
23 |
#include <trace/events/f2fs.h> |
e05df3b11 f2fs: add node op... |
24 |
|
f978f5a06 f2fs: introduce h... |
25 |
#define on_build_free_nids(nmi) mutex_is_locked(&nm_i->build_lock) |
e05df3b11 f2fs: add node op... |
26 27 |
static struct kmem_cache *nat_entry_slab; static struct kmem_cache *free_nid_slab; |
aec71382c f2fs: refactor fl... |
28 |
static struct kmem_cache *nat_entry_set_slab; |
e05df3b11 f2fs: add node op... |
29 |
|
6fb03f3a4 f2fs: adjust free... |
30 |
bool available_free_memory(struct f2fs_sb_info *sbi, int type) |
cdfc41c13 f2fs: throttle th... |
31 |
{ |
6fb03f3a4 f2fs: adjust free... |
32 |
struct f2fs_nm_info *nm_i = NM_I(sbi); |
cdfc41c13 f2fs: throttle th... |
33 |
struct sysinfo val; |
e5e7ea3c8 f2fs: control the... |
34 |
unsigned long avail_ram; |
cdfc41c13 f2fs: throttle th... |
35 |
unsigned long mem_size = 0; |
6fb03f3a4 f2fs: adjust free... |
36 |
bool res = false; |
cdfc41c13 f2fs: throttle th... |
37 38 |
si_meminfo(&val); |
e5e7ea3c8 f2fs: control the... |
39 40 41 |
/* only uses low memory */ avail_ram = val.totalram - val.totalhigh; |
429511cdf f2fs: add core fu... |
42 43 44 |
/* * give 25%, 25%, 50%, 50%, 50% memory for each components respectively */ |
6fb03f3a4 f2fs: adjust free... |
45 |
if (type == FREE_NIDS) { |
e5e7ea3c8 f2fs: control the... |
46 |
mem_size = (nm_i->fcnt * sizeof(struct free_nid)) >> |
09cbfeaf1 mm, fs: get rid o... |
47 |
PAGE_SHIFT; |
e5e7ea3c8 f2fs: control the... |
48 |
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); |
6fb03f3a4 f2fs: adjust free... |
49 |
} else if (type == NAT_ENTRIES) { |
e5e7ea3c8 f2fs: control the... |
50 |
mem_size = (nm_i->nat_cnt * sizeof(struct nat_entry)) >> |
09cbfeaf1 mm, fs: get rid o... |
51 |
PAGE_SHIFT; |
e5e7ea3c8 f2fs: control the... |
52 |
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2); |
e589c2c47 f2fs: control not... |
53 54 |
if (excess_cached_nats(sbi)) res = false; |
a12570232 Revert "f2fs: do ... |
55 56 57 58 59 |
} else if (type == DIRTY_DENTS) { if (sbi->sb->s_bdi->wb.dirty_exceeded) return false; mem_size = get_pages(sbi, F2FS_DIRTY_DENTS); res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); |
e5e7ea3c8 f2fs: control the... |
60 61 |
} else if (type == INO_ENTRIES) { int i; |
e5e7ea3c8 f2fs: control the... |
62 |
for (i = 0; i <= UPDATE_INO; i++) |
67298804f f2fs: introduce s... |
63 |
mem_size += (sbi->im[i].ino_num * |
09cbfeaf1 mm, fs: get rid o... |
64 |
sizeof(struct ino_entry)) >> PAGE_SHIFT; |
e5e7ea3c8 f2fs: control the... |
65 |
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); |
429511cdf f2fs: add core fu... |
66 |
} else if (type == EXTENT_CACHE) { |
7441ccef3 f2fs: use atomic ... |
67 68 |
mem_size = (atomic_read(&sbi->total_ext_tree) * sizeof(struct extent_tree) + |
429511cdf f2fs: add core fu... |
69 |
atomic_read(&sbi->total_ext_node) * |
09cbfeaf1 mm, fs: get rid o... |
70 |
sizeof(struct extent_node)) >> PAGE_SHIFT; |
429511cdf f2fs: add core fu... |
71 |
res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1); |
1e84371ff f2fs: change atom... |
72 |
} else { |
1663cae48 f2fs: fix wrong m... |
73 74 |
if (!sbi->sb->s_bdi->wb.dirty_exceeded) return true; |
6fb03f3a4 f2fs: adjust free... |
75 76 |
} return res; |
cdfc41c13 f2fs: throttle th... |
77 |
} |
e05df3b11 f2fs: add node op... |
78 79 80 |
static void clear_node_page_dirty(struct page *page) { struct address_space *mapping = page->mapping; |
e05df3b11 f2fs: add node op... |
81 82 83 84 85 86 87 88 89 90 |
unsigned int long flags; if (PageDirty(page)) { spin_lock_irqsave(&mapping->tree_lock, flags); radix_tree_tag_clear(&mapping->page_tree, page_index(page), PAGECACHE_TAG_DIRTY); spin_unlock_irqrestore(&mapping->tree_lock, flags); clear_page_dirty_for_io(page); |
4081363fb f2fs: introduce F... |
91 |
dec_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_NODES); |
e05df3b11 f2fs: add node op... |
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
} ClearPageUptodate(page); } static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) { pgoff_t index = current_nat_addr(sbi, nid); return get_meta_page(sbi, index); } static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) { struct page *src_page; struct page *dst_page; pgoff_t src_off; pgoff_t dst_off; void *src_addr; void *dst_addr; struct f2fs_nm_info *nm_i = NM_I(sbi); src_off = current_nat_addr(sbi, nid); dst_off = next_nat_addr(sbi, src_off); /* get current nat block page with lock */ src_page = get_meta_page(sbi, src_off); |
e05df3b11 f2fs: add node op... |
117 |
dst_page = grab_meta_page(sbi, dst_off); |
9850cf4a8 f2fs: need fsck.f... |
118 |
f2fs_bug_on(sbi, PageDirty(src_page)); |
e05df3b11 f2fs: add node op... |
119 120 121 |
src_addr = page_address(src_page); dst_addr = page_address(dst_page); |
09cbfeaf1 mm, fs: get rid o... |
122 |
memcpy(dst_addr, src_addr, PAGE_SIZE); |
e05df3b11 f2fs: add node op... |
123 124 125 126 127 128 129 |
set_page_dirty(dst_page); f2fs_put_page(src_page, 1); set_to_next_nat(nm_i, nid); return dst_page; } |
e05df3b11 f2fs: add node op... |
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 |
static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) { return radix_tree_lookup(&nm_i->nat_root, n); } static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t start, unsigned int nr, struct nat_entry **ep) { return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); } static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) { list_del(&e->list); radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); nm_i->nat_cnt--; kmem_cache_free(nat_entry_slab, e); } |
309cc2b6e f2fs: refactor fl... |
148 149 150 151 152 153 154 155 |
static void __set_nat_cache_dirty(struct f2fs_nm_info *nm_i, struct nat_entry *ne) { nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); struct nat_entry_set *head; if (get_nat_flag(ne, IS_DIRTY)) return; |
9be32d72b f2fs: do retry op... |
156 |
|
309cc2b6e f2fs: refactor fl... |
157 158 |
head = radix_tree_lookup(&nm_i->nat_set_root, set); if (!head) { |
80c545055 f2fs: use __GFP_N... |
159 |
head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS); |
309cc2b6e f2fs: refactor fl... |
160 161 162 163 164 |
INIT_LIST_HEAD(&head->entry_list); INIT_LIST_HEAD(&head->set_list); head->set = set; head->entry_cnt = 0; |
9be32d72b f2fs: do retry op... |
165 |
f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head); |
309cc2b6e f2fs: refactor fl... |
166 167 168 169 170 171 172 173 174 175 |
} list_move_tail(&ne->list, &head->entry_list); nm_i->dirty_nat_cnt++; head->entry_cnt++; set_nat_flag(ne, IS_DIRTY, true); } static void __clear_nat_cache_dirty(struct f2fs_nm_info *nm_i, struct nat_entry *ne) { |
20d047c87 f2fs: check dirty... |
176 |
nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid); |
309cc2b6e f2fs: refactor fl... |
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
struct nat_entry_set *head; head = radix_tree_lookup(&nm_i->nat_set_root, set); if (head) { list_move_tail(&ne->list, &nm_i->nat_entries); set_nat_flag(ne, IS_DIRTY, false); head->entry_cnt--; nm_i->dirty_nat_cnt--; } } static unsigned int __gang_lookup_nat_set(struct f2fs_nm_info *nm_i, nid_t start, unsigned int nr, struct nat_entry_set **ep) { return radix_tree_gang_lookup(&nm_i->nat_set_root, (void **)ep, start, nr); } |
2dcf51ab2 f2fs: add need_de... |
194 |
int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid) |
e05df3b11 f2fs: add node op... |
195 196 197 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); struct nat_entry *e; |
2dcf51ab2 f2fs: add need_de... |
198 |
bool need = false; |
e05df3b11 f2fs: add node op... |
199 |
|
b873b798a Revert "f2fs: use... |
200 |
down_read(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
201 |
e = __lookup_nat_cache(nm_i, nid); |
2dcf51ab2 f2fs: add need_de... |
202 203 204 205 206 |
if (e) { if (!get_nat_flag(e, IS_CHECKPOINTED) && !get_nat_flag(e, HAS_FSYNCED_INODE)) need = true; } |
b873b798a Revert "f2fs: use... |
207 |
up_read(&nm_i->nat_tree_lock); |
2dcf51ab2 f2fs: add need_de... |
208 |
return need; |
e05df3b11 f2fs: add node op... |
209 |
} |
2dcf51ab2 f2fs: add need_de... |
210 |
bool is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) |
479f40c44 f2fs: skip unnece... |
211 212 213 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); struct nat_entry *e; |
2dcf51ab2 f2fs: add need_de... |
214 |
bool is_cp = true; |
479f40c44 f2fs: skip unnece... |
215 |
|
b873b798a Revert "f2fs: use... |
216 |
down_read(&nm_i->nat_tree_lock); |
2dcf51ab2 f2fs: add need_de... |
217 218 219 |
e = __lookup_nat_cache(nm_i, nid); if (e && !get_nat_flag(e, IS_CHECKPOINTED)) is_cp = false; |
b873b798a Revert "f2fs: use... |
220 |
up_read(&nm_i->nat_tree_lock); |
2dcf51ab2 f2fs: add need_de... |
221 |
return is_cp; |
479f40c44 f2fs: skip unnece... |
222 |
} |
88bd02c94 f2fs: fix conditi... |
223 |
bool need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino) |
b6fe5873c f2fs: fix to reco... |
224 225 226 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); struct nat_entry *e; |
88bd02c94 f2fs: fix conditi... |
227 |
bool need_update = true; |
b6fe5873c f2fs: fix to reco... |
228 |
|
b873b798a Revert "f2fs: use... |
229 |
down_read(&nm_i->nat_tree_lock); |
88bd02c94 f2fs: fix conditi... |
230 231 232 233 234 |
e = __lookup_nat_cache(nm_i, ino); if (e && get_nat_flag(e, HAS_LAST_FSYNC) && (get_nat_flag(e, IS_CHECKPOINTED) || get_nat_flag(e, HAS_FSYNCED_INODE))) need_update = false; |
b873b798a Revert "f2fs: use... |
235 |
up_read(&nm_i->nat_tree_lock); |
88bd02c94 f2fs: fix conditi... |
236 |
return need_update; |
b6fe5873c f2fs: fix to reco... |
237 |
} |
e05df3b11 f2fs: add node op... |
238 239 240 |
static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) { struct nat_entry *new; |
80c545055 f2fs: use __GFP_N... |
241 |
new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_NOFS); |
9be32d72b f2fs: do retry op... |
242 |
f2fs_radix_tree_insert(&nm_i->nat_root, nid, new); |
e05df3b11 f2fs: add node op... |
243 244 |
memset(new, 0, sizeof(struct nat_entry)); nat_set_nid(new, nid); |
88bd02c94 f2fs: fix conditi... |
245 |
nat_reset_flag(new); |
e05df3b11 f2fs: add node op... |
246 247 248 249 |
list_add_tail(&new->list, &nm_i->nat_entries); nm_i->nat_cnt++; return new; } |
1515aef01 f2fs: reorder nat... |
250 |
static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, |
e05df3b11 f2fs: add node op... |
251 252 |
struct f2fs_nat_entry *ne) { |
1515aef01 f2fs: reorder nat... |
253 |
struct f2fs_nm_info *nm_i = NM_I(sbi); |
e05df3b11 f2fs: add node op... |
254 |
struct nat_entry *e; |
9be32d72b f2fs: do retry op... |
255 |
|
e05df3b11 f2fs: add node op... |
256 257 258 |
e = __lookup_nat_cache(nm_i, nid); if (!e) { e = grab_nat_entry(nm_i, nid); |
94dac22e7 f2fs: introduce r... |
259 |
node_info_from_raw_nat(&e->ni, ne); |
1515aef01 f2fs: reorder nat... |
260 261 262 263 |
} else { f2fs_bug_on(sbi, nat_get_ino(e) != ne->ino || nat_get_blkaddr(e) != ne->block_addr || nat_get_version(e) != ne->version); |
e05df3b11 f2fs: add node op... |
264 |
} |
e05df3b11 f2fs: add node op... |
265 266 267 |
} static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, |
479f40c44 f2fs: skip unnece... |
268 |
block_t new_blkaddr, bool fsync_done) |
e05df3b11 f2fs: add node op... |
269 270 271 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); struct nat_entry *e; |
9be32d72b f2fs: do retry op... |
272 |
|
b873b798a Revert "f2fs: use... |
273 |
down_write(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
274 275 276 |
e = __lookup_nat_cache(nm_i, ni->nid); if (!e) { e = grab_nat_entry(nm_i, ni->nid); |
5c27f4ee4 f2fs: merge two u... |
277 |
copy_node_info(&e->ni, ni); |
9850cf4a8 f2fs: need fsck.f... |
278 |
f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR); |
e05df3b11 f2fs: add node op... |
279 280 281 282 283 284 |
} else if (new_blkaddr == NEW_ADDR) { /* * when nid is reallocated, * previous nat entry can be remained in nat cache. * So, reinitialize it with new information. */ |
5c27f4ee4 f2fs: merge two u... |
285 |
copy_node_info(&e->ni, ni); |
9850cf4a8 f2fs: need fsck.f... |
286 |
f2fs_bug_on(sbi, ni->blk_addr != NULL_ADDR); |
e05df3b11 f2fs: add node op... |
287 |
} |
e05df3b11 f2fs: add node op... |
288 |
/* sanity check */ |
9850cf4a8 f2fs: need fsck.f... |
289 290 |
f2fs_bug_on(sbi, nat_get_blkaddr(e) != ni->blk_addr); f2fs_bug_on(sbi, nat_get_blkaddr(e) == NULL_ADDR && |
e05df3b11 f2fs: add node op... |
291 |
new_blkaddr == NULL_ADDR); |
9850cf4a8 f2fs: need fsck.f... |
292 |
f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR && |
e05df3b11 f2fs: add node op... |
293 |
new_blkaddr == NEW_ADDR); |
9850cf4a8 f2fs: need fsck.f... |
294 |
f2fs_bug_on(sbi, nat_get_blkaddr(e) != NEW_ADDR && |
e05df3b11 f2fs: add node op... |
295 296 |
nat_get_blkaddr(e) != NULL_ADDR && new_blkaddr == NEW_ADDR); |
e1c420452 f2fs: fix typo |
297 |
/* increment version no as node is removed */ |
e05df3b11 f2fs: add node op... |
298 299 300 |
if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { unsigned char version = nat_get_version(e); nat_set_version(e, inc_node_version(version)); |
268344664 f2fs: reuse nids ... |
301 302 303 304 |
/* in order to reuse the nid */ if (nm_i->next_scan_nid > ni->nid) nm_i->next_scan_nid = ni->nid; |
e05df3b11 f2fs: add node op... |
305 306 307 308 |
} /* change address */ nat_set_blkaddr(e, new_blkaddr); |
88bd02c94 f2fs: fix conditi... |
309 310 |
if (new_blkaddr == NEW_ADDR || new_blkaddr == NULL_ADDR) set_nat_flag(e, IS_CHECKPOINTED, false); |
e05df3b11 f2fs: add node op... |
311 |
__set_nat_cache_dirty(nm_i, e); |
479f40c44 f2fs: skip unnece... |
312 313 |
/* update fsync_mark if its inode nat entry is still alive */ |
d5b692b78 f2fs: do not re-l... |
314 315 |
if (ni->nid != ni->ino) e = __lookup_nat_cache(nm_i, ni->ino); |
88bd02c94 f2fs: fix conditi... |
316 317 318 319 320 |
if (e) { if (fsync_done && ni->nid == ni->ino) set_nat_flag(e, HAS_FSYNCED_INODE, true); set_nat_flag(e, HAS_LAST_FSYNC, fsync_done); } |
b873b798a Revert "f2fs: use... |
321 |
up_write(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
322 |
} |
4660f9c0f f2fs: introduce f... |
323 |
int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) |
e05df3b11 f2fs: add node op... |
324 325 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); |
1b38dc8e7 f2fs: shrink nat_... |
326 |
int nr = nr_shrink; |
e05df3b11 f2fs: add node op... |
327 |
|
b873b798a Revert "f2fs: use... |
328 329 |
if (!down_write_trylock(&nm_i->nat_tree_lock)) return 0; |
e05df3b11 f2fs: add node op... |
330 |
|
e05df3b11 f2fs: add node op... |
331 332 333 334 335 336 337 |
while (nr_shrink && !list_empty(&nm_i->nat_entries)) { struct nat_entry *ne; ne = list_first_entry(&nm_i->nat_entries, struct nat_entry, list); __del_from_nat_cache(nm_i, ne); nr_shrink--; } |
b873b798a Revert "f2fs: use... |
338 |
up_write(&nm_i->nat_tree_lock); |
1b38dc8e7 f2fs: shrink nat_... |
339 |
return nr - nr_shrink; |
e05df3b11 f2fs: add node op... |
340 |
} |
0a8165d7c f2fs: adjust kern... |
341 |
/* |
e1c420452 f2fs: fix typo |
342 |
* This function always returns success |
e05df3b11 f2fs: add node op... |
343 344 345 346 347 |
*/ void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
b7ad7512b f2fs: split journ... |
348 |
struct f2fs_journal *journal = curseg->journal; |
e05df3b11 f2fs: add node op... |
349 350 351 352 353 354 355 356 357 358 |
nid_t start_nid = START_NID(nid); struct f2fs_nat_block *nat_blk; struct page *page = NULL; struct f2fs_nat_entry ne; struct nat_entry *e; int i; ni->nid = nid; /* Check nat cache */ |
b873b798a Revert "f2fs: use... |
359 |
down_read(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
360 361 362 363 364 |
e = __lookup_nat_cache(nm_i, nid); if (e) { ni->ino = nat_get_ino(e); ni->blk_addr = nat_get_blkaddr(e); ni->version = nat_get_version(e); |
b873b798a Revert "f2fs: use... |
365 |
up_read(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
366 |
return; |
1515aef01 f2fs: reorder nat... |
367 |
} |
e05df3b11 f2fs: add node op... |
368 |
|
3547ea961 f2fs: avoid poten... |
369 |
memset(&ne, 0, sizeof(struct f2fs_nat_entry)); |
e05df3b11 f2fs: add node op... |
370 |
/* Check current segment summary */ |
b7ad7512b f2fs: split journ... |
371 |
down_read(&curseg->journal_rwsem); |
dfc08a12e f2fs: introduce f... |
372 |
i = lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0); |
e05df3b11 f2fs: add node op... |
373 |
if (i >= 0) { |
dfc08a12e f2fs: introduce f... |
374 |
ne = nat_in_journal(journal, i); |
e05df3b11 f2fs: add node op... |
375 376 |
node_info_from_raw_nat(ni, &ne); } |
b7ad7512b f2fs: split journ... |
377 |
up_read(&curseg->journal_rwsem); |
e05df3b11 f2fs: add node op... |
378 379 380 381 382 383 384 385 386 387 |
if (i >= 0) goto cache; /* Fill node_info from nat page */ page = get_current_nat_page(sbi, start_nid); nat_blk = (struct f2fs_nat_block *)page_address(page); ne = nat_blk->entries[nid - start_nid]; node_info_from_raw_nat(ni, &ne); f2fs_put_page(page, 1); cache: |
b873b798a Revert "f2fs: use... |
388 |
up_read(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
389 |
/* cache nat entry */ |
b873b798a Revert "f2fs: use... |
390 |
down_write(&nm_i->nat_tree_lock); |
1515aef01 f2fs: reorder nat... |
391 |
cache_nat_entry(sbi, nid, &ne); |
b873b798a Revert "f2fs: use... |
392 |
up_write(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
393 |
} |
79344efb9 f2fs: read node b... |
394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 |
/* * readahead MAX_RA_NODE number of node pages. */ static void ra_node_pages(struct page *parent, int start, int n) { struct f2fs_sb_info *sbi = F2FS_P_SB(parent); struct blk_plug plug; int i, end; nid_t nid; blk_start_plug(&plug); /* Then, try readahead for siblings of the desired node */ end = start + n; end = min(end, NIDS_PER_BLOCK); for (i = start; i < end; i++) { nid = get_nid(parent, i, false); ra_node_page(sbi, nid); } blk_finish_plug(&plug); } |
3cf457470 f2fs: introduce g... |
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
pgoff_t get_next_page_offset(struct dnode_of_data *dn, pgoff_t pgofs) { const long direct_index = ADDRS_PER_INODE(dn->inode); const long direct_blks = ADDRS_PER_BLOCK; const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; unsigned int skipped_unit = ADDRS_PER_BLOCK; int cur_level = dn->cur_level; int max_level = dn->max_level; pgoff_t base = 0; if (!dn->max_level) return pgofs + 1; while (max_level-- > cur_level) skipped_unit *= NIDS_PER_BLOCK; switch (dn->max_level) { case 3: base += 2 * indirect_blks; case 2: base += 2 * direct_blks; case 1: base += direct_index; break; default: f2fs_bug_on(F2FS_I_SB(dn->inode), 1); } return ((pgofs - base) / skipped_unit + 1) * skipped_unit + base; } |
0a8165d7c f2fs: adjust kern... |
446 |
/* |
e05df3b11 f2fs: add node op... |
447 448 449 |
* The maximum depth is four. * Offset[0] will have raw inode offset. */ |
81ca7350c f2fs: remove unne... |
450 |
static int get_node_path(struct inode *inode, long block, |
de93653fe f2fs: reserve the... |
451 |
int offset[4], unsigned int noffset[4]) |
e05df3b11 f2fs: add node op... |
452 |
{ |
81ca7350c f2fs: remove unne... |
453 |
const long direct_index = ADDRS_PER_INODE(inode); |
e05df3b11 f2fs: add node op... |
454 455 456 457 458 459 460 461 462 463 |
const long direct_blks = ADDRS_PER_BLOCK; const long dptrs_per_blk = NIDS_PER_BLOCK; const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; int n = 0; int level = 0; noffset[0] = 0; if (block < direct_index) { |
25c0a6e52 f2fs: avoid extra... |
464 |
offset[n] = block; |
e05df3b11 f2fs: add node op... |
465 466 467 468 469 470 |
goto got; } block -= direct_index; if (block < direct_blks) { offset[n++] = NODE_DIR1_BLOCK; noffset[n] = 1; |
25c0a6e52 f2fs: avoid extra... |
471 |
offset[n] = block; |
e05df3b11 f2fs: add node op... |
472 473 474 475 476 477 478 |
level = 1; goto got; } block -= direct_blks; if (block < direct_blks) { offset[n++] = NODE_DIR2_BLOCK; noffset[n] = 2; |
25c0a6e52 f2fs: avoid extra... |
479 |
offset[n] = block; |
e05df3b11 f2fs: add node op... |
480 481 482 483 484 485 486 487 488 |
level = 1; goto got; } block -= direct_blks; if (block < indirect_blks) { offset[n++] = NODE_IND1_BLOCK; noffset[n] = 3; offset[n++] = block / direct_blks; noffset[n] = 4 + offset[n - 1]; |
25c0a6e52 f2fs: avoid extra... |
489 |
offset[n] = block % direct_blks; |
e05df3b11 f2fs: add node op... |
490 491 492 493 494 495 496 497 498 |
level = 2; goto got; } block -= indirect_blks; if (block < indirect_blks) { offset[n++] = NODE_IND2_BLOCK; noffset[n] = 4 + dptrs_per_blk; offset[n++] = block / direct_blks; noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; |
25c0a6e52 f2fs: avoid extra... |
499 |
offset[n] = block % direct_blks; |
e05df3b11 f2fs: add node op... |
500 501 502 503 504 505 506 507 508 509 510 511 512 513 |
level = 2; goto got; } block -= indirect_blks; if (block < dindirect_blks) { offset[n++] = NODE_DIND_BLOCK; noffset[n] = 5 + (dptrs_per_blk * 2); offset[n++] = block / indirect_blks; noffset[n] = 6 + (dptrs_per_blk * 2) + offset[n - 1] * (dptrs_per_blk + 1); offset[n++] = (block / direct_blks) % dptrs_per_blk; noffset[n] = 7 + (dptrs_per_blk * 2) + offset[n - 2] * (dptrs_per_blk + 1) + offset[n - 1]; |
25c0a6e52 f2fs: avoid extra... |
514 |
offset[n] = block % direct_blks; |
e05df3b11 f2fs: add node op... |
515 516 517 518 519 520 521 522 523 524 525 |
level = 3; goto got; } else { BUG(); } got: return level; } /* * Caller should call f2fs_put_dnode(dn). |
4f4124d0b f2fs: update seve... |
526 527 |
* Also, it should grab and release a rwsem by calling f2fs_lock_op() and * f2fs_unlock_op() only if ro is not set RDONLY_NODE. |
399368372 f2fs: introduce a... |
528 |
* In the case of RDONLY_NODE, we don't need to care about mutex. |
e05df3b11 f2fs: add node op... |
529 |
*/ |
266e97a81 f2fs: introduce r... |
530 |
int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) |
e05df3b11 f2fs: add node op... |
531 |
{ |
4081363fb f2fs: introduce F... |
532 |
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); |
e05df3b11 f2fs: add node op... |
533 |
struct page *npage[4]; |
f1a3b98e7 f2fs: fix accessi... |
534 |
struct page *parent = NULL; |
e05df3b11 f2fs: add node op... |
535 536 537 |
int offset[4]; unsigned int noffset[4]; nid_t nids[4]; |
3cf457470 f2fs: introduce g... |
538 |
int level, i = 0; |
e05df3b11 f2fs: add node op... |
539 |
int err = 0; |
81ca7350c f2fs: remove unne... |
540 |
level = get_node_path(dn->inode, index, offset, noffset); |
e05df3b11 f2fs: add node op... |
541 542 |
nids[0] = dn->inode->i_ino; |
1646cfac9 f2fs: skip get_no... |
543 |
npage[0] = dn->inode_page; |
e05df3b11 f2fs: add node op... |
544 |
|
1646cfac9 f2fs: skip get_no... |
545 546 547 548 549 |
if (!npage[0]) { npage[0] = get_node_page(sbi, nids[0]); if (IS_ERR(npage[0])) return PTR_ERR(npage[0]); } |
f1a3b98e7 f2fs: fix accessi... |
550 551 552 |
/* if inline_data is set, should not report any block indices */ if (f2fs_has_inline_data(dn->inode) && index) { |
766291659 f2fs: report -ENO... |
553 |
err = -ENOENT; |
f1a3b98e7 f2fs: fix accessi... |
554 555 556 |
f2fs_put_page(npage[0], 1); goto release_out; } |
e05df3b11 f2fs: add node op... |
557 |
parent = npage[0]; |
52c2db3f9 f2fs: check the l... |
558 559 |
if (level != 0) nids[1] = get_nid(parent, offset[0], true); |
e05df3b11 f2fs: add node op... |
560 561 562 563 564 565 |
dn->inode_page = npage[0]; dn->inode_page_locked = true; /* get indirect or direct nodes */ for (i = 1; i <= level; i++) { bool done = false; |
266e97a81 f2fs: introduce r... |
566 |
if (!nids[i] && mode == ALLOC_NODE) { |
e05df3b11 f2fs: add node op... |
567 568 |
/* alloc new node */ if (!alloc_nid(sbi, &(nids[i]))) { |
e05df3b11 f2fs: add node op... |
569 570 571 572 573 |
err = -ENOSPC; goto release_pages; } dn->nid = nids[i]; |
8ae8f1627 f2fs: support xat... |
574 |
npage[i] = new_node_page(dn, noffset[i], NULL); |
e05df3b11 f2fs: add node op... |
575 576 |
if (IS_ERR(npage[i])) { alloc_nid_failed(sbi, nids[i]); |
e05df3b11 f2fs: add node op... |
577 578 579 580 581 582 |
err = PTR_ERR(npage[i]); goto release_pages; } set_nid(parent, offset[i - 1], nids[i], i == 1); alloc_nid_done(sbi, nids[i]); |
e05df3b11 f2fs: add node op... |
583 |
done = true; |
266e97a81 f2fs: introduce r... |
584 |
} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { |
e05df3b11 f2fs: add node op... |
585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 |
npage[i] = get_node_page_ra(parent, offset[i - 1]); if (IS_ERR(npage[i])) { err = PTR_ERR(npage[i]); goto release_pages; } done = true; } if (i == 1) { dn->inode_page_locked = false; unlock_page(parent); } else { f2fs_put_page(parent, 1); } if (!done) { npage[i] = get_node_page(sbi, nids[i]); if (IS_ERR(npage[i])) { err = PTR_ERR(npage[i]); f2fs_put_page(npage[0], 0); goto release_out; } } if (i < level) { parent = npage[i]; nids[i + 1] = get_nid(parent, offset[i], false); } } dn->nid = nids[level]; dn->ofs_in_node = offset[level]; dn->node_page = npage[level]; dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node); return 0; release_pages: f2fs_put_page(parent, 1); if (i > 1) f2fs_put_page(npage[0], 0); release_out: dn->inode_page = NULL; dn->node_page = NULL; |
3cf457470 f2fs: introduce g... |
625 626 627 |
if (err == -ENOENT) { dn->cur_level = i; dn->max_level = level; |
0a2aa8fbb f2fs: refactor __... |
628 |
dn->ofs_in_node = offset[level]; |
3cf457470 f2fs: introduce g... |
629 |
} |
e05df3b11 f2fs: add node op... |
630 631 632 633 634 |
return err; } static void truncate_node(struct dnode_of_data *dn) { |
4081363fb f2fs: introduce F... |
635 |
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); |
e05df3b11 f2fs: add node op... |
636 637 638 |
struct node_info ni; get_node_info(sbi, dn->nid, &ni); |
71e9fec54 f2fs: invalidate ... |
639 |
if (dn->inode->i_blocks == 0) { |
9850cf4a8 f2fs: need fsck.f... |
640 |
f2fs_bug_on(sbi, ni.blk_addr != NULL_ADDR); |
71e9fec54 f2fs: invalidate ... |
641 642 |
goto invalidate; } |
9850cf4a8 f2fs: need fsck.f... |
643 |
f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); |
e05df3b11 f2fs: add node op... |
644 |
|
e05df3b11 f2fs: add node op... |
645 |
/* Deallocate node address */ |
71e9fec54 f2fs: invalidate ... |
646 |
invalidate_blocks(sbi, ni.blk_addr); |
ef86d7099 f2fs: convert inc... |
647 |
dec_valid_node_count(sbi, dn->inode); |
479f40c44 f2fs: skip unnece... |
648 |
set_node_addr(sbi, &ni, NULL_ADDR, false); |
e05df3b11 f2fs: add node op... |
649 650 651 652 |
if (dn->nid == dn->inode->i_ino) { remove_orphan_inode(sbi, dn->nid); dec_valid_inode_count(sbi); |
0f18b462b f2fs: flush inode... |
653 |
f2fs_inode_synced(dn->inode); |
e05df3b11 f2fs: add node op... |
654 |
} |
71e9fec54 f2fs: invalidate ... |
655 |
invalidate: |
e05df3b11 f2fs: add node op... |
656 |
clear_node_page_dirty(dn->node_page); |
caf0047e7 f2fs: merge flags... |
657 |
set_sbi_flag(sbi, SBI_IS_DIRTY); |
e05df3b11 f2fs: add node op... |
658 659 |
f2fs_put_page(dn->node_page, 1); |
bf39c00a9 f2fs: drop obsole... |
660 661 662 |
invalidate_mapping_pages(NODE_MAPPING(sbi), dn->node_page->index, dn->node_page->index); |
e05df3b11 f2fs: add node op... |
663 |
dn->node_page = NULL; |
51dd62493 f2fs: add tracepo... |
664 |
trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); |
e05df3b11 f2fs: add node op... |
665 666 667 668 |
} static int truncate_dnode(struct dnode_of_data *dn) { |
e05df3b11 f2fs: add node op... |
669 670 671 672 673 674 |
struct page *page; if (dn->nid == 0) return 1; /* get direct node */ |
4081363fb f2fs: introduce F... |
675 |
page = get_node_page(F2FS_I_SB(dn->inode), dn->nid); |
e05df3b11 f2fs: add node op... |
676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 |
if (IS_ERR(page) && PTR_ERR(page) == -ENOENT) return 1; else if (IS_ERR(page)) return PTR_ERR(page); /* Make dnode_of_data for parameter */ dn->node_page = page; dn->ofs_in_node = 0; truncate_data_blocks(dn); truncate_node(dn); return 1; } static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, int ofs, int depth) { |
e05df3b11 f2fs: add node op... |
692 693 694 695 696 697 698 699 700 701 |
struct dnode_of_data rdn = *dn; struct page *page; struct f2fs_node *rn; nid_t child_nid; unsigned int child_nofs; int freed = 0; int i, ret; if (dn->nid == 0) return NIDS_PER_BLOCK + 1; |
51dd62493 f2fs: add tracepo... |
702 |
trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); |
4081363fb f2fs: introduce F... |
703 |
page = get_node_page(F2FS_I_SB(dn->inode), dn->nid); |
51dd62493 f2fs: add tracepo... |
704 705 |
if (IS_ERR(page)) { trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); |
e05df3b11 f2fs: add node op... |
706 |
return PTR_ERR(page); |
51dd62493 f2fs: add tracepo... |
707 |
} |
e05df3b11 f2fs: add node op... |
708 |
|
79344efb9 f2fs: read node b... |
709 |
ra_node_pages(page, ofs, NIDS_PER_BLOCK); |
455907106 f2fs: introduce h... |
710 |
rn = F2FS_NODE(page); |
e05df3b11 f2fs: add node op... |
711 712 713 714 715 716 717 718 719 |
if (depth < 3) { for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { child_nid = le32_to_cpu(rn->in.nid[i]); if (child_nid == 0) continue; rdn.nid = child_nid; ret = truncate_dnode(&rdn); if (ret < 0) goto out_err; |
12719ae14 f2fs: avoid unnec... |
720 721 |
if (set_nid(page, i, 0, false)) dn->node_changed = true; |
e05df3b11 f2fs: add node op... |
722 723 724 725 726 727 728 729 730 731 732 733 |
} } else { child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; for (i = ofs; i < NIDS_PER_BLOCK; i++) { child_nid = le32_to_cpu(rn->in.nid[i]); if (child_nid == 0) { child_nofs += NIDS_PER_BLOCK + 1; continue; } rdn.nid = child_nid; ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); if (ret == (NIDS_PER_BLOCK + 1)) { |
12719ae14 f2fs: avoid unnec... |
734 735 |
if (set_nid(page, i, 0, false)) dn->node_changed = true; |
e05df3b11 f2fs: add node op... |
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 |
child_nofs += ret; } else if (ret < 0 && ret != -ENOENT) { goto out_err; } } freed = child_nofs; } if (!ofs) { /* remove current indirect node */ dn->node_page = page; truncate_node(dn); freed++; } else { f2fs_put_page(page, 1); } |
51dd62493 f2fs: add tracepo... |
752 |
trace_f2fs_truncate_nodes_exit(dn->inode, freed); |
e05df3b11 f2fs: add node op... |
753 754 755 756 |
return freed; out_err: f2fs_put_page(page, 1); |
51dd62493 f2fs: add tracepo... |
757 |
trace_f2fs_truncate_nodes_exit(dn->inode, ret); |
e05df3b11 f2fs: add node op... |
758 759 760 761 762 763 |
return ret; } static int truncate_partial_nodes(struct dnode_of_data *dn, struct f2fs_inode *ri, int *offset, int depth) { |
e05df3b11 f2fs: add node op... |
764 765 766 767 768 769 770 771 772 773 774 775 |
struct page *pages[2]; nid_t nid[3]; nid_t child_nid; int err = 0; int i; int idx = depth - 2; nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); if (!nid[0]) return 0; /* get indirect nodes in the path */ |
a225dca39 f2fs: fix truncat... |
776 |
for (i = 0; i < idx + 1; i++) { |
e1c420452 f2fs: fix typo |
777 |
/* reference count'll be increased */ |
4081363fb f2fs: introduce F... |
778 |
pages[i] = get_node_page(F2FS_I_SB(dn->inode), nid[i]); |
e05df3b11 f2fs: add node op... |
779 |
if (IS_ERR(pages[i])) { |
e05df3b11 f2fs: add node op... |
780 |
err = PTR_ERR(pages[i]); |
a225dca39 f2fs: fix truncat... |
781 |
idx = i - 1; |
e05df3b11 f2fs: add node op... |
782 783 784 785 |
goto fail; } nid[i + 1] = get_nid(pages[i], offset[i + 1], false); } |
79344efb9 f2fs: read node b... |
786 |
ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK); |
e05df3b11 f2fs: add node op... |
787 |
/* free direct nodes linked to a partial indirect node */ |
a225dca39 f2fs: fix truncat... |
788 |
for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) { |
e05df3b11 f2fs: add node op... |
789 790 791 792 793 794 795 |
child_nid = get_nid(pages[idx], i, false); if (!child_nid) continue; dn->nid = child_nid; err = truncate_dnode(dn); if (err < 0) goto fail; |
12719ae14 f2fs: avoid unnec... |
796 797 |
if (set_nid(pages[idx], i, 0, false)) dn->node_changed = true; |
e05df3b11 f2fs: add node op... |
798 |
} |
a225dca39 f2fs: fix truncat... |
799 |
if (offset[idx + 1] == 0) { |
e05df3b11 f2fs: add node op... |
800 801 802 803 804 805 806 |
dn->node_page = pages[idx]; dn->nid = nid[idx]; truncate_node(dn); } else { f2fs_put_page(pages[idx], 1); } offset[idx]++; |
a225dca39 f2fs: fix truncat... |
807 808 |
offset[idx + 1] = 0; idx--; |
e05df3b11 f2fs: add node op... |
809 |
fail: |
a225dca39 f2fs: fix truncat... |
810 |
for (i = idx; i >= 0; i--) |
e05df3b11 f2fs: add node op... |
811 |
f2fs_put_page(pages[i], 1); |
51dd62493 f2fs: add tracepo... |
812 813 |
trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); |
e05df3b11 f2fs: add node op... |
814 815 |
return err; } |
0a8165d7c f2fs: adjust kern... |
816 |
/* |
e05df3b11 f2fs: add node op... |
817 818 819 820 |
* All the block addresses of data and nodes should be nullified. */ int truncate_inode_blocks(struct inode *inode, pgoff_t from) { |
4081363fb f2fs: introduce F... |
821 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
e05df3b11 f2fs: add node op... |
822 823 |
int err = 0, cont = 1; int level, offset[4], noffset[4]; |
7dd690c82 f2fs: avoid build... |
824 |
unsigned int nofs = 0; |
58bfaf44d f2fs: introduce F... |
825 |
struct f2fs_inode *ri; |
e05df3b11 f2fs: add node op... |
826 827 |
struct dnode_of_data dn; struct page *page; |
51dd62493 f2fs: add tracepo... |
828 |
trace_f2fs_truncate_inode_blocks_enter(inode, from); |
81ca7350c f2fs: remove unne... |
829 |
level = get_node_path(inode, from, offset, noffset); |
ff3735588 f2fs: add BUG_ON ... |
830 |
|
e05df3b11 f2fs: add node op... |
831 |
page = get_node_page(sbi, inode->i_ino); |
51dd62493 f2fs: add tracepo... |
832 833 |
if (IS_ERR(page)) { trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); |
e05df3b11 f2fs: add node op... |
834 |
return PTR_ERR(page); |
51dd62493 f2fs: add tracepo... |
835 |
} |
e05df3b11 f2fs: add node op... |
836 837 838 |
set_new_dnode(&dn, inode, page, NULL, 0); unlock_page(page); |
58bfaf44d f2fs: introduce F... |
839 |
ri = F2FS_INODE(page); |
e05df3b11 f2fs: add node op... |
840 841 842 843 844 845 846 847 848 |
switch (level) { case 0: case 1: nofs = noffset[1]; break; case 2: nofs = noffset[1]; if (!offset[level - 1]) goto skip_partial; |
58bfaf44d f2fs: introduce F... |
849 |
err = truncate_partial_nodes(&dn, ri, offset, level); |
e05df3b11 f2fs: add node op... |
850 851 852 853 854 855 856 857 |
if (err < 0 && err != -ENOENT) goto fail; nofs += 1 + NIDS_PER_BLOCK; break; case 3: nofs = 5 + 2 * NIDS_PER_BLOCK; if (!offset[level - 1]) goto skip_partial; |
58bfaf44d f2fs: introduce F... |
858 |
err = truncate_partial_nodes(&dn, ri, offset, level); |
e05df3b11 f2fs: add node op... |
859 860 861 862 863 864 865 866 867 |
if (err < 0 && err != -ENOENT) goto fail; break; default: BUG(); } skip_partial: while (cont) { |
58bfaf44d f2fs: introduce F... |
868 |
dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); |
e05df3b11 f2fs: add node op... |
869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 |
switch (offset[0]) { case NODE_DIR1_BLOCK: case NODE_DIR2_BLOCK: err = truncate_dnode(&dn); break; case NODE_IND1_BLOCK: case NODE_IND2_BLOCK: err = truncate_nodes(&dn, nofs, offset[1], 2); break; case NODE_DIND_BLOCK: err = truncate_nodes(&dn, nofs, offset[1], 3); cont = 0; break; default: BUG(); } if (err < 0 && err != -ENOENT) goto fail; if (offset[1] == 0 && |
58bfaf44d f2fs: introduce F... |
891 |
ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) { |
e05df3b11 f2fs: add node op... |
892 |
lock_page(page); |
ff3735588 f2fs: add BUG_ON ... |
893 |
BUG_ON(page->mapping != NODE_MAPPING(sbi)); |
fec1d6576 f2fs: use wait_fo... |
894 |
f2fs_wait_on_page_writeback(page, NODE, true); |
58bfaf44d f2fs: introduce F... |
895 |
ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; |
e05df3b11 f2fs: add node op... |
896 897 898 899 900 901 902 903 904 |
set_page_dirty(page); unlock_page(page); } offset[1] = 0; offset[0]++; nofs += err; } fail: f2fs_put_page(page, 0); |
51dd62493 f2fs: add tracepo... |
905 |
trace_f2fs_truncate_inode_blocks_exit(inode, err); |
e05df3b11 f2fs: add node op... |
906 907 |
return err > 0 ? 0 : err; } |
4f16fb0f9 f2fs: add the tru... |
908 909 |
int truncate_xattr_node(struct inode *inode, struct page *page) { |
4081363fb f2fs: introduce F... |
910 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
4f16fb0f9 f2fs: add the tru... |
911 912 913 914 915 916 917 918 919 920 |
nid_t nid = F2FS_I(inode)->i_xattr_nid; struct dnode_of_data dn; struct page *npage; if (!nid) return 0; npage = get_node_page(sbi, nid); if (IS_ERR(npage)) return PTR_ERR(npage); |
205b98221 f2fs: call mark_i... |
921 |
f2fs_i_xnid_write(inode, 0); |
65985d935 f2fs: support the... |
922 923 924 |
/* need to do checkpoint during fsync */ F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); |
4f16fb0f9 f2fs: add the tru... |
925 926 927 |
set_new_dnode(&dn, inode, page, npage, nid); if (page) |
01d2d1aa0 f2fs: use true an... |
928 |
dn.inode_page_locked = true; |
4f16fb0f9 f2fs: add the tru... |
929 930 931 |
truncate_node(&dn); return 0; } |
399368372 f2fs: introduce a... |
932 |
/* |
4f4124d0b f2fs: update seve... |
933 934 |
* Caller should grab and release a rwsem by calling f2fs_lock_op() and * f2fs_unlock_op(). |
399368372 f2fs: introduce a... |
935 |
*/ |
13ec7297e f2fs: fix to rele... |
936 |
int remove_inode_page(struct inode *inode) |
e05df3b11 f2fs: add node op... |
937 |
{ |
e05df3b11 f2fs: add node op... |
938 |
struct dnode_of_data dn; |
13ec7297e f2fs: fix to rele... |
939 |
int err; |
e05df3b11 f2fs: add node op... |
940 |
|
c2e69583a f2fs: truncate st... |
941 |
set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); |
13ec7297e f2fs: fix to rele... |
942 943 944 |
err = get_dnode_of_data(&dn, 0, LOOKUP_NODE); if (err) return err; |
e05df3b11 f2fs: add node op... |
945 |
|
13ec7297e f2fs: fix to rele... |
946 947 |
err = truncate_xattr_node(inode, dn.inode_page); if (err) { |
c2e69583a f2fs: truncate st... |
948 |
f2fs_put_dnode(&dn); |
13ec7297e f2fs: fix to rele... |
949 |
return err; |
e05df3b11 f2fs: add node op... |
950 |
} |
c2e69583a f2fs: truncate st... |
951 952 953 954 955 |
/* remove potential inline_data blocks */ if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) truncate_data_blocks_range(&dn, 1); |
e1c420452 f2fs: fix typo |
956 |
/* 0 is possible, after f2fs_new_inode() has failed */ |
9850cf4a8 f2fs: need fsck.f... |
957 958 |
f2fs_bug_on(F2FS_I_SB(inode), inode->i_blocks != 0 && inode->i_blocks != 1); |
c2e69583a f2fs: truncate st... |
959 960 |
/* will put inode & node pages */ |
71e9fec54 f2fs: invalidate ... |
961 |
truncate_node(&dn); |
13ec7297e f2fs: fix to rele... |
962 |
return 0; |
e05df3b11 f2fs: add node op... |
963 |
} |
a014e037b f2fs: clean up an... |
964 |
struct page *new_inode_page(struct inode *inode) |
e05df3b11 f2fs: add node op... |
965 |
{ |
e05df3b11 f2fs: add node op... |
966 967 968 969 |
struct dnode_of_data dn; /* allocate inode page for new inode */ set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); |
44a83ff6a f2fs: update inod... |
970 971 |
/* caller should f2fs_put_page(page, 1); */ |
8ae8f1627 f2fs: support xat... |
972 |
return new_node_page(&dn, 0, NULL); |
e05df3b11 f2fs: add node op... |
973 |
} |
8ae8f1627 f2fs: support xat... |
974 975 |
struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs, struct page *ipage) |
e05df3b11 f2fs: add node op... |
976 |
{ |
4081363fb f2fs: introduce F... |
977 |
struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode); |
e05df3b11 f2fs: add node op... |
978 979 980 |
struct node_info old_ni, new_ni; struct page *page; int err; |
91942321e f2fs: use inode p... |
981 |
if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC))) |
e05df3b11 f2fs: add node op... |
982 |
return ERR_PTR(-EPERM); |
300e129c1 f2fs: use f2fs_gr... |
983 |
page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false); |
e05df3b11 f2fs: add node op... |
984 985 |
if (!page) return ERR_PTR(-ENOMEM); |
6bacf52fb f2fs: add unlikel... |
986 |
if (unlikely(!inc_valid_node_count(sbi, dn->inode))) { |
9c02740c0 f2fs: check the f... |
987 988 989 |
err = -ENOSPC; goto fail; } |
e05df3b11 f2fs: add node op... |
990 |
|
9c02740c0 f2fs: check the f... |
991 |
get_node_info(sbi, dn->nid, &old_ni); |
e05df3b11 f2fs: add node op... |
992 993 |
/* Reinitialize old_ni with new node page */ |
9850cf4a8 f2fs: need fsck.f... |
994 |
f2fs_bug_on(sbi, old_ni.blk_addr != NULL_ADDR); |
e05df3b11 f2fs: add node op... |
995 996 |
new_ni = old_ni; new_ni.ino = dn->inode->i_ino; |
479f40c44 f2fs: skip unnece... |
997 |
set_node_addr(sbi, &new_ni, NEW_ADDR, false); |
9c02740c0 f2fs: check the f... |
998 |
|
fec1d6576 f2fs: use wait_fo... |
999 |
f2fs_wait_on_page_writeback(page, NODE, true); |
9c02740c0 f2fs: check the f... |
1000 |
fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); |
398b1ac5a f2fs: fix handlin... |
1001 |
set_cold_node(dn->inode, page); |
237c0790e f2fs: call SetPag... |
1002 1003 |
if (!PageUptodate(page)) SetPageUptodate(page); |
12719ae14 f2fs: avoid unnec... |
1004 1005 |
if (set_page_dirty(page)) dn->node_changed = true; |
e05df3b11 f2fs: add node op... |
1006 |
|
4bc8e9bcf f2fs: introduce f... |
1007 |
if (f2fs_has_xattr_block(ofs)) |
205b98221 f2fs: call mark_i... |
1008 |
f2fs_i_xnid_write(dn->inode, dn->nid); |
479bd73ac f2fs: should cove... |
1009 |
|
e05df3b11 f2fs: add node op... |
1010 1011 |
if (ofs == 0) inc_valid_inode_count(sbi); |
e05df3b11 f2fs: add node op... |
1012 1013 1014 |
return page; fail: |
71e9fec54 f2fs: invalidate ... |
1015 |
clear_node_page_dirty(page); |
e05df3b11 f2fs: add node op... |
1016 1017 1018 |
f2fs_put_page(page, 1); return ERR_PTR(err); } |
56ae674cc f2fs: remove redu... |
1019 1020 1021 |
/* * Caller should do after getting the following values. * 0: f2fs_put_page(page, 0) |
86531d6b8 f2fs: callers tak... |
1022 |
* LOCKED_PAGE or error: f2fs_put_page(page, 1) |
56ae674cc f2fs: remove redu... |
1023 |
*/ |
04d328def f2fs: use bio op ... |
1024 |
static int read_node_page(struct page *page, int op_flags) |
e05df3b11 f2fs: add node op... |
1025 |
{ |
4081363fb f2fs: introduce F... |
1026 |
struct f2fs_sb_info *sbi = F2FS_P_SB(page); |
e05df3b11 f2fs: add node op... |
1027 |
struct node_info ni; |
cf04e8eb5 f2fs: use f2fs_io... |
1028 |
struct f2fs_io_info fio = { |
05ca3632e f2fs: add sbi and... |
1029 |
.sbi = sbi, |
cf04e8eb5 f2fs: use f2fs_io... |
1030 |
.type = NODE, |
04d328def f2fs: use bio op ... |
1031 1032 |
.op = REQ_OP_READ, .op_flags = op_flags, |
05ca3632e f2fs: add sbi and... |
1033 |
.page = page, |
4375a3366 f2fs crypto: add ... |
1034 |
.encrypted_page = NULL, |
cf04e8eb5 f2fs: use f2fs_io... |
1035 |
}; |
e05df3b11 f2fs: add node op... |
1036 |
|
3bdad3c7e f2fs: skip to che... |
1037 1038 |
if (PageUptodate(page)) return LOCKED_PAGE; |
e05df3b11 f2fs: add node op... |
1039 |
get_node_info(sbi, page->index, &ni); |
6bacf52fb f2fs: add unlikel... |
1040 |
if (unlikely(ni.blk_addr == NULL_ADDR)) { |
2bca1e238 f2fs: clear page'... |
1041 |
ClearPageUptodate(page); |
e05df3b11 f2fs: add node op... |
1042 |
return -ENOENT; |
393ff91f5 f2fs: reduce unnc... |
1043 |
} |
7a9d75481 f2fs: trace old b... |
1044 |
fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr; |
05ca3632e f2fs: add sbi and... |
1045 |
return f2fs_submit_page_bio(&fio); |
e05df3b11 f2fs: add node op... |
1046 |
} |
0a8165d7c f2fs: adjust kern... |
1047 |
/* |
e05df3b11 f2fs: add node op... |
1048 1049 1050 1051 |
* Readahead a node page */ void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) { |
e05df3b11 f2fs: add node op... |
1052 |
struct page *apage; |
56ae674cc f2fs: remove redu... |
1053 |
int err; |
e05df3b11 f2fs: add node op... |
1054 |
|
e84587250 f2fs: check node ... |
1055 1056 1057 |
if (!nid) return; f2fs_bug_on(sbi, check_nid_range(sbi, nid)); |
999270de3 f2fs: modify the ... |
1058 1059 1060 1061 |
rcu_read_lock(); apage = radix_tree_lookup(&NODE_MAPPING(sbi)->page_tree, nid); rcu_read_unlock(); if (apage) |
393ff91f5 f2fs: reduce unnc... |
1062 |
return; |
e05df3b11 f2fs: add node op... |
1063 |
|
300e129c1 f2fs: use f2fs_gr... |
1064 |
apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); |
e05df3b11 f2fs: add node op... |
1065 1066 |
if (!apage) return; |
70246286e block: get rid of... |
1067 |
err = read_node_page(apage, REQ_RAHEAD); |
86531d6b8 f2fs: callers tak... |
1068 |
f2fs_put_page(apage, err ? 1 : 0); |
e05df3b11 f2fs: add node op... |
1069 |
} |
17a0ee552 f2fs: declare sta... |
1070 |
static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid, |
0e022ea8f f2fs: introduce _... |
1071 |
struct page *parent, int start) |
e05df3b11 f2fs: add node op... |
1072 |
{ |
e05df3b11 f2fs: add node op... |
1073 |
struct page *page; |
0e022ea8f f2fs: introduce _... |
1074 |
int err; |
e05df3b11 f2fs: add node op... |
1075 |
|
e05df3b11 f2fs: add node op... |
1076 1077 |
if (!nid) return ERR_PTR(-ENOENT); |
e84587250 f2fs: check node ... |
1078 |
f2fs_bug_on(sbi, check_nid_range(sbi, nid)); |
afcb7ca01 f2fs: check trunc... |
1079 |
repeat: |
300e129c1 f2fs: use f2fs_gr... |
1080 |
page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false); |
e05df3b11 f2fs: add node op... |
1081 1082 |
if (!page) return ERR_PTR(-ENOMEM); |
66d36a294 f2fs: read with R... |
1083 |
err = read_node_page(page, READ_SYNC); |
86531d6b8 f2fs: callers tak... |
1084 1085 |
if (err < 0) { f2fs_put_page(page, 1); |
e05df3b11 f2fs: add node op... |
1086 |
return ERR_PTR(err); |
86531d6b8 f2fs: callers tak... |
1087 |
} else if (err == LOCKED_PAGE) { |
56ae674cc f2fs: remove redu... |
1088 |
goto page_hit; |
86531d6b8 f2fs: callers tak... |
1089 |
} |
e05df3b11 f2fs: add node op... |
1090 |
|
0e022ea8f f2fs: introduce _... |
1091 |
if (parent) |
79344efb9 f2fs: read node b... |
1092 |
ra_node_pages(parent, start + 1, MAX_RA_NODE); |
c718379b6 f2fs: give a chan... |
1093 |
|
e05df3b11 f2fs: add node op... |
1094 |
lock_page(page); |
0e022ea8f f2fs: introduce _... |
1095 |
|
4ef51a8fc f2fs: introduce N... |
1096 |
if (unlikely(page->mapping != NODE_MAPPING(sbi))) { |
afcb7ca01 f2fs: check trunc... |
1097 1098 1099 |
f2fs_put_page(page, 1); goto repeat; } |
1563ac75e f2fs: fix to dete... |
1100 1101 1102 |
if (unlikely(!PageUptodate(page))) goto out_err; |
e0f56cb44 f2fs: optimize ge... |
1103 |
page_hit: |
0c9df7fb8 f2fs: return the ... |
1104 1105 1106 1107 1108 1109 1110 |
if(unlikely(nid != nid_of_node(page))) { f2fs_bug_on(sbi, 1); ClearPageUptodate(page); out_err: f2fs_put_page(page, 1); return ERR_PTR(-EIO); } |
e05df3b11 f2fs: add node op... |
1111 1112 |
return page; } |
0e022ea8f f2fs: introduce _... |
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 |
struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) { return __get_node_page(sbi, nid, NULL, 0); } struct page *get_node_page_ra(struct page *parent, int start) { struct f2fs_sb_info *sbi = F2FS_P_SB(parent); nid_t nid = get_nid(parent, start, false); return __get_node_page(sbi, nid, parent, start); } |
2049d4fcb f2fs: avoid multi... |
1125 1126 1127 1128 |
static void flush_inline_data(struct f2fs_sb_info *sbi, nid_t ino) { struct inode *inode; struct page *page; |
0f3311a8c f2fs: fix to upda... |
1129 |
int ret; |
2049d4fcb f2fs: avoid multi... |
1130 1131 1132 1133 1134 |
/* should flush inline_data before evict_inode */ inode = ilookup(sbi->sb, ino); if (!inode) return; |
4a6de50d5 f2fs: use PGP_LOC... |
1135 |
page = pagecache_get_page(inode->i_mapping, 0, FGP_LOCK|FGP_NOWAIT, 0); |
2049d4fcb f2fs: avoid multi... |
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 |
if (!page) goto iput_out; if (!PageUptodate(page)) goto page_out; if (!PageDirty(page)) goto page_out; if (!clear_page_dirty_for_io(page)) goto page_out; |
0f3311a8c f2fs: fix to upda... |
1147 1148 1149 |
ret = f2fs_write_inline_data(inode, page); inode_dec_dirty_pages(inode); if (ret) |
2049d4fcb f2fs: avoid multi... |
1150 1151 |
set_page_dirty(page); page_out: |
4a6de50d5 f2fs: use PGP_LOC... |
1152 |
f2fs_put_page(page, 1); |
2049d4fcb f2fs: avoid multi... |
1153 1154 1155 |
iput_out: iput(inode); } |
da011cc0d f2fs: move node p... |
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 |
void move_node_page(struct page *node_page, int gc_type) { if (gc_type == FG_GC) { struct f2fs_sb_info *sbi = F2FS_P_SB(node_page); struct writeback_control wbc = { .sync_mode = WB_SYNC_ALL, .nr_to_write = 1, .for_reclaim = 0, }; set_page_dirty(node_page); f2fs_wait_on_page_writeback(node_page, NODE, true); f2fs_bug_on(sbi, PageWriteback(node_page)); if (!clear_page_dirty_for_io(node_page)) goto out_page; if (NODE_MAPPING(sbi)->a_ops->writepage(node_page, &wbc)) unlock_page(node_page); goto release_page; } else { /* set page dirty and write it */ if (!PageWriteback(node_page)) set_page_dirty(node_page); } out_page: unlock_page(node_page); release_page: f2fs_put_page(node_page, 0); } |
608514deb f2fs: set fsync m... |
1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 |
static struct page *last_fsync_dnode(struct f2fs_sb_info *sbi, nid_t ino) { pgoff_t index, end; struct pagevec pvec; struct page *last_page = NULL; pagevec_init(&pvec, 0); index = 0; end = ULONG_MAX; while (index <= end) { int i, nr_pages; nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; if (unlikely(f2fs_cp_error(sbi))) { f2fs_put_page(last_page, 0); pagevec_release(&pvec); return ERR_PTR(-EIO); } if (!IS_DNODE(page) || !is_cold_node(page)) continue; if (ino_of_node(page) != ino) continue; lock_page(page); if (unlikely(page->mapping != NODE_MAPPING(sbi))) { continue_unlock: unlock_page(page); continue; } if (ino_of_node(page) != ino) goto continue_unlock; if (!PageDirty(page)) { /* someone wrote it for us */ goto continue_unlock; } if (last_page) f2fs_put_page(last_page, 0); get_page(page); last_page = page; unlock_page(page); } pagevec_release(&pvec); cond_resched(); } return last_page; } |
26de9b117 f2fs: avoid unnec... |
1245 |
int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode, |
608514deb f2fs: set fsync m... |
1246 |
struct writeback_control *wbc, bool atomic) |
e05df3b11 f2fs: add node op... |
1247 |
{ |
e05df3b11 f2fs: add node op... |
1248 1249 |
pgoff_t index, end; struct pagevec pvec; |
c267ec152 f2fs: report unwr... |
1250 |
int ret = 0; |
608514deb f2fs: set fsync m... |
1251 1252 |
struct page *last_page = NULL; bool marked = false; |
26de9b117 f2fs: avoid unnec... |
1253 |
nid_t ino = inode->i_ino; |
3f5f4959b f2fs: fix to comm... |
1254 |
int nwritten = 0; |
526813756 f2fs: split sync_... |
1255 |
|
608514deb f2fs: set fsync m... |
1256 1257 1258 1259 1260 1261 |
if (atomic) { last_page = last_fsync_dnode(sbi, ino); if (IS_ERR_OR_NULL(last_page)) return PTR_ERR_OR_ZERO(last_page); } retry: |
526813756 f2fs: split sync_... |
1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 |
pagevec_init(&pvec, 0); index = 0; end = ULONG_MAX; while (index <= end) { int i, nr_pages; nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, PAGECACHE_TAG_DIRTY, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; if (unlikely(f2fs_cp_error(sbi))) { |
608514deb f2fs: set fsync m... |
1278 |
f2fs_put_page(last_page, 0); |
526813756 f2fs: split sync_... |
1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 |
pagevec_release(&pvec); return -EIO; } if (!IS_DNODE(page) || !is_cold_node(page)) continue; if (ino_of_node(page) != ino) continue; lock_page(page); if (unlikely(page->mapping != NODE_MAPPING(sbi))) { continue_unlock: unlock_page(page); continue; } if (ino_of_node(page) != ino) goto continue_unlock; |
608514deb f2fs: set fsync m... |
1297 |
if (!PageDirty(page) && page != last_page) { |
526813756 f2fs: split sync_... |
1298 1299 1300 1301 1302 1303 |
/* someone wrote it for us */ goto continue_unlock; } f2fs_wait_on_page_writeback(page, NODE, true); BUG_ON(PageWriteback(page)); |
526813756 f2fs: split sync_... |
1304 |
|
608514deb f2fs: set fsync m... |
1305 1306 |
if (!atomic || page == last_page) { set_fsync_mark(page, 1); |
26de9b117 f2fs: avoid unnec... |
1307 1308 1309 1310 |
if (IS_INODE(page)) { if (is_inode_flag_set(inode, FI_DIRTY_INODE)) update_inode(inode, page); |
608514deb f2fs: set fsync m... |
1311 |
set_dentry_mark(page, |
526813756 f2fs: split sync_... |
1312 |
need_dentry_mark(sbi, ino)); |
26de9b117 f2fs: avoid unnec... |
1313 |
} |
608514deb f2fs: set fsync m... |
1314 1315 1316 1317 1318 1319 1320 |
/* may be written by other thread */ if (!PageDirty(page)) set_page_dirty(page); } if (!clear_page_dirty_for_io(page)) goto continue_unlock; |
526813756 f2fs: split sync_... |
1321 |
|
c267ec152 f2fs: report unwr... |
1322 1323 |
ret = NODE_MAPPING(sbi)->a_ops->writepage(page, wbc); if (ret) { |
526813756 f2fs: split sync_... |
1324 |
unlock_page(page); |
608514deb f2fs: set fsync m... |
1325 1326 |
f2fs_put_page(last_page, 0); break; |
3f5f4959b f2fs: fix to comm... |
1327 1328 |
} else { nwritten++; |
608514deb f2fs: set fsync m... |
1329 |
} |
3f5f4959b f2fs: fix to comm... |
1330 |
|
608514deb f2fs: set fsync m... |
1331 1332 1333 |
if (page == last_page) { f2fs_put_page(page, 0); marked = true; |
526813756 f2fs: split sync_... |
1334 |
break; |
c267ec152 f2fs: report unwr... |
1335 |
} |
526813756 f2fs: split sync_... |
1336 1337 1338 |
} pagevec_release(&pvec); cond_resched(); |
608514deb f2fs: set fsync m... |
1339 |
if (ret || marked) |
526813756 f2fs: split sync_... |
1340 1341 |
break; } |
608514deb f2fs: set fsync m... |
1342 1343 1344 1345 1346 1347 1348 1349 1350 |
if (!ret && atomic && !marked) { f2fs_msg(sbi->sb, KERN_DEBUG, "Retry to write fsync mark: ino=%u, idx=%lx", ino, last_page->index); lock_page(last_page); set_page_dirty(last_page); unlock_page(last_page); goto retry; } |
3f5f4959b f2fs: fix to comm... |
1351 1352 1353 |
if (nwritten) f2fs_submit_merged_bio_cond(sbi, NULL, NULL, ino, NODE, WRITE); |
c267ec152 f2fs: report unwr... |
1354 |
return ret ? -EIO: 0; |
526813756 f2fs: split sync_... |
1355 1356 1357 1358 1359 1360 1361 |
} int sync_node_pages(struct f2fs_sb_info *sbi, struct writeback_control *wbc) { pgoff_t index, end; struct pagevec pvec; int step = 0; |
12bb0a8fd f2fs: submit node... |
1362 |
int nwritten = 0; |
3f5f4959b f2fs: fix to comm... |
1363 |
int ret = 0; |
e05df3b11 f2fs: add node op... |
1364 1365 1366 1367 1368 |
pagevec_init(&pvec, 0); next_step: index = 0; |
80dd9c0e9 f2fs: fix incorre... |
1369 |
end = ULONG_MAX; |
e05df3b11 f2fs: add node op... |
1370 1371 1372 |
while (index <= end) { int i, nr_pages; |
4ef51a8fc f2fs: introduce N... |
1373 |
nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, |
e05df3b11 f2fs: add node op... |
1374 1375 1376 1377 1378 1379 1380 |
PAGECACHE_TAG_DIRTY, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) break; for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; |
6d5a1495e f2fs: let user be... |
1381 1382 |
if (unlikely(f2fs_cp_error(sbi))) { pagevec_release(&pvec); |
3f5f4959b f2fs: fix to comm... |
1383 1384 |
ret = -EIO; goto out; |
6d5a1495e f2fs: let user be... |
1385 |
} |
e05df3b11 f2fs: add node op... |
1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 |
/* * flushing sequence with step: * 0. indirect nodes * 1. dentry dnodes * 2. file dnodes */ if (step == 0 && IS_DNODE(page)) continue; if (step == 1 && (!IS_DNODE(page) || is_cold_node(page))) continue; if (step == 2 && (!IS_DNODE(page) || !is_cold_node(page))) continue; |
9a4cbc9e5 f2fs: try to flus... |
1400 |
lock_node: |
526813756 f2fs: split sync_... |
1401 |
if (!trylock_page(page)) |
e05df3b11 f2fs: add node op... |
1402 |
continue; |
4ef51a8fc f2fs: introduce N... |
1403 |
if (unlikely(page->mapping != NODE_MAPPING(sbi))) { |
e05df3b11 f2fs: add node op... |
1404 1405 1406 1407 |
continue_unlock: unlock_page(page); continue; } |
e05df3b11 f2fs: add node op... |
1408 1409 1410 1411 1412 |
if (!PageDirty(page)) { /* someone wrote it for us */ goto continue_unlock; } |
2049d4fcb f2fs: avoid multi... |
1413 |
/* flush inline_data */ |
526813756 f2fs: split sync_... |
1414 |
if (is_inline_node(page)) { |
2049d4fcb f2fs: avoid multi... |
1415 1416 1417 |
clear_inline_node(page); unlock_page(page); flush_inline_data(sbi, ino_of_node(page)); |
9a4cbc9e5 f2fs: try to flus... |
1418 |
goto lock_node; |
2049d4fcb f2fs: avoid multi... |
1419 |
} |
fa3d2bdf9 f2fs: wait on pag... |
1420 1421 1422 |
f2fs_wait_on_page_writeback(page, NODE, true); BUG_ON(PageWriteback(page)); |
e05df3b11 f2fs: add node op... |
1423 1424 |
if (!clear_page_dirty_for_io(page)) goto continue_unlock; |
526813756 f2fs: split sync_... |
1425 1426 |
set_fsync_mark(page, 0); set_dentry_mark(page, 0); |
527465192 f2fs: unlock_page... |
1427 1428 1429 |
if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc)) unlock_page(page); |
3f5f4959b f2fs: fix to comm... |
1430 1431 |
else nwritten++; |
e05df3b11 f2fs: add node op... |
1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 |
if (--wbc->nr_to_write == 0) break; } pagevec_release(&pvec); cond_resched(); if (wbc->nr_to_write == 0) { step = 2; break; } } if (step < 2) { step++; goto next_step; } |
3f5f4959b f2fs: fix to comm... |
1449 1450 1451 1452 |
out: if (nwritten) f2fs_submit_merged_bio(sbi, NODE, WRITE); return ret; |
e05df3b11 f2fs: add node op... |
1453 |
} |
cfe58f9dc f2fs: avoid to wa... |
1454 1455 |
int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino) { |
80dd9c0e9 f2fs: fix incorre... |
1456 |
pgoff_t index = 0, end = ULONG_MAX; |
cfe58f9dc f2fs: avoid to wa... |
1457 |
struct pagevec pvec; |
280db3c88 f2fs: use filemap... |
1458 |
int ret2, ret = 0; |
cfe58f9dc f2fs: avoid to wa... |
1459 1460 |
pagevec_init(&pvec, 0); |
4ef51a8fc f2fs: introduce N... |
1461 1462 1463 1464 1465 1466 1467 1468 |
while (index <= end) { int i, nr_pages; nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, PAGECACHE_TAG_WRITEBACK, min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); if (nr_pages == 0) break; |
cfe58f9dc f2fs: avoid to wa... |
1469 1470 1471 1472 1473 |
for (i = 0; i < nr_pages; i++) { struct page *page = pvec.pages[i]; /* until radix tree lookup accepts end_index */ |
cfb271d48 f2fs: add unlikel... |
1474 |
if (unlikely(page->index > end)) |
cfe58f9dc f2fs: avoid to wa... |
1475 |
continue; |
4bf08ff6f f2fs: remove unne... |
1476 |
if (ino && ino_of_node(page) == ino) { |
fec1d6576 f2fs: use wait_fo... |
1477 |
f2fs_wait_on_page_writeback(page, NODE, true); |
4bf08ff6f f2fs: remove unne... |
1478 1479 1480 |
if (TestClearPageError(page)) ret = -EIO; } |
cfe58f9dc f2fs: avoid to wa... |
1481 1482 1483 1484 |
} pagevec_release(&pvec); cond_resched(); } |
280db3c88 f2fs: use filemap... |
1485 |
ret2 = filemap_check_errors(NODE_MAPPING(sbi)); |
cfe58f9dc f2fs: avoid to wa... |
1486 1487 1488 1489 |
if (!ret) ret = ret2; return ret; } |
e05df3b11 f2fs: add node op... |
1490 1491 1492 |
static int f2fs_write_node_page(struct page *page, struct writeback_control *wbc) { |
4081363fb f2fs: introduce F... |
1493 |
struct f2fs_sb_info *sbi = F2FS_P_SB(page); |
e05df3b11 f2fs: add node op... |
1494 |
nid_t nid; |
e05df3b11 f2fs: add node op... |
1495 |
struct node_info ni; |
fb5566da9 f2fs: improve wri... |
1496 |
struct f2fs_io_info fio = { |
05ca3632e f2fs: add sbi and... |
1497 |
.sbi = sbi, |
fb5566da9 f2fs: improve wri... |
1498 |
.type = NODE, |
04d328def f2fs: use bio op ... |
1499 1500 |
.op = REQ_OP_WRITE, .op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0, |
05ca3632e f2fs: add sbi and... |
1501 |
.page = page, |
4375a3366 f2fs crypto: add ... |
1502 |
.encrypted_page = NULL, |
fb5566da9 f2fs: improve wri... |
1503 |
}; |
e05df3b11 f2fs: add node op... |
1504 |
|
ecda0de34 f2fs: add a trace... |
1505 |
trace_f2fs_writepage(page, NODE); |
caf0047e7 f2fs: merge flags... |
1506 |
if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING))) |
87a9bd265 f2fs: avoid to wr... |
1507 |
goto redirty_out; |
cf779cab1 f2fs: handle EIO ... |
1508 1509 |
if (unlikely(f2fs_cp_error(sbi))) goto redirty_out; |
87a9bd265 f2fs: avoid to wr... |
1510 |
|
e05df3b11 f2fs: add node op... |
1511 1512 |
/* get old block addr of this node page */ nid = nid_of_node(page); |
9850cf4a8 f2fs: need fsck.f... |
1513 |
f2fs_bug_on(sbi, page->index != nid); |
e05df3b11 f2fs: add node op... |
1514 |
|
25b93346a f2fs: cover numbe... |
1515 1516 1517 1518 1519 1520 |
if (wbc->for_reclaim) { if (!down_read_trylock(&sbi->node_write)) goto redirty_out; } else { down_read(&sbi->node_write); } |
e05df3b11 f2fs: add node op... |
1521 1522 1523 |
get_node_info(sbi, nid, &ni); /* This page is already truncated */ |
6bacf52fb f2fs: add unlikel... |
1524 |
if (unlikely(ni.blk_addr == NULL_ADDR)) { |
2bca1e238 f2fs: clear page'... |
1525 |
ClearPageUptodate(page); |
399368372 f2fs: introduce a... |
1526 |
dec_page_count(sbi, F2FS_DIRTY_NODES); |
25b93346a f2fs: cover numbe... |
1527 |
up_read(&sbi->node_write); |
399368372 f2fs: introduce a... |
1528 1529 1530 |
unlock_page(page); return 0; } |
e05df3b11 f2fs: add node op... |
1531 1532 |
set_page_writeback(page); |
7a9d75481 f2fs: trace old b... |
1533 |
fio.old_blkaddr = ni.blk_addr; |
05ca3632e f2fs: add sbi and... |
1534 |
write_node_page(nid, &fio); |
7a9d75481 f2fs: trace old b... |
1535 |
set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page)); |
e05df3b11 f2fs: add node op... |
1536 |
dec_page_count(sbi, F2FS_DIRTY_NODES); |
b3582c689 f2fs: reduce comp... |
1537 |
up_read(&sbi->node_write); |
0c3a57975 f2fs: introduce f... |
1538 1539 1540 |
if (wbc->for_reclaim) f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, NODE, WRITE); |
e05df3b11 f2fs: add node op... |
1541 |
unlock_page(page); |
27c6bd60a f2fs: submit bio ... |
1542 |
|
0c3a57975 f2fs: introduce f... |
1543 |
if (unlikely(f2fs_cp_error(sbi))) |
27c6bd60a f2fs: submit bio ... |
1544 |
f2fs_submit_merged_bio(sbi, NODE, WRITE); |
e05df3b11 f2fs: add node op... |
1545 |
return 0; |
87a9bd265 f2fs: avoid to wr... |
1546 1547 |
redirty_out: |
76f60268e f2fs: call redirt... |
1548 |
redirty_page_for_writepage(wbc, page); |
87a9bd265 f2fs: avoid to wr... |
1549 |
return AOP_WRITEPAGE_ACTIVATE; |
e05df3b11 f2fs: add node op... |
1550 1551 1552 1553 1554 |
} static int f2fs_write_node_pages(struct address_space *mapping, struct writeback_control *wbc) { |
4081363fb f2fs: introduce F... |
1555 |
struct f2fs_sb_info *sbi = F2FS_M_SB(mapping); |
9dfa1baff f2fs: use blk_plu... |
1556 |
struct blk_plug plug; |
50c8cdb35 f2fs: introduce n... |
1557 |
long diff; |
e05df3b11 f2fs: add node op... |
1558 |
|
4660f9c0f f2fs: introduce f... |
1559 1560 |
/* balancing f2fs's metadata in background */ f2fs_balance_fs_bg(sbi); |
e05df3b11 f2fs: add node op... |
1561 |
|
a7fdffbd3 f2fs: avoid issui... |
1562 |
/* collect a number of dirty node pages and write together */ |
87d6f8909 f2fs: avoid small... |
1563 |
if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE)) |
d3baf95da f2fs: increase pa... |
1564 |
goto skip_write; |
a7fdffbd3 f2fs: avoid issui... |
1565 |
|
d31c7c3f0 f2fs: fix missing... |
1566 |
trace_f2fs_writepages(mapping->host, wbc, NODE); |
50c8cdb35 f2fs: introduce n... |
1567 |
diff = nr_pages_to_write(sbi, NODE, wbc); |
fb5566da9 f2fs: improve wri... |
1568 |
wbc->sync_mode = WB_SYNC_NONE; |
9dfa1baff f2fs: use blk_plu... |
1569 |
blk_start_plug(&plug); |
526813756 f2fs: split sync_... |
1570 |
sync_node_pages(sbi, wbc); |
9dfa1baff f2fs: use blk_plu... |
1571 |
blk_finish_plug(&plug); |
50c8cdb35 f2fs: introduce n... |
1572 |
wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); |
e05df3b11 f2fs: add node op... |
1573 |
return 0; |
d3baf95da f2fs: increase pa... |
1574 1575 1576 |
skip_write: wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES); |
d31c7c3f0 f2fs: fix missing... |
1577 |
trace_f2fs_writepages(mapping->host, wbc, NODE); |
d3baf95da f2fs: increase pa... |
1578 |
return 0; |
e05df3b11 f2fs: add node op... |
1579 1580 1581 1582 |
} static int f2fs_set_node_page_dirty(struct page *page) { |
26c6b8879 f2fs: add tracepo... |
1583 |
trace_f2fs_set_page_dirty(page, NODE); |
237c0790e f2fs: call SetPag... |
1584 1585 |
if (!PageUptodate(page)) SetPageUptodate(page); |
e05df3b11 f2fs: add node op... |
1586 |
if (!PageDirty(page)) { |
fe76b796f f2fs: introduce f... |
1587 |
f2fs_set_page_dirty_nobuffers(page); |
4081363fb f2fs: introduce F... |
1588 |
inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES); |
e05df3b11 f2fs: add node op... |
1589 |
SetPagePrivate(page); |
9e4ded3f3 f2fs: activate f2... |
1590 |
f2fs_trace_pid(page); |
e05df3b11 f2fs: add node op... |
1591 1592 1593 1594 |
return 1; } return 0; } |
0a8165d7c f2fs: adjust kern... |
1595 |
/* |
e05df3b11 f2fs: add node op... |
1596 1597 1598 1599 1600 1601 |
* Structure of the f2fs node operations */ const struct address_space_operations f2fs_node_aops = { .writepage = f2fs_write_node_page, .writepages = f2fs_write_node_pages, .set_page_dirty = f2fs_set_node_page_dirty, |
487261f39 f2fs: merge {inva... |
1602 1603 |
.invalidatepage = f2fs_invalidate_page, .releasepage = f2fs_release_page, |
5b7a487cf f2fs: add customi... |
1604 1605 1606 |
#ifdef CONFIG_MIGRATION .migratepage = f2fs_migrate_page, #endif |
e05df3b11 f2fs: add node op... |
1607 |
}; |
8a7ed66aa f2fs: introduce a... |
1608 1609 |
static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, nid_t n) |
e05df3b11 f2fs: add node op... |
1610 |
{ |
8a7ed66aa f2fs: introduce a... |
1611 |
return radix_tree_lookup(&nm_i->free_nid_root, n); |
e05df3b11 f2fs: add node op... |
1612 |
} |
8a7ed66aa f2fs: introduce a... |
1613 1614 |
static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i, struct free_nid *i) |
e05df3b11 f2fs: add node op... |
1615 1616 |
{ list_del(&i->list); |
8a7ed66aa f2fs: introduce a... |
1617 |
radix_tree_delete(&nm_i->free_nid_root, i->nid); |
e05df3b11 f2fs: add node op... |
1618 |
} |
6fb03f3a4 f2fs: adjust free... |
1619 |
static int add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) |
e05df3b11 f2fs: add node op... |
1620 |
{ |
6fb03f3a4 f2fs: adjust free... |
1621 |
struct f2fs_nm_info *nm_i = NM_I(sbi); |
e05df3b11 f2fs: add node op... |
1622 |
struct free_nid *i; |
59bbd474a f2fs: cover free_... |
1623 |
struct nat_entry *ne; |
e05df3b11 f2fs: add node op... |
1624 |
|
6fb03f3a4 f2fs: adjust free... |
1625 |
if (!available_free_memory(sbi, FREE_NIDS)) |
23d388442 f2fs: optimize sc... |
1626 |
return -1; |
9198aceb5 f2fs: check nid =... |
1627 1628 |
/* 0 nid should not be used */ |
cfb271d48 f2fs: add unlikel... |
1629 |
if (unlikely(nid == 0)) |
9198aceb5 f2fs: check nid =... |
1630 |
return 0; |
59bbd474a f2fs: cover free_... |
1631 |
|
7bd59381c f2fs: introduce f... |
1632 1633 |
if (build) { /* do not add allocated nids */ |
7bd59381c f2fs: introduce f... |
1634 |
ne = __lookup_nat_cache(nm_i, nid); |
a51311938 f2fs: cover more ... |
1635 |
if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) || |
7ef35e3b9 f2fs: introduce a... |
1636 |
nat_get_blkaddr(ne) != NULL_ADDR)) |
7bd59381c f2fs: introduce f... |
1637 |
return 0; |
e05df3b11 f2fs: add node op... |
1638 |
} |
7bd59381c f2fs: introduce f... |
1639 1640 |
i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS); |
e05df3b11 f2fs: add node op... |
1641 1642 |
i->nid = nid; i->state = NID_NEW; |
769ec6e5b f2fs: call radix_... |
1643 1644 1645 1646 |
if (radix_tree_preload(GFP_NOFS)) { kmem_cache_free(free_nid_slab, i); return 0; } |
e05df3b11 f2fs: add node op... |
1647 |
spin_lock(&nm_i->free_nid_list_lock); |
8a7ed66aa f2fs: introduce a... |
1648 |
if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) { |
e05df3b11 f2fs: add node op... |
1649 |
spin_unlock(&nm_i->free_nid_list_lock); |
769ec6e5b f2fs: call radix_... |
1650 |
radix_tree_preload_end(); |
e05df3b11 f2fs: add node op... |
1651 1652 1653 1654 1655 1656 |
kmem_cache_free(free_nid_slab, i); return 0; } list_add_tail(&i->list, &nm_i->free_nid_list); nm_i->fcnt++; spin_unlock(&nm_i->free_nid_list_lock); |
769ec6e5b f2fs: call radix_... |
1657 |
radix_tree_preload_end(); |
e05df3b11 f2fs: add node op... |
1658 1659 1660 1661 1662 1663 |
return 1; } static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) { struct free_nid *i; |
cf0ee0f09 f2fs: avoid free ... |
1664 |
bool need_free = false; |
e05df3b11 f2fs: add node op... |
1665 |
spin_lock(&nm_i->free_nid_list_lock); |
8a7ed66aa f2fs: introduce a... |
1666 |
i = __lookup_free_nid_list(nm_i, nid); |
e05df3b11 f2fs: add node op... |
1667 |
if (i && i->state == NID_NEW) { |
8a7ed66aa f2fs: introduce a... |
1668 |
__del_from_free_nid_list(nm_i, i); |
e05df3b11 f2fs: add node op... |
1669 |
nm_i->fcnt--; |
cf0ee0f09 f2fs: avoid free ... |
1670 |
need_free = true; |
e05df3b11 f2fs: add node op... |
1671 1672 |
} spin_unlock(&nm_i->free_nid_list_lock); |
cf0ee0f09 f2fs: avoid free ... |
1673 1674 1675 |
if (need_free) kmem_cache_free(free_nid_slab, i); |
e05df3b11 f2fs: add node op... |
1676 |
} |
6fb03f3a4 f2fs: adjust free... |
1677 |
static void scan_nat_page(struct f2fs_sb_info *sbi, |
e05df3b11 f2fs: add node op... |
1678 1679 |
struct page *nat_page, nid_t start_nid) { |
6fb03f3a4 f2fs: adjust free... |
1680 |
struct f2fs_nm_info *nm_i = NM_I(sbi); |
e05df3b11 f2fs: add node op... |
1681 1682 |
struct f2fs_nat_block *nat_blk = page_address(nat_page); block_t blk_addr; |
e05df3b11 f2fs: add node op... |
1683 |
int i; |
e05df3b11 f2fs: add node op... |
1684 1685 1686 |
i = start_nid % NAT_ENTRY_PER_BLOCK; for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { |
23d388442 f2fs: optimize sc... |
1687 |
|
cfb271d48 f2fs: add unlikel... |
1688 |
if (unlikely(start_nid >= nm_i->max_nid)) |
04431c44e f2fs: fix not to ... |
1689 |
break; |
23d388442 f2fs: optimize sc... |
1690 1691 |
blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); |
9850cf4a8 f2fs: need fsck.f... |
1692 |
f2fs_bug_on(sbi, blk_addr == NEW_ADDR); |
23d388442 f2fs: optimize sc... |
1693 |
if (blk_addr == NULL_ADDR) { |
6fb03f3a4 f2fs: adjust free... |
1694 |
if (add_free_nid(sbi, start_nid, true) < 0) |
23d388442 f2fs: optimize sc... |
1695 1696 |
break; } |
e05df3b11 f2fs: add node op... |
1697 |
} |
e05df3b11 f2fs: add node op... |
1698 |
} |
ad4edb831 f2fs: produce mor... |
1699 |
void build_free_nids(struct f2fs_sb_info *sbi) |
e05df3b11 f2fs: add node op... |
1700 |
{ |
e05df3b11 f2fs: add node op... |
1701 1702 |
struct f2fs_nm_info *nm_i = NM_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
b7ad7512b f2fs: split journ... |
1703 |
struct f2fs_journal *journal = curseg->journal; |
8760952d9 f2fs: code cleanu... |
1704 |
int i = 0; |
55008d845 f2fs: enhance all... |
1705 |
nid_t nid = nm_i->next_scan_nid; |
e05df3b11 f2fs: add node op... |
1706 |
|
55008d845 f2fs: enhance all... |
1707 |
/* Enough entries */ |
ad4edb831 f2fs: produce mor... |
1708 |
if (nm_i->fcnt >= NAT_ENTRY_PER_BLOCK) |
55008d845 f2fs: enhance all... |
1709 |
return; |
e05df3b11 f2fs: add node op... |
1710 |
|
55008d845 f2fs: enhance all... |
1711 |
/* readahead nat pages to be scanned */ |
26879fb10 f2fs: support low... |
1712 1713 |
ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, META_NAT, true); |
e05df3b11 f2fs: add node op... |
1714 |
|
b873b798a Revert "f2fs: use... |
1715 |
down_read(&nm_i->nat_tree_lock); |
a51311938 f2fs: cover more ... |
1716 |
|
e05df3b11 f2fs: add node op... |
1717 1718 |
while (1) { struct page *page = get_current_nat_page(sbi, nid); |
6fb03f3a4 f2fs: adjust free... |
1719 |
scan_nat_page(sbi, page, nid); |
e05df3b11 f2fs: add node op... |
1720 1721 1722 |
f2fs_put_page(page, 1); nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); |
cfb271d48 f2fs: add unlikel... |
1723 |
if (unlikely(nid >= nm_i->max_nid)) |
e05df3b11 f2fs: add node op... |
1724 |
nid = 0; |
55008d845 f2fs: enhance all... |
1725 |
|
a6d494b6d f2fs: fix to buil... |
1726 |
if (++i >= FREE_NID_PAGES) |
e05df3b11 f2fs: add node op... |
1727 1728 |
break; } |
55008d845 f2fs: enhance all... |
1729 1730 |
/* go to the next free nat pages to find free nids abundantly */ nm_i->next_scan_nid = nid; |
e05df3b11 f2fs: add node op... |
1731 1732 |
/* find free nids from current sum_pages */ |
b7ad7512b f2fs: split journ... |
1733 |
down_read(&curseg->journal_rwsem); |
dfc08a12e f2fs: introduce f... |
1734 1735 1736 1737 1738 |
for (i = 0; i < nats_in_cursum(journal); i++) { block_t addr; addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); nid = le32_to_cpu(nid_in_journal(journal, i)); |
e05df3b11 f2fs: add node op... |
1739 |
if (addr == NULL_ADDR) |
6fb03f3a4 f2fs: adjust free... |
1740 |
add_free_nid(sbi, nid, true); |
e05df3b11 f2fs: add node op... |
1741 1742 1743 |
else remove_free_nid(nm_i, nid); } |
b7ad7512b f2fs: split journ... |
1744 |
up_read(&curseg->journal_rwsem); |
b873b798a Revert "f2fs: use... |
1745 |
up_read(&nm_i->nat_tree_lock); |
2db2388fc f2fs: readahead f... |
1746 1747 |
ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid), |
ea1a29a0b f2fs: export ra_n... |
1748 |
nm_i->ra_nid_pages, META_NAT, false); |
e05df3b11 f2fs: add node op... |
1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 |
} /* * If this function returns success, caller can obtain a new nid * from second parameter of this function. * The returned nid could be used ino as well as nid when inode is created. */ bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i = NULL; |
e05df3b11 f2fs: add node op... |
1760 |
retry: |
cb78942b8 f2fs: inject ENOS... |
1761 |
#ifdef CONFIG_F2FS_FAULT_INJECTION |
1ecc0c5c5 f2fs: support con... |
1762 |
if (time_to_inject(sbi, FAULT_ALLOC_NID)) |
cb78942b8 f2fs: inject ENOS... |
1763 1764 |
return false; #endif |
7ee0eeabc f2fs: add availab... |
1765 |
if (unlikely(sbi->total_valid_node_count + 1 > nm_i->available_nids)) |
55008d845 f2fs: enhance all... |
1766 |
return false; |
e05df3b11 f2fs: add node op... |
1767 |
|
e05df3b11 f2fs: add node op... |
1768 |
spin_lock(&nm_i->free_nid_list_lock); |
e05df3b11 f2fs: add node op... |
1769 |
|
55008d845 f2fs: enhance all... |
1770 |
/* We should not use stale free nids created by build_free_nids */ |
f978f5a06 f2fs: introduce h... |
1771 |
if (nm_i->fcnt && !on_build_free_nids(nm_i)) { |
9850cf4a8 f2fs: need fsck.f... |
1772 |
f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list)); |
2d7b822ad f2fs: use list_fo... |
1773 |
list_for_each_entry(i, &nm_i->free_nid_list, list) |
55008d845 f2fs: enhance all... |
1774 1775 |
if (i->state == NID_NEW) break; |
e05df3b11 f2fs: add node op... |
1776 |
|
9850cf4a8 f2fs: need fsck.f... |
1777 |
f2fs_bug_on(sbi, i->state != NID_NEW); |
55008d845 f2fs: enhance all... |
1778 1779 1780 1781 1782 1783 |
*nid = i->nid; i->state = NID_ALLOC; nm_i->fcnt--; spin_unlock(&nm_i->free_nid_list_lock); return true; } |
e05df3b11 f2fs: add node op... |
1784 |
spin_unlock(&nm_i->free_nid_list_lock); |
55008d845 f2fs: enhance all... |
1785 1786 1787 |
/* Let's scan nat pages and its caches to get free nids */ mutex_lock(&nm_i->build_lock); |
55008d845 f2fs: enhance all... |
1788 |
build_free_nids(sbi); |
55008d845 f2fs: enhance all... |
1789 1790 |
mutex_unlock(&nm_i->build_lock); goto retry; |
e05df3b11 f2fs: add node op... |
1791 |
} |
0a8165d7c f2fs: adjust kern... |
1792 |
/* |
e05df3b11 f2fs: add node op... |
1793 1794 1795 1796 1797 1798 1799 1800 |
* alloc_nid() should be called prior to this function. */ void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i; spin_lock(&nm_i->free_nid_list_lock); |
8a7ed66aa f2fs: introduce a... |
1801 |
i = __lookup_free_nid_list(nm_i, nid); |
9850cf4a8 f2fs: need fsck.f... |
1802 |
f2fs_bug_on(sbi, !i || i->state != NID_ALLOC); |
8a7ed66aa f2fs: introduce a... |
1803 |
__del_from_free_nid_list(nm_i, i); |
e05df3b11 f2fs: add node op... |
1804 |
spin_unlock(&nm_i->free_nid_list_lock); |
cf0ee0f09 f2fs: avoid free ... |
1805 1806 |
kmem_cache_free(free_nid_slab, i); |
e05df3b11 f2fs: add node op... |
1807 |
} |
0a8165d7c f2fs: adjust kern... |
1808 |
/* |
e05df3b11 f2fs: add node op... |
1809 1810 1811 1812 |
* alloc_nid() should be called prior to this function. */ void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) { |
49952fa18 f2fs: reduce redu... |
1813 1814 |
struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i; |
cf0ee0f09 f2fs: avoid free ... |
1815 |
bool need_free = false; |
49952fa18 f2fs: reduce redu... |
1816 |
|
65985d935 f2fs: support the... |
1817 1818 |
if (!nid) return; |
49952fa18 f2fs: reduce redu... |
1819 |
spin_lock(&nm_i->free_nid_list_lock); |
8a7ed66aa f2fs: introduce a... |
1820 |
i = __lookup_free_nid_list(nm_i, nid); |
9850cf4a8 f2fs: need fsck.f... |
1821 |
f2fs_bug_on(sbi, !i || i->state != NID_ALLOC); |
6fb03f3a4 f2fs: adjust free... |
1822 |
if (!available_free_memory(sbi, FREE_NIDS)) { |
8a7ed66aa f2fs: introduce a... |
1823 |
__del_from_free_nid_list(nm_i, i); |
cf0ee0f09 f2fs: avoid free ... |
1824 |
need_free = true; |
95630cbad f2fs: bugfix for ... |
1825 1826 1827 1828 |
} else { i->state = NID_NEW; nm_i->fcnt++; } |
49952fa18 f2fs: reduce redu... |
1829 |
spin_unlock(&nm_i->free_nid_list_lock); |
cf0ee0f09 f2fs: avoid free ... |
1830 1831 1832 |
if (need_free) kmem_cache_free(free_nid_slab, i); |
e05df3b11 f2fs: add node op... |
1833 |
} |
31696580b f2fs: shrink free... |
1834 1835 1836 1837 1838 |
int try_to_free_nids(struct f2fs_sb_info *sbi, int nr_shrink) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i, *next; int nr = nr_shrink; |
ad4edb831 f2fs: produce mor... |
1839 1840 |
if (nm_i->fcnt <= MAX_FREE_NIDS) return 0; |
31696580b f2fs: shrink free... |
1841 1842 1843 1844 1845 |
if (!mutex_trylock(&nm_i->build_lock)) return 0; spin_lock(&nm_i->free_nid_list_lock); list_for_each_entry_safe(i, next, &nm_i->free_nid_list, list) { |
ad4edb831 f2fs: produce mor... |
1846 |
if (nr_shrink <= 0 || nm_i->fcnt <= MAX_FREE_NIDS) |
31696580b f2fs: shrink free... |
1847 1848 1849 1850 |
break; if (i->state == NID_ALLOC) continue; __del_from_free_nid_list(nm_i, i); |
31696580b f2fs: shrink free... |
1851 |
kmem_cache_free(free_nid_slab, i); |
f7409d0fa f2fs: fix wrong p... |
1852 |
nm_i->fcnt--; |
31696580b f2fs: shrink free... |
1853 |
nr_shrink--; |
31696580b f2fs: shrink free... |
1854 1855 1856 1857 1858 1859 |
} spin_unlock(&nm_i->free_nid_list_lock); mutex_unlock(&nm_i->build_lock); return nr - nr_shrink; } |
70cfed88e f2fs: avoid skipp... |
1860 |
void recover_inline_xattr(struct inode *inode, struct page *page) |
28cdce045 f2fs: recover inl... |
1861 |
{ |
28cdce045 f2fs: recover inl... |
1862 1863 1864 1865 |
void *src_addr, *dst_addr; size_t inline_size; struct page *ipage; struct f2fs_inode *ri; |
4081363fb f2fs: introduce F... |
1866 |
ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino); |
9850cf4a8 f2fs: need fsck.f... |
1867 |
f2fs_bug_on(F2FS_I_SB(inode), IS_ERR(ipage)); |
28cdce045 f2fs: recover inl... |
1868 |
|
e3b4d43f7 f2fs: should clea... |
1869 1870 |
ri = F2FS_INODE(page); if (!(ri->i_inline & F2FS_INLINE_XATTR)) { |
91942321e f2fs: use inode p... |
1871 |
clear_inode_flag(inode, FI_INLINE_XATTR); |
e3b4d43f7 f2fs: should clea... |
1872 1873 |
goto update_inode; } |
28cdce045 f2fs: recover inl... |
1874 1875 1876 |
dst_addr = inline_xattr_addr(ipage); src_addr = inline_xattr_addr(page); inline_size = inline_xattr_size(inode); |
fec1d6576 f2fs: use wait_fo... |
1877 |
f2fs_wait_on_page_writeback(ipage, NODE, true); |
28cdce045 f2fs: recover inl... |
1878 |
memcpy(dst_addr, src_addr, inline_size); |
e3b4d43f7 f2fs: should clea... |
1879 |
update_inode: |
28cdce045 f2fs: recover inl... |
1880 1881 1882 |
update_inode(inode, ipage); f2fs_put_page(ipage, 1); } |
1c35a90e8 f2fs: fix to reco... |
1883 |
void recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) |
abb2366c8 f2fs: fix to reco... |
1884 |
{ |
4081363fb f2fs: introduce F... |
1885 |
struct f2fs_sb_info *sbi = F2FS_I_SB(inode); |
abb2366c8 f2fs: fix to reco... |
1886 1887 1888 |
nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid; nid_t new_xnid = nid_of_node(page); struct node_info ni; |
abb2366c8 f2fs: fix to reco... |
1889 1890 1891 1892 1893 1894 |
/* 1: invalidate the previous xattr nid */ if (!prev_xnid) goto recover_xnid; /* Deallocate node address */ get_node_info(sbi, prev_xnid, &ni); |
9850cf4a8 f2fs: need fsck.f... |
1895 |
f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR); |
abb2366c8 f2fs: fix to reco... |
1896 1897 |
invalidate_blocks(sbi, ni.blk_addr); dec_valid_node_count(sbi, inode); |
479f40c44 f2fs: skip unnece... |
1898 |
set_node_addr(sbi, &ni, NULL_ADDR, false); |
abb2366c8 f2fs: fix to reco... |
1899 1900 1901 1902 |
recover_xnid: /* 2: allocate new xattr nid */ if (unlikely(!inc_valid_node_count(sbi, inode))) |
9850cf4a8 f2fs: need fsck.f... |
1903 |
f2fs_bug_on(sbi, 1); |
abb2366c8 f2fs: fix to reco... |
1904 1905 1906 1907 |
remove_free_nid(NM_I(sbi), new_xnid); get_node_info(sbi, new_xnid, &ni); ni.ino = inode->i_ino; |
479f40c44 f2fs: skip unnece... |
1908 |
set_node_addr(sbi, &ni, NEW_ADDR, false); |
205b98221 f2fs: call mark_i... |
1909 |
f2fs_i_xnid_write(inode, new_xnid); |
abb2366c8 f2fs: fix to reco... |
1910 1911 1912 |
/* 3: update xattr blkaddr */ refresh_sit_entry(sbi, NEW_ADDR, blkaddr); |
479f40c44 f2fs: skip unnece... |
1913 |
set_node_addr(sbi, &ni, blkaddr, false); |
abb2366c8 f2fs: fix to reco... |
1914 |
} |
e05df3b11 f2fs: add node op... |
1915 1916 |
int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) { |
58bfaf44d f2fs: introduce F... |
1917 |
struct f2fs_inode *src, *dst; |
e05df3b11 f2fs: add node op... |
1918 1919 1920 |
nid_t ino = ino_of_node(page); struct node_info old_ni, new_ni; struct page *ipage; |
e8271fa39 f2fs: avoid BUG_O... |
1921 1922 1923 1924 |
get_node_info(sbi, ino, &old_ni); if (unlikely(old_ni.blk_addr != NULL_ADDR)) return -EINVAL; |
e8ea9b3d7 f2fs: avoid ENOME... |
1925 |
retry: |
300e129c1 f2fs: use f2fs_gr... |
1926 |
ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false); |
e8ea9b3d7 f2fs: avoid ENOME... |
1927 1928 1929 1930 |
if (!ipage) { congestion_wait(BLK_RW_ASYNC, HZ/50); goto retry; } |
e05df3b11 f2fs: add node op... |
1931 |
|
e1c420452 f2fs: fix typo |
1932 |
/* Should not use this inode from free nid list */ |
e05df3b11 f2fs: add node op... |
1933 |
remove_free_nid(NM_I(sbi), ino); |
237c0790e f2fs: call SetPag... |
1934 1935 |
if (!PageUptodate(ipage)) SetPageUptodate(ipage); |
e05df3b11 f2fs: add node op... |
1936 |
fill_node_footer(ipage, ino, ino, 0, true); |
58bfaf44d f2fs: introduce F... |
1937 1938 |
src = F2FS_INODE(page); dst = F2FS_INODE(ipage); |
e05df3b11 f2fs: add node op... |
1939 |
|
58bfaf44d f2fs: introduce F... |
1940 1941 1942 1943 1944 |
memcpy(dst, src, (unsigned long)&src->i_ext - (unsigned long)src); dst->i_size = 0; dst->i_blocks = cpu_to_le64(1); dst->i_links = cpu_to_le32(1); dst->i_xattr_nid = 0; |
617deb8c0 f2fs: fix the ini... |
1945 |
dst->i_inline = src->i_inline & F2FS_INLINE_XATTR; |
e05df3b11 f2fs: add node op... |
1946 1947 1948 |
new_ni = old_ni; new_ni.ino = ino; |
cfb271d48 f2fs: add unlikel... |
1949 |
if (unlikely(!inc_valid_node_count(sbi, NULL))) |
65e5cd0a1 f2fs: fix inconsi... |
1950 |
WARN_ON(1); |
479f40c44 f2fs: skip unnece... |
1951 |
set_node_addr(sbi, &new_ni, NEW_ADDR, false); |
e05df3b11 f2fs: add node op... |
1952 |
inc_valid_inode_count(sbi); |
617deb8c0 f2fs: fix the ini... |
1953 |
set_page_dirty(ipage); |
e05df3b11 f2fs: add node op... |
1954 1955 1956 1957 1958 1959 1960 1961 1962 |
f2fs_put_page(ipage, 1); return 0; } int restore_node_summary(struct f2fs_sb_info *sbi, unsigned int segno, struct f2fs_summary_block *sum) { struct f2fs_node *rn; struct f2fs_summary *sum_entry; |
e05df3b11 f2fs: add node op... |
1963 |
block_t addr; |
90a893c74 f2fs: use MAX_BIO... |
1964 |
int bio_blocks = MAX_BIO_BLOCKS(sbi); |
9ecf4b80b f2fs: use ra_meta... |
1965 |
int i, idx, last_offset, nrpages; |
e05df3b11 f2fs: add node op... |
1966 1967 1968 1969 1970 |
/* scan the node segment */ last_offset = sbi->blocks_per_seg; addr = START_BLOCK(sbi, segno); sum_entry = &sum->entries[0]; |
9ecf4b80b f2fs: use ra_meta... |
1971 |
for (i = 0; i < last_offset; i += nrpages, addr += nrpages) { |
9af0ff1c5 f2fs: readahead c... |
1972 |
nrpages = min(last_offset - i, bio_blocks); |
393ff91f5 f2fs: reduce unnc... |
1973 |
|
e1c420452 f2fs: fix typo |
1974 |
/* readahead node pages */ |
26879fb10 f2fs: support low... |
1975 |
ra_meta_pages(sbi, addr, nrpages, META_POR, true); |
e05df3b11 f2fs: add node op... |
1976 |
|
9ecf4b80b f2fs: use ra_meta... |
1977 |
for (idx = addr; idx < addr + nrpages; idx++) { |
2b947003f f2fs: don't tag R... |
1978 |
struct page *page = get_tmp_page(sbi, idx); |
9af0ff1c5 f2fs: readahead c... |
1979 |
|
9ecf4b80b f2fs: use ra_meta... |
1980 1981 1982 1983 1984 1985 |
rn = F2FS_NODE(page); sum_entry->nid = rn->footer.nid; sum_entry->version = 0; sum_entry->ofs_in_node = 0; sum_entry++; f2fs_put_page(page, 1); |
9af0ff1c5 f2fs: readahead c... |
1986 |
} |
bac4eef65 f2fs: avoid crash... |
1987 |
|
9ecf4b80b f2fs: use ra_meta... |
1988 |
invalidate_mapping_pages(META_MAPPING(sbi), addr, |
bac4eef65 f2fs: avoid crash... |
1989 |
addr + nrpages); |
e05df3b11 f2fs: add node op... |
1990 |
} |
9ecf4b80b f2fs: use ra_meta... |
1991 |
return 0; |
e05df3b11 f2fs: add node op... |
1992 |
} |
aec71382c f2fs: refactor fl... |
1993 |
static void remove_nats_in_journal(struct f2fs_sb_info *sbi) |
e05df3b11 f2fs: add node op... |
1994 1995 1996 |
{ struct f2fs_nm_info *nm_i = NM_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
b7ad7512b f2fs: split journ... |
1997 |
struct f2fs_journal *journal = curseg->journal; |
e05df3b11 f2fs: add node op... |
1998 |
int i; |
b7ad7512b f2fs: split journ... |
1999 |
down_write(&curseg->journal_rwsem); |
dfc08a12e f2fs: introduce f... |
2000 |
for (i = 0; i < nats_in_cursum(journal); i++) { |
e05df3b11 f2fs: add node op... |
2001 2002 |
struct nat_entry *ne; struct f2fs_nat_entry raw_ne; |
dfc08a12e f2fs: introduce f... |
2003 |
nid_t nid = le32_to_cpu(nid_in_journal(journal, i)); |
e05df3b11 f2fs: add node op... |
2004 |
|
dfc08a12e f2fs: introduce f... |
2005 |
raw_ne = nat_in_journal(journal, i); |
9be32d72b f2fs: do retry op... |
2006 |
|
e05df3b11 f2fs: add node op... |
2007 |
ne = __lookup_nat_cache(nm_i, nid); |
e05df3b11 f2fs: add node op... |
2008 |
if (!ne) { |
9be32d72b f2fs: do retry op... |
2009 2010 |
ne = grab_nat_entry(nm_i, nid); node_info_from_raw_nat(&ne->ni, &raw_ne); |
e05df3b11 f2fs: add node op... |
2011 |
} |
e05df3b11 f2fs: add node op... |
2012 |
__set_nat_cache_dirty(nm_i, ne); |
e05df3b11 f2fs: add node op... |
2013 |
} |
dfc08a12e f2fs: introduce f... |
2014 |
update_nats_in_cursum(journal, -i); |
b7ad7512b f2fs: split journ... |
2015 |
up_write(&curseg->journal_rwsem); |
e05df3b11 f2fs: add node op... |
2016 |
} |
309cc2b6e f2fs: refactor fl... |
2017 2018 |
static void __adjust_nat_entry_set(struct nat_entry_set *nes, struct list_head *head, int max) |
e05df3b11 f2fs: add node op... |
2019 |
{ |
309cc2b6e f2fs: refactor fl... |
2020 |
struct nat_entry_set *cur; |
e05df3b11 f2fs: add node op... |
2021 |
|
309cc2b6e f2fs: refactor fl... |
2022 2023 |
if (nes->entry_cnt >= max) goto add_out; |
e05df3b11 f2fs: add node op... |
2024 |
|
309cc2b6e f2fs: refactor fl... |
2025 2026 2027 2028 2029 |
list_for_each_entry(cur, head, set_list) { if (cur->entry_cnt >= nes->entry_cnt) { list_add(&nes->set_list, cur->set_list.prev); return; } |
aec71382c f2fs: refactor fl... |
2030 |
} |
309cc2b6e f2fs: refactor fl... |
2031 2032 2033 |
add_out: list_add_tail(&nes->set_list, head); } |
e05df3b11 f2fs: add node op... |
2034 |
|
309cc2b6e f2fs: refactor fl... |
2035 2036 2037 2038 |
static void __flush_nat_entry_set(struct f2fs_sb_info *sbi, struct nat_entry_set *set) { struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
b7ad7512b f2fs: split journ... |
2039 |
struct f2fs_journal *journal = curseg->journal; |
309cc2b6e f2fs: refactor fl... |
2040 2041 2042 2043 2044 |
nid_t start_nid = set->set * NAT_ENTRY_PER_BLOCK; bool to_journal = true; struct f2fs_nat_block *nat_blk; struct nat_entry *ne, *cur; struct page *page = NULL; |
e05df3b11 f2fs: add node op... |
2045 |
|
aec71382c f2fs: refactor fl... |
2046 2047 2048 2049 2050 |
/* * there are two steps to flush nat entries: * #1, flush nat entries to journal in current hot data summary block. * #2, flush nat entries to nat page. */ |
dfc08a12e f2fs: introduce f... |
2051 |
if (!__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL)) |
309cc2b6e f2fs: refactor fl... |
2052 2053 2054 |
to_journal = false; if (to_journal) { |
b7ad7512b f2fs: split journ... |
2055 |
down_write(&curseg->journal_rwsem); |
309cc2b6e f2fs: refactor fl... |
2056 2057 2058 2059 2060 |
} else { page = get_next_nat_page(sbi, start_nid); nat_blk = page_address(page); f2fs_bug_on(sbi, !nat_blk); } |
aec71382c f2fs: refactor fl... |
2061 |
|
309cc2b6e f2fs: refactor fl... |
2062 2063 2064 2065 2066 2067 2068 2069 |
/* flush dirty nats in nat entry set */ list_for_each_entry_safe(ne, cur, &set->entry_list, list) { struct f2fs_nat_entry *raw_ne; nid_t nid = nat_get_nid(ne); int offset; if (nat_get_blkaddr(ne) == NEW_ADDR) continue; |
aec71382c f2fs: refactor fl... |
2070 2071 |
if (to_journal) { |
dfc08a12e f2fs: introduce f... |
2072 |
offset = lookup_journal_in_cursum(journal, |
309cc2b6e f2fs: refactor fl... |
2073 2074 |
NAT_JOURNAL, nid, 1); f2fs_bug_on(sbi, offset < 0); |
dfc08a12e f2fs: introduce f... |
2075 2076 |
raw_ne = &nat_in_journal(journal, offset); nid_in_journal(journal, offset) = cpu_to_le32(nid); |
aec71382c f2fs: refactor fl... |
2077 |
} else { |
309cc2b6e f2fs: refactor fl... |
2078 |
raw_ne = &nat_blk->entries[nid - start_nid]; |
e05df3b11 f2fs: add node op... |
2079 |
} |
309cc2b6e f2fs: refactor fl... |
2080 |
raw_nat_from_node_info(raw_ne, &ne->ni); |
309cc2b6e f2fs: refactor fl... |
2081 2082 |
nat_reset_flag(ne); __clear_nat_cache_dirty(NM_I(sbi), ne); |
309cc2b6e f2fs: refactor fl... |
2083 2084 2085 |
if (nat_get_blkaddr(ne) == NULL_ADDR) add_free_nid(sbi, nid, false); } |
e05df3b11 f2fs: add node op... |
2086 |
|
309cc2b6e f2fs: refactor fl... |
2087 |
if (to_journal) |
b7ad7512b f2fs: split journ... |
2088 |
up_write(&curseg->journal_rwsem); |
309cc2b6e f2fs: refactor fl... |
2089 2090 |
else f2fs_put_page(page, 1); |
aec71382c f2fs: refactor fl... |
2091 |
|
80ec2e914 f2fs: no more dir... |
2092 2093 2094 2095 |
f2fs_bug_on(sbi, set->entry_cnt); radix_tree_delete(&NM_I(sbi)->nat_set_root, set->set); kmem_cache_free(nat_entry_set_slab, set); |
309cc2b6e f2fs: refactor fl... |
2096 |
} |
aec71382c f2fs: refactor fl... |
2097 |
|
309cc2b6e f2fs: refactor fl... |
2098 2099 2100 2101 2102 2103 2104 |
/* * This function is called during the checkpointing process. */ void flush_nat_entries(struct f2fs_sb_info *sbi) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); |
b7ad7512b f2fs: split journ... |
2105 |
struct f2fs_journal *journal = curseg->journal; |
7aed0d453 f2fs: free radix_... |
2106 |
struct nat_entry_set *setvec[SETVEC_SIZE]; |
309cc2b6e f2fs: refactor fl... |
2107 2108 2109 2110 |
struct nat_entry_set *set, *tmp; unsigned int found; nid_t set_idx = 0; LIST_HEAD(sets); |
20d047c87 f2fs: check dirty... |
2111 2112 |
if (!nm_i->dirty_nat_cnt) return; |
a51311938 f2fs: cover more ... |
2113 |
|
b873b798a Revert "f2fs: use... |
2114 |
down_write(&nm_i->nat_tree_lock); |
a51311938 f2fs: cover more ... |
2115 |
|
309cc2b6e f2fs: refactor fl... |
2116 2117 2118 2119 2120 |
/* * if there are no enough space in journal to store dirty nat * entries, remove all entries from journal and merge them * into nat entry set. */ |
dfc08a12e f2fs: introduce f... |
2121 |
if (!__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL)) |
309cc2b6e f2fs: refactor fl... |
2122 |
remove_nats_in_journal(sbi); |
309cc2b6e f2fs: refactor fl... |
2123 |
while ((found = __gang_lookup_nat_set(nm_i, |
7aed0d453 f2fs: free radix_... |
2124 |
set_idx, SETVEC_SIZE, setvec))) { |
309cc2b6e f2fs: refactor fl... |
2125 2126 2127 2128 |
unsigned idx; set_idx = setvec[found - 1]->set + 1; for (idx = 0; idx < found; idx++) __adjust_nat_entry_set(setvec[idx], &sets, |
dfc08a12e f2fs: introduce f... |
2129 |
MAX_NAT_JENTRIES(journal)); |
e05df3b11 f2fs: add node op... |
2130 |
} |
aec71382c f2fs: refactor fl... |
2131 |
|
309cc2b6e f2fs: refactor fl... |
2132 2133 2134 |
/* flush dirty nats in nat entry set */ list_for_each_entry_safe(set, tmp, &sets, set_list) __flush_nat_entry_set(sbi, set); |
b873b798a Revert "f2fs: use... |
2135 |
up_write(&nm_i->nat_tree_lock); |
a51311938 f2fs: cover more ... |
2136 |
|
9850cf4a8 f2fs: need fsck.f... |
2137 |
f2fs_bug_on(sbi, nm_i->dirty_nat_cnt); |
e05df3b11 f2fs: add node op... |
2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 |
} static int init_node_manager(struct f2fs_sb_info *sbi) { struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); struct f2fs_nm_info *nm_i = NM_I(sbi); unsigned char *version_bitmap; unsigned int nat_segs, nat_blocks; nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); /* segment_count_nat includes pair segment so divide to 2. */ nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); |
b63da15e8 f2fs: fix the cal... |
2152 |
|
7ee0eeabc f2fs: add availab... |
2153 |
nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; |
b63da15e8 f2fs: fix the cal... |
2154 |
/* not used nids: 0, node, meta, (and root counted as valid node) */ |
c200b1aa6 f2fs: fix incorre... |
2155 |
nm_i->available_nids = nm_i->max_nid - F2FS_RESERVED_NODE_NUM; |
e05df3b11 f2fs: add node op... |
2156 2157 |
nm_i->fcnt = 0; nm_i->nat_cnt = 0; |
cdfc41c13 f2fs: throttle th... |
2158 |
nm_i->ram_thresh = DEF_RAM_THRESHOLD; |
ea1a29a0b f2fs: export ra_n... |
2159 |
nm_i->ra_nid_pages = DEF_RA_NID_PAGES; |
2304cb0c4 f2fs: export dirt... |
2160 |
nm_i->dirty_nats_ratio = DEF_DIRTY_NAT_RATIO_THRESHOLD; |
e05df3b11 f2fs: add node op... |
2161 |
|
8a7ed66aa f2fs: introduce a... |
2162 |
INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC); |
e05df3b11 f2fs: add node op... |
2163 |
INIT_LIST_HEAD(&nm_i->free_nid_list); |
769ec6e5b f2fs: call radix_... |
2164 2165 |
INIT_RADIX_TREE(&nm_i->nat_root, GFP_NOIO); INIT_RADIX_TREE(&nm_i->nat_set_root, GFP_NOIO); |
e05df3b11 f2fs: add node op... |
2166 |
INIT_LIST_HEAD(&nm_i->nat_entries); |
e05df3b11 f2fs: add node op... |
2167 2168 2169 |
mutex_init(&nm_i->build_lock); spin_lock_init(&nm_i->free_nid_list_lock); |
b873b798a Revert "f2fs: use... |
2170 |
init_rwsem(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
2171 |
|
e05df3b11 f2fs: add node op... |
2172 |
nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); |
79b5793be f2fs: use kmemdup |
2173 |
nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); |
e05df3b11 f2fs: add node op... |
2174 2175 2176 |
version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); if (!version_bitmap) return -EFAULT; |
79b5793be f2fs: use kmemdup |
2177 2178 2179 2180 |
nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, GFP_KERNEL); if (!nm_i->nat_bitmap) return -ENOMEM; |
e05df3b11 f2fs: add node op... |
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 |
return 0; } int build_node_manager(struct f2fs_sb_info *sbi) { int err; sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL); if (!sbi->nm_info) return -ENOMEM; err = init_node_manager(sbi); if (err) return err; build_free_nids(sbi); return 0; } void destroy_node_manager(struct f2fs_sb_info *sbi) { struct f2fs_nm_info *nm_i = NM_I(sbi); struct free_nid *i, *next_i; struct nat_entry *natvec[NATVEC_SIZE]; |
7aed0d453 f2fs: free radix_... |
2205 |
struct nat_entry_set *setvec[SETVEC_SIZE]; |
e05df3b11 f2fs: add node op... |
2206 2207 2208 2209 2210 2211 2212 2213 2214 |
nid_t nid = 0; unsigned int found; if (!nm_i) return; /* destroy free nid list */ spin_lock(&nm_i->free_nid_list_lock); list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { |
9850cf4a8 f2fs: need fsck.f... |
2215 |
f2fs_bug_on(sbi, i->state == NID_ALLOC); |
8a7ed66aa f2fs: introduce a... |
2216 |
__del_from_free_nid_list(nm_i, i); |
e05df3b11 f2fs: add node op... |
2217 |
nm_i->fcnt--; |
cf0ee0f09 f2fs: avoid free ... |
2218 2219 2220 |
spin_unlock(&nm_i->free_nid_list_lock); kmem_cache_free(free_nid_slab, i); spin_lock(&nm_i->free_nid_list_lock); |
e05df3b11 f2fs: add node op... |
2221 |
} |
9850cf4a8 f2fs: need fsck.f... |
2222 |
f2fs_bug_on(sbi, nm_i->fcnt); |
e05df3b11 f2fs: add node op... |
2223 2224 2225 |
spin_unlock(&nm_i->free_nid_list_lock); /* destroy nat cache */ |
b873b798a Revert "f2fs: use... |
2226 |
down_write(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
2227 2228 2229 |
while ((found = __gang_lookup_nat_cache(nm_i, nid, NATVEC_SIZE, natvec))) { unsigned idx; |
7aed0d453 f2fs: free radix_... |
2230 |
|
b6ce391e6 f2fs: update star... |
2231 2232 2233 |
nid = nat_get_nid(natvec[found - 1]) + 1; for (idx = 0; idx < found; idx++) __del_from_nat_cache(nm_i, natvec[idx]); |
e05df3b11 f2fs: add node op... |
2234 |
} |
9850cf4a8 f2fs: need fsck.f... |
2235 |
f2fs_bug_on(sbi, nm_i->nat_cnt); |
7aed0d453 f2fs: free radix_... |
2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 |
/* destroy nat set cache */ nid = 0; while ((found = __gang_lookup_nat_set(nm_i, nid, SETVEC_SIZE, setvec))) { unsigned idx; nid = setvec[found - 1]->set + 1; for (idx = 0; idx < found; idx++) { /* entry_cnt is not zero, when cp_error was occurred */ f2fs_bug_on(sbi, !list_empty(&setvec[idx]->entry_list)); radix_tree_delete(&nm_i->nat_set_root, setvec[idx]->set); kmem_cache_free(nat_entry_set_slab, setvec[idx]); } } |
b873b798a Revert "f2fs: use... |
2251 |
up_write(&nm_i->nat_tree_lock); |
e05df3b11 f2fs: add node op... |
2252 2253 2254 2255 2256 |
kfree(nm_i->nat_bitmap); sbi->nm_info = NULL; kfree(nm_i); } |
6e6093a8f f2fs: add __init ... |
2257 |
int __init create_node_manager_caches(void) |
e05df3b11 f2fs: add node op... |
2258 2259 |
{ nat_entry_slab = f2fs_kmem_cache_create("nat_entry", |
e8512d2e0 f2fs: remove the ... |
2260 |
sizeof(struct nat_entry)); |
e05df3b11 f2fs: add node op... |
2261 |
if (!nat_entry_slab) |
aec71382c f2fs: refactor fl... |
2262 |
goto fail; |
e05df3b11 f2fs: add node op... |
2263 2264 |
free_nid_slab = f2fs_kmem_cache_create("free_nid", |
e8512d2e0 f2fs: remove the ... |
2265 |
sizeof(struct free_nid)); |
aec71382c f2fs: refactor fl... |
2266 |
if (!free_nid_slab) |
ce3e6d25f f2fs: fix typos f... |
2267 |
goto destroy_nat_entry; |
aec71382c f2fs: refactor fl... |
2268 2269 2270 2271 |
nat_entry_set_slab = f2fs_kmem_cache_create("nat_entry_set", sizeof(struct nat_entry_set)); if (!nat_entry_set_slab) |
ce3e6d25f f2fs: fix typos f... |
2272 |
goto destroy_free_nid; |
e05df3b11 f2fs: add node op... |
2273 |
return 0; |
aec71382c f2fs: refactor fl... |
2274 |
|
ce3e6d25f f2fs: fix typos f... |
2275 |
destroy_free_nid: |
aec71382c f2fs: refactor fl... |
2276 |
kmem_cache_destroy(free_nid_slab); |
ce3e6d25f f2fs: fix typos f... |
2277 |
destroy_nat_entry: |
aec71382c f2fs: refactor fl... |
2278 2279 2280 |
kmem_cache_destroy(nat_entry_slab); fail: return -ENOMEM; |
e05df3b11 f2fs: add node op... |
2281 2282 2283 2284 |
} void destroy_node_manager_caches(void) { |
aec71382c f2fs: refactor fl... |
2285 |
kmem_cache_destroy(nat_entry_set_slab); |
e05df3b11 f2fs: add node op... |
2286 2287 2288 |
kmem_cache_destroy(free_nid_slab); kmem_cache_destroy(nat_entry_slab); } |