Blame view

fs/f2fs/node.c 56.8 KB
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1
  /*
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: activate f2...
22
  #include "trace.h"
51dd62493   Namjae Jeon   f2fs: add tracepo...
23
  #include <trace/events/f2fs.h>
e05df3b11   Jaegeuk Kim   f2fs: add node op...
24

f978f5a06   Gu Zheng   f2fs: introduce h...
25
  #define on_build_free_nids(nmi) mutex_is_locked(&nm_i->build_lock)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
26
27
  static struct kmem_cache *nat_entry_slab;
  static struct kmem_cache *free_nid_slab;
aec71382c   Chao Yu   f2fs: refactor fl...
28
  static struct kmem_cache *nat_entry_set_slab;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
29

6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
30
  bool available_free_memory(struct f2fs_sb_info *sbi, int type)
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
31
  {
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
32
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
33
  	struct sysinfo val;
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
34
  	unsigned long avail_ram;
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
35
  	unsigned long mem_size = 0;
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
36
  	bool res = false;
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
37
38
  
  	si_meminfo(&val);
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
39
40
41
  
  	/* only uses low memory */
  	avail_ram = val.totalram - val.totalhigh;
429511cdf   Chao Yu   f2fs: add core fu...
42
43
44
  	/*
  	 * give 25%, 25%, 50%, 50%, 50% memory for each components respectively
  	 */
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
45
  	if (type == FREE_NIDS) {
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
46
  		mem_size = (nm_i->fcnt * sizeof(struct free_nid)) >>
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
47
  							PAGE_SHIFT;
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
48
  		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
49
  	} else if (type == NAT_ENTRIES) {
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
50
  		mem_size = (nm_i->nat_cnt * sizeof(struct nat_entry)) >>
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
51
  							PAGE_SHIFT;
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
52
  		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 2);
e589c2c47   Jaegeuk Kim   f2fs: control not...
53
54
  		if (excess_cached_nats(sbi))
  			res = false;
a12570232   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: control the...
60
61
  	} else if (type == INO_ENTRIES) {
  		int i;
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
62
  		for (i = 0; i <= UPDATE_INO; i++)
67298804f   Chao Yu   f2fs: introduce s...
63
  			mem_size += (sbi->im[i].ino_num *
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
64
  				sizeof(struct ino_entry)) >> PAGE_SHIFT;
e5e7ea3c8   Jaegeuk Kim   f2fs: control the...
65
  		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
429511cdf   Chao Yu   f2fs: add core fu...
66
  	} else if (type == EXTENT_CACHE) {
7441ccef3   Jaegeuk Kim   f2fs: use atomic ...
67
68
  		mem_size = (atomic_read(&sbi->total_ext_tree) *
  				sizeof(struct extent_tree) +
429511cdf   Chao Yu   f2fs: add core fu...
69
  				atomic_read(&sbi->total_ext_node) *
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
70
  				sizeof(struct extent_node)) >> PAGE_SHIFT;
429511cdf   Chao Yu   f2fs: add core fu...
71
  		res = mem_size < ((avail_ram * nm_i->ram_thresh / 100) >> 1);
1e84371ff   Jaegeuk Kim   f2fs: change atom...
72
  	} else {
1663cae48   Jaegeuk Kim   f2fs: fix wrong m...
73
74
  		if (!sbi->sb->s_bdi->wb.dirty_exceeded)
  			return true;
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
75
76
  	}
  	return res;
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
77
  }
e05df3b11   Jaegeuk Kim   f2fs: add node op...
78
79
80
  static void clear_node_page_dirty(struct page *page)
  {
  	struct address_space *mapping = page->mapping;
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
91
  		dec_page_count(F2FS_M_SB(mapping), F2FS_DIRTY_NODES);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
117
  	dst_page = grab_meta_page(sbi, dst_off);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
118
  	f2fs_bug_on(sbi, PageDirty(src_page));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
119
120
121
  
  	src_addr = page_address(src_page);
  	dst_addr = page_address(dst_page);
09cbfeaf1   Kirill A. Shutemov   mm, fs: get rid o...
122
  	memcpy(dst_addr, src_addr, PAGE_SIZE);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: do retry op...
156

309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
157
158
  	head = radix_tree_lookup(&nm_i->nat_set_root, set);
  	if (!head) {
80c545055   Jaegeuk Kim   f2fs: use __GFP_N...
159
  		head = f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_NOFS);
309cc2b6e   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: do retry op...
165
  		f2fs_radix_tree_insert(&nm_i->nat_set_root, set, head);
309cc2b6e   Jaegeuk Kim   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   Changman Lee   f2fs: check dirty...
176
  	nid_t set = NAT_BLOCK_OFFSET(ne->ni.nid);
309cc2b6e   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add need_de...
194
  int need_dentry_mark(struct f2fs_sb_info *sbi, nid_t nid)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
195
196
197
  {
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
  	struct nat_entry *e;
2dcf51ab2   Jaegeuk Kim   f2fs: add need_de...
198
  	bool need = false;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
199

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
200
  	down_read(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
201
  	e = __lookup_nat_cache(nm_i, nid);
2dcf51ab2   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
207
  	up_read(&nm_i->nat_tree_lock);
2dcf51ab2   Jaegeuk Kim   f2fs: add need_de...
208
  	return need;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
209
  }
2dcf51ab2   Jaegeuk Kim   f2fs: add need_de...
210
  bool is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid)
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
211
212
213
  {
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
  	struct nat_entry *e;
2dcf51ab2   Jaegeuk Kim   f2fs: add need_de...
214
  	bool is_cp = true;
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
215

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
216
  	down_read(&nm_i->nat_tree_lock);
2dcf51ab2   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
220
  	up_read(&nm_i->nat_tree_lock);
2dcf51ab2   Jaegeuk Kim   f2fs: add need_de...
221
  	return is_cp;
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
222
  }
88bd02c94   Jaegeuk Kim   f2fs: fix conditi...
223
  bool need_inode_block_update(struct f2fs_sb_info *sbi, nid_t ino)
b6fe5873c   Jaegeuk Kim   f2fs: fix to reco...
224
225
226
  {
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
  	struct nat_entry *e;
88bd02c94   Jaegeuk Kim   f2fs: fix conditi...
227
  	bool need_update = true;
b6fe5873c   Jaegeuk Kim   f2fs: fix to reco...
228

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
229
  	down_read(&nm_i->nat_tree_lock);
88bd02c94   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
235
  	up_read(&nm_i->nat_tree_lock);
88bd02c94   Jaegeuk Kim   f2fs: fix conditi...
236
  	return need_update;
b6fe5873c   Jaegeuk Kim   f2fs: fix to reco...
237
  }
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: use __GFP_N...
241
  	new = f2fs_kmem_cache_alloc(nat_entry_slab, GFP_NOFS);
9be32d72b   Jaegeuk Kim   f2fs: do retry op...
242
  	f2fs_radix_tree_insert(&nm_i->nat_root, nid, new);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
243
244
  	memset(new, 0, sizeof(struct nat_entry));
  	nat_set_nid(new, nid);
88bd02c94   Jaegeuk Kim   f2fs: fix conditi...
245
  	nat_reset_flag(new);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
246
247
248
249
  	list_add_tail(&new->list, &nm_i->nat_entries);
  	nm_i->nat_cnt++;
  	return new;
  }
1515aef01   Chao Yu   f2fs: reorder nat...
250
  static void cache_nat_entry(struct f2fs_sb_info *sbi, nid_t nid,
e05df3b11   Jaegeuk Kim   f2fs: add node op...
251
252
  						struct f2fs_nat_entry *ne)
  {
1515aef01   Chao Yu   f2fs: reorder nat...
253
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
254
  	struct nat_entry *e;
9be32d72b   Jaegeuk Kim   f2fs: do retry op...
255

e05df3b11   Jaegeuk Kim   f2fs: add node op...
256
257
258
  	e = __lookup_nat_cache(nm_i, nid);
  	if (!e) {
  		e = grab_nat_entry(nm_i, nid);
94dac22e7   Chao Yu   f2fs: introduce r...
259
  		node_info_from_raw_nat(&e->ni, ne);
1515aef01   Chao Yu   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   Jaegeuk Kim   f2fs: add node op...
264
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
265
266
267
  }
  
  static void set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni,
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
268
  			block_t new_blkaddr, bool fsync_done)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
269
270
271
  {
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
  	struct nat_entry *e;
9be32d72b   Jaegeuk Kim   f2fs: do retry op...
272

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
273
  	down_write(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: merge two u...
277
  		copy_node_info(&e->ni, ni);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
278
  		f2fs_bug_on(sbi, ni->blk_addr == NEW_ADDR);
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: merge two u...
285
  		copy_node_info(&e->ni, ni);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
286
  		f2fs_bug_on(sbi, ni->blk_addr != NULL_ADDR);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
287
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
288
  	/* sanity check */
9850cf4a8   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
291
  			new_blkaddr == NULL_ADDR);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
292
  	f2fs_bug_on(sbi, nat_get_blkaddr(e) == NEW_ADDR &&
e05df3b11   Jaegeuk Kim   f2fs: add node op...
293
  			new_blkaddr == NEW_ADDR);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
294
  	f2fs_bug_on(sbi, nat_get_blkaddr(e) != NEW_ADDR &&
e05df3b11   Jaegeuk Kim   f2fs: add node op...
295
296
  			nat_get_blkaddr(e) != NULL_ADDR &&
  			new_blkaddr == NEW_ADDR);
e1c420452   arter97   f2fs: fix typo
297
  	/* increment version no as node is removed */
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
305
306
307
308
  	}
  
  	/* change address */
  	nat_set_blkaddr(e, new_blkaddr);
88bd02c94   Jaegeuk Kim   f2fs: fix conditi...
309
310
  	if (new_blkaddr == NEW_ADDR || new_blkaddr == NULL_ADDR)
  		set_nat_flag(e, IS_CHECKPOINTED, false);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
311
  	__set_nat_cache_dirty(nm_i, e);
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
312
313
  
  	/* update fsync_mark if its inode nat entry is still alive */
d5b692b78   Chao Yu   f2fs: do not re-l...
314
315
  	if (ni->nid != ni->ino)
  		e = __lookup_nat_cache(nm_i, ni->ino);
88bd02c94   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
321
  	up_write(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
322
  }
4660f9c0f   Jaegeuk Kim   f2fs: introduce f...
323
  int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
324
325
  {
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
1b38dc8e7   Jaegeuk Kim   f2fs: shrink nat_...
326
  	int nr = nr_shrink;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
327

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
328
329
  	if (!down_write_trylock(&nm_i->nat_tree_lock))
  		return 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
330

e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
338
  	up_write(&nm_i->nat_tree_lock);
1b38dc8e7   Jaegeuk Kim   f2fs: shrink nat_...
339
  	return nr - nr_shrink;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
340
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
341
  /*
e1c420452   arter97   f2fs: fix typo
342
   * This function always returns success
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: split journ...
348
  	struct f2fs_journal *journal = curseg->journal;
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
359
  	down_read(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
365
  		up_read(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
366
  		return;
1515aef01   Chao Yu   f2fs: reorder nat...
367
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
368

3547ea961   Jaegeuk Kim   f2fs: avoid poten...
369
  	memset(&ne, 0, sizeof(struct f2fs_nat_entry));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
370
  	/* Check current segment summary */
b7ad7512b   Chao Yu   f2fs: split journ...
371
  	down_read(&curseg->journal_rwsem);
dfc08a12e   Chao Yu   f2fs: introduce f...
372
  	i = lookup_journal_in_cursum(journal, NAT_JOURNAL, nid, 0);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
373
  	if (i >= 0) {
dfc08a12e   Chao Yu   f2fs: introduce f...
374
  		ne = nat_in_journal(journal, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
375
376
  		node_info_from_raw_nat(ni, &ne);
  	}
b7ad7512b   Chao Yu   f2fs: split journ...
377
  	up_read(&curseg->journal_rwsem);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
388
  	up_read(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
389
  	/* cache nat entry */
b873b798a   Jaegeuk Kim   Revert "f2fs: use...
390
  	down_write(&nm_i->nat_tree_lock);
1515aef01   Chao Yu   f2fs: reorder nat...
391
  	cache_nat_entry(sbi, nid, &ne);
b873b798a   Jaegeuk Kim   Revert "f2fs: use...
392
  	up_write(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
393
  }
79344efb9   Jaegeuk Kim   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   Chao Yu   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   Jaegeuk Kim   f2fs: adjust kern...
446
  /*
e05df3b11   Jaegeuk Kim   f2fs: add node op...
447
448
449
   * The maximum depth is four.
   * Offset[0] will have raw inode offset.
   */
81ca7350c   Chao Yu   f2fs: remove unne...
450
  static int get_node_path(struct inode *inode, long block,
de93653fe   Jaegeuk Kim   f2fs: reserve the...
451
  				int offset[4], unsigned int noffset[4])
e05df3b11   Jaegeuk Kim   f2fs: add node op...
452
  {
81ca7350c   Chao Yu   f2fs: remove unne...
453
  	const long direct_index = ADDRS_PER_INODE(inode);
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
464
  		offset[n] = block;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
471
  		offset[n] = block;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
479
  		offset[n] = block;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
489
  		offset[n] = block % direct_blks;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
499
  		offset[n] = block % direct_blks;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: avoid extra...
514
  		offset[n] = block % direct_blks;
e05df3b11   Jaegeuk Kim   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   Chao Yu   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   Jaegeuk Kim   f2fs: introduce a...
528
   * In the case of RDONLY_NODE, we don't need to care about mutex.
e05df3b11   Jaegeuk Kim   f2fs: add node op...
529
   */
266e97a81   Jaegeuk Kim   f2fs: introduce r...
530
  int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
531
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
532
  	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
533
  	struct page *npage[4];
f1a3b98e7   Jaegeuk Kim   f2fs: fix accessi...
534
  	struct page *parent = NULL;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
535
536
537
  	int offset[4];
  	unsigned int noffset[4];
  	nid_t nids[4];
3cf457470   Chao Yu   f2fs: introduce g...
538
  	int level, i = 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
539
  	int err = 0;
81ca7350c   Chao Yu   f2fs: remove unne...
540
  	level = get_node_path(dn->inode, index, offset, noffset);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
541
542
  
  	nids[0] = dn->inode->i_ino;
1646cfac9   Jaegeuk Kim   f2fs: skip get_no...
543
  	npage[0] = dn->inode_page;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
544

1646cfac9   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: report -ENO...
553
  		err = -ENOENT;
f1a3b98e7   Jaegeuk Kim   f2fs: fix accessi...
554
555
556
  		f2fs_put_page(npage[0], 1);
  		goto release_out;
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
557
  	parent = npage[0];
52c2db3f9   Changman Lee   f2fs: check the l...
558
559
  	if (level != 0)
  		nids[1] = get_nid(parent, offset[0], true);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce r...
566
  		if (!nids[i] && mode == ALLOC_NODE) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
567
568
  			/* alloc new node */
  			if (!alloc_nid(sbi, &(nids[i]))) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
569
570
571
572
573
  				err = -ENOSPC;
  				goto release_pages;
  			}
  
  			dn->nid = nids[i];
8ae8f1627   Jaegeuk Kim   f2fs: support xat...
574
  			npage[i] = new_node_page(dn, noffset[i], NULL);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
575
576
  			if (IS_ERR(npage[i])) {
  				alloc_nid_failed(sbi, nids[i]);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
583
  			done = true;
266e97a81   Jaegeuk Kim   f2fs: introduce r...
584
  		} else if (mode == LOOKUP_NODE_RA && i == level && level > 1) {
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: introduce g...
625
626
627
  	if (err == -ENOENT) {
  		dn->cur_level = i;
  		dn->max_level = level;
0a2aa8fbb   Jaegeuk Kim   f2fs: refactor __...
628
  		dn->ofs_in_node = offset[level];
3cf457470   Chao Yu   f2fs: introduce g...
629
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
630
631
632
633
634
  	return err;
  }
  
  static void truncate_node(struct dnode_of_data *dn)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
635
  	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
636
637
638
  	struct node_info ni;
  
  	get_node_info(sbi, dn->nid, &ni);
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
639
  	if (dn->inode->i_blocks == 0) {
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
640
  		f2fs_bug_on(sbi, ni.blk_addr != NULL_ADDR);
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
641
642
  		goto invalidate;
  	}
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
643
  	f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
644

e05df3b11   Jaegeuk Kim   f2fs: add node op...
645
  	/* Deallocate node address */
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
646
  	invalidate_blocks(sbi, ni.blk_addr);
ef86d7099   Gu Zheng   f2fs: convert inc...
647
  	dec_valid_node_count(sbi, dn->inode);
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
648
  	set_node_addr(sbi, &ni, NULL_ADDR, false);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: flush inode...
653
  		f2fs_inode_synced(dn->inode);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
654
  	}
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
655
  invalidate:
e05df3b11   Jaegeuk Kim   f2fs: add node op...
656
  	clear_node_page_dirty(dn->node_page);
caf0047e7   Chao Yu   f2fs: merge flags...
657
  	set_sbi_flag(sbi, SBI_IS_DIRTY);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
658
659
  
  	f2fs_put_page(dn->node_page, 1);
bf39c00a9   Jaegeuk Kim   f2fs: drop obsole...
660
661
662
  
  	invalidate_mapping_pages(NODE_MAPPING(sbi),
  			dn->node_page->index, dn->node_page->index);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
663
  	dn->node_page = NULL;
51dd62493   Namjae Jeon   f2fs: add tracepo...
664
  	trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
665
666
667
668
  }
  
  static int truncate_dnode(struct dnode_of_data *dn)
  {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
669
670
671
672
673
674
  	struct page *page;
  
  	if (dn->nid == 0)
  		return 1;
  
  	/* get direct node */
4081363fb   Jaegeuk Kim   f2fs: introduce F...
675
  	page = get_node_page(F2FS_I_SB(dn->inode), dn->nid);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   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   Namjae Jeon   f2fs: add tracepo...
702
  	trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr);
4081363fb   Jaegeuk Kim   f2fs: introduce F...
703
  	page = get_node_page(F2FS_I_SB(dn->inode), dn->nid);
51dd62493   Namjae Jeon   f2fs: add tracepo...
704
705
  	if (IS_ERR(page)) {
  		trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
706
  		return PTR_ERR(page);
51dd62493   Namjae Jeon   f2fs: add tracepo...
707
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
708

79344efb9   Jaegeuk Kim   f2fs: read node b...
709
  	ra_node_pages(page, ofs, NIDS_PER_BLOCK);
455907106   Gu Zheng   f2fs: introduce h...
710
  	rn = F2FS_NODE(page);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid unnec...
720
721
  			if (set_nid(page, i, 0, false))
  				dn->node_changed = true;
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid unnec...
734
735
  				if (set_nid(page, i, 0, false))
  					dn->node_changed = true;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: add tracepo...
752
  	trace_f2fs_truncate_nodes_exit(dn->inode, freed);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
753
754
755
756
  	return freed;
  
  out_err:
  	f2fs_put_page(page, 1);
51dd62493   Namjae Jeon   f2fs: add tracepo...
757
  	trace_f2fs_truncate_nodes_exit(dn->inode, ret);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   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   shifei10.ge   f2fs: fix truncat...
776
  	for (i = 0; i < idx + 1; i++) {
e1c420452   arter97   f2fs: fix typo
777
  		/* reference count'll be increased */
4081363fb   Jaegeuk Kim   f2fs: introduce F...
778
  		pages[i] = get_node_page(F2FS_I_SB(dn->inode), nid[i]);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
779
  		if (IS_ERR(pages[i])) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
780
  			err = PTR_ERR(pages[i]);
a225dca39   shifei10.ge   f2fs: fix truncat...
781
  			idx = i - 1;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
782
783
784
785
  			goto fail;
  		}
  		nid[i + 1] = get_nid(pages[i], offset[i + 1], false);
  	}
79344efb9   Jaegeuk Kim   f2fs: read node b...
786
  	ra_node_pages(pages[idx], offset[idx + 1], NIDS_PER_BLOCK);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
787
  	/* free direct nodes linked to a partial indirect node */
a225dca39   shifei10.ge   f2fs: fix truncat...
788
  	for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) {
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid unnec...
796
797
  		if (set_nid(pages[idx], i, 0, false))
  			dn->node_changed = true;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
798
  	}
a225dca39   shifei10.ge   f2fs: fix truncat...
799
  	if (offset[idx + 1] == 0) {
e05df3b11   Jaegeuk Kim   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   shifei10.ge   f2fs: fix truncat...
807
808
  	offset[idx + 1] = 0;
  	idx--;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
809
  fail:
a225dca39   shifei10.ge   f2fs: fix truncat...
810
  	for (i = idx; i >= 0; i--)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
811
  		f2fs_put_page(pages[i], 1);
51dd62493   Namjae Jeon   f2fs: add tracepo...
812
813
  
  	trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
814
815
  	return err;
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
816
  /*
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
821
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
822
823
  	int err = 0, cont = 1;
  	int level, offset[4], noffset[4];
7dd690c82   Jaegeuk Kim   f2fs: avoid build...
824
  	unsigned int nofs = 0;
58bfaf44d   Jaegeuk Kim   f2fs: introduce F...
825
  	struct f2fs_inode *ri;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
826
827
  	struct dnode_of_data dn;
  	struct page *page;
51dd62493   Namjae Jeon   f2fs: add tracepo...
828
  	trace_f2fs_truncate_inode_blocks_enter(inode, from);
81ca7350c   Chao Yu   f2fs: remove unne...
829
  	level = get_node_path(inode, from, offset, noffset);
ff3735588   Jaegeuk Kim   f2fs: add BUG_ON ...
830

e05df3b11   Jaegeuk Kim   f2fs: add node op...
831
  	page = get_node_page(sbi, inode->i_ino);
51dd62493   Namjae Jeon   f2fs: add tracepo...
832
833
  	if (IS_ERR(page)) {
  		trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
834
  		return PTR_ERR(page);
51dd62493   Namjae Jeon   f2fs: add tracepo...
835
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
836
837
838
  
  	set_new_dnode(&dn, inode, page, NULL, 0);
  	unlock_page(page);
58bfaf44d   Jaegeuk Kim   f2fs: introduce F...
839
  	ri = F2FS_INODE(page);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
849
  		err = truncate_partial_nodes(&dn, ri, offset, level);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
858
  		err = truncate_partial_nodes(&dn, ri, offset, level);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
868
  		dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce F...
891
  				ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
892
  			lock_page(page);
ff3735588   Jaegeuk Kim   f2fs: add BUG_ON ...
893
  			BUG_ON(page->mapping != NODE_MAPPING(sbi));
fec1d6576   Jaegeuk Kim   f2fs: use wait_fo...
894
  			f2fs_wait_on_page_writeback(page, NODE, true);
58bfaf44d   Jaegeuk Kim   f2fs: introduce F...
895
  			ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0;
e05df3b11   Jaegeuk Kim   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   Namjae Jeon   f2fs: add tracepo...
905
  	trace_f2fs_truncate_inode_blocks_exit(inode, err);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
906
907
  	return err > 0 ? 0 : err;
  }
4f16fb0f9   Jaegeuk Kim   f2fs: add the tru...
908
909
  int truncate_xattr_node(struct inode *inode, struct page *page)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
910
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
4f16fb0f9   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: call mark_i...
921
  	f2fs_i_xnid_write(inode, 0);
65985d935   Jaegeuk Kim   f2fs: support the...
922
923
924
  
  	/* need to do checkpoint during fsync */
  	F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi));
4f16fb0f9   Jaegeuk Kim   f2fs: add the tru...
925
926
927
  	set_new_dnode(&dn, inode, page, npage, nid);
  
  	if (page)
01d2d1aa0   Chao Yu   f2fs: use true an...
928
  		dn.inode_page_locked = true;
4f16fb0f9   Jaegeuk Kim   f2fs: add the tru...
929
930
931
  	truncate_node(&dn);
  	return 0;
  }
399368372   Jaegeuk Kim   f2fs: introduce a...
932
  /*
4f4124d0b   Chao Yu   f2fs: update seve...
933
934
   * Caller should grab and release a rwsem by calling f2fs_lock_op() and
   * f2fs_unlock_op().
399368372   Jaegeuk Kim   f2fs: introduce a...
935
   */
13ec7297e   Chao Yu   f2fs: fix to rele...
936
  int remove_inode_page(struct inode *inode)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
937
  {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
938
  	struct dnode_of_data dn;
13ec7297e   Chao Yu   f2fs: fix to rele...
939
  	int err;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
940

c2e69583a   Jaegeuk Kim   f2fs: truncate st...
941
  	set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
13ec7297e   Chao Yu   f2fs: fix to rele...
942
943
944
  	err = get_dnode_of_data(&dn, 0, LOOKUP_NODE);
  	if (err)
  		return err;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
945

13ec7297e   Chao Yu   f2fs: fix to rele...
946
947
  	err = truncate_xattr_node(inode, dn.inode_page);
  	if (err) {
c2e69583a   Jaegeuk Kim   f2fs: truncate st...
948
  		f2fs_put_dnode(&dn);
13ec7297e   Chao Yu   f2fs: fix to rele...
949
  		return err;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
950
  	}
c2e69583a   Jaegeuk Kim   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   arter97   f2fs: fix typo
956
  	/* 0 is possible, after f2fs_new_inode() has failed */
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
957
958
  	f2fs_bug_on(F2FS_I_SB(inode),
  			inode->i_blocks != 0 && inode->i_blocks != 1);
c2e69583a   Jaegeuk Kim   f2fs: truncate st...
959
960
  
  	/* will put inode & node pages */
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
961
  	truncate_node(&dn);
13ec7297e   Chao Yu   f2fs: fix to rele...
962
  	return 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
963
  }
a014e037b   Jaegeuk Kim   f2fs: clean up an...
964
  struct page *new_inode_page(struct inode *inode)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
965
  {
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: update inod...
970
971
  
  	/* caller should f2fs_put_page(page, 1); */
8ae8f1627   Jaegeuk Kim   f2fs: support xat...
972
  	return new_node_page(&dn, 0, NULL);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
973
  }
8ae8f1627   Jaegeuk Kim   f2fs: support xat...
974
975
  struct page *new_node_page(struct dnode_of_data *dn,
  				unsigned int ofs, struct page *ipage)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
976
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
977
  	struct f2fs_sb_info *sbi = F2FS_I_SB(dn->inode);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
978
979
980
  	struct node_info old_ni, new_ni;
  	struct page *page;
  	int err;
91942321e   Jaegeuk Kim   f2fs: use inode p...
981
  	if (unlikely(is_inode_flag_set(dn->inode, FI_NO_ALLOC)))
e05df3b11   Jaegeuk Kim   f2fs: add node op...
982
  		return ERR_PTR(-EPERM);
300e129c1   Jaegeuk Kim   f2fs: use f2fs_gr...
983
  	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), dn->nid, false);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
984
985
  	if (!page)
  		return ERR_PTR(-ENOMEM);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
986
  	if (unlikely(!inc_valid_node_count(sbi, dn->inode))) {
9c02740c0   Jaegeuk Kim   f2fs: check the f...
987
988
989
  		err = -ENOSPC;
  		goto fail;
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
990

9c02740c0   Jaegeuk Kim   f2fs: check the f...
991
  	get_node_info(sbi, dn->nid, &old_ni);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
992
993
  
  	/* Reinitialize old_ni with new node page */
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
994
  	f2fs_bug_on(sbi, old_ni.blk_addr != NULL_ADDR);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
995
996
  	new_ni = old_ni;
  	new_ni.ino = dn->inode->i_ino;
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
997
  	set_node_addr(sbi, &new_ni, NEW_ADDR, false);
9c02740c0   Jaegeuk Kim   f2fs: check the f...
998

fec1d6576   Jaegeuk Kim   f2fs: use wait_fo...
999
  	f2fs_wait_on_page_writeback(page, NODE, true);
9c02740c0   Jaegeuk Kim   f2fs: check the f...
1000
  	fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true);
398b1ac5a   Jaegeuk Kim   f2fs: fix handlin...
1001
  	set_cold_node(dn->inode, page);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
1002
1003
  	if (!PageUptodate(page))
  		SetPageUptodate(page);
12719ae14   Jaegeuk Kim   f2fs: avoid unnec...
1004
1005
  	if (set_page_dirty(page))
  		dn->node_changed = true;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1006

4bc8e9bcf   Chao Yu   f2fs: introduce f...
1007
  	if (f2fs_has_xattr_block(ofs))
205b98221   Jaegeuk Kim   f2fs: call mark_i...
1008
  		f2fs_i_xnid_write(dn->inode, dn->nid);
479bd73ac   Jaegeuk Kim   f2fs: should cove...
1009

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1010
1011
  	if (ofs == 0)
  		inc_valid_inode_count(sbi);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1012
1013
1014
  	return page;
  
  fail:
71e9fec54   Jaegeuk Kim   f2fs: invalidate ...
1015
  	clear_node_page_dirty(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1016
1017
1018
  	f2fs_put_page(page, 1);
  	return ERR_PTR(err);
  }
56ae674cc   Jaegeuk Kim   f2fs: remove redu...
1019
1020
1021
  /*
   * Caller should do after getting the following values.
   * 0: f2fs_put_page(page, 0)
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
1022
   * LOCKED_PAGE or error: f2fs_put_page(page, 1)
56ae674cc   Jaegeuk Kim   f2fs: remove redu...
1023
   */
04d328def   Mike Christie   f2fs: use bio op ...
1024
  static int read_node_page(struct page *page, int op_flags)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1025
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1026
  	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1027
  	struct node_info ni;
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
1028
  	struct f2fs_io_info fio = {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1029
  		.sbi = sbi,
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
1030
  		.type = NODE,
04d328def   Mike Christie   f2fs: use bio op ...
1031
1032
  		.op = REQ_OP_READ,
  		.op_flags = op_flags,
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1033
  		.page = page,
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
1034
  		.encrypted_page = NULL,
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
1035
  	};
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1036

3bdad3c7e   Jaegeuk Kim   f2fs: skip to che...
1037
1038
  	if (PageUptodate(page))
  		return LOCKED_PAGE;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1039
  	get_node_info(sbi, page->index, &ni);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
1040
  	if (unlikely(ni.blk_addr == NULL_ADDR)) {
2bca1e238   Jaegeuk Kim   f2fs: clear page'...
1041
  		ClearPageUptodate(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1042
  		return -ENOENT;
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
1043
  	}
7a9d75481   Chao Yu   f2fs: trace old b...
1044
  	fio.new_blkaddr = fio.old_blkaddr = ni.blk_addr;
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1045
  	return f2fs_submit_page_bio(&fio);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1046
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1047
  /*
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
1052
  	struct page *apage;
56ae674cc   Jaegeuk Kim   f2fs: remove redu...
1053
  	int err;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1054

e84587250   Chao Yu   f2fs: check node ...
1055
1056
1057
  	if (!nid)
  		return;
  	f2fs_bug_on(sbi, check_nid_range(sbi, nid));
999270de3   Fan Li   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   Jaegeuk Kim   f2fs: reduce unnc...
1062
  		return;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1063

300e129c1   Jaegeuk Kim   f2fs: use f2fs_gr...
1064
  	apage = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1065
1066
  	if (!apage)
  		return;
70246286e   Christoph Hellwig   block: get rid of...
1067
  	err = read_node_page(apage, REQ_RAHEAD);
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
1068
  	f2fs_put_page(apage, err ? 1 : 0);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1069
  }
17a0ee552   Jaegeuk Kim   f2fs: declare sta...
1070
  static struct page *__get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid,
0e022ea8f   Chao Yu   f2fs: introduce _...
1071
  					struct page *parent, int start)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1072
  {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1073
  	struct page *page;
0e022ea8f   Chao Yu   f2fs: introduce _...
1074
  	int err;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1075

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1076
1077
  	if (!nid)
  		return ERR_PTR(-ENOENT);
e84587250   Chao Yu   f2fs: check node ...
1078
  	f2fs_bug_on(sbi, check_nid_range(sbi, nid));
afcb7ca01   Jaegeuk Kim   f2fs: check trunc...
1079
  repeat:
300e129c1   Jaegeuk Kim   f2fs: use f2fs_gr...
1080
  	page = f2fs_grab_cache_page(NODE_MAPPING(sbi), nid, false);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1081
1082
  	if (!page)
  		return ERR_PTR(-ENOMEM);
66d36a294   Jaegeuk Kim   f2fs: read with R...
1083
  	err = read_node_page(page, READ_SYNC);
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
1084
1085
  	if (err < 0) {
  		f2fs_put_page(page, 1);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1086
  		return ERR_PTR(err);
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
1087
  	} else if (err == LOCKED_PAGE) {
56ae674cc   Jaegeuk Kim   f2fs: remove redu...
1088
  		goto page_hit;
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
1089
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1090

0e022ea8f   Chao Yu   f2fs: introduce _...
1091
  	if (parent)
79344efb9   Jaegeuk Kim   f2fs: read node b...
1092
  		ra_node_pages(parent, start + 1, MAX_RA_NODE);
c718379b6   Jaegeuk Kim   f2fs: give a chan...
1093

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1094
  	lock_page(page);
0e022ea8f   Chao Yu   f2fs: introduce _...
1095

4ef51a8fc   Jaegeuk Kim   f2fs: introduce N...
1096
  	if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
afcb7ca01   Jaegeuk Kim   f2fs: check trunc...
1097
1098
1099
  		f2fs_put_page(page, 1);
  		goto repeat;
  	}
1563ac75e   Chao Yu   f2fs: fix to dete...
1100
1101
1102
  
  	if (unlikely(!PageUptodate(page)))
  		goto out_err;
e0f56cb44   Namjae Jeon   f2fs: optimize ge...
1103
  page_hit:
0c9df7fb8   Yunlong Song   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   Jaegeuk Kim   f2fs: add node op...
1111
1112
  	return page;
  }
0e022ea8f   Chao Yu   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   Jaegeuk Kim   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   Chao Yu   f2fs: fix to upda...
1129
  	int ret;
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1130
1131
1132
1133
1134
  
  	/* should flush inline_data before evict_inode */
  	inode = ilookup(sbi->sb, ino);
  	if (!inode)
  		return;
4a6de50d5   Jaegeuk Kim   f2fs: use PGP_LOC...
1135
  	page = pagecache_get_page(inode->i_mapping, 0, FGP_LOCK|FGP_NOWAIT, 0);
2049d4fcb   Jaegeuk Kim   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   Chao Yu   f2fs: fix to upda...
1147
1148
1149
  	ret = f2fs_write_inline_data(inode, page);
  	inode_dec_dirty_pages(inode);
  	if (ret)
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1150
1151
  		set_page_dirty(page);
  page_out:
4a6de50d5   Jaegeuk Kim   f2fs: use PGP_LOC...
1152
  	f2fs_put_page(page, 1);
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1153
1154
1155
  iput_out:
  	iput(inode);
  }
da011cc0d   Chao Yu   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid unnec...
1245
  int fsync_node_pages(struct f2fs_sb_info *sbi, struct inode *inode,
608514deb   Jaegeuk Kim   f2fs: set fsync m...
1246
  			struct writeback_control *wbc, bool atomic)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1247
  {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1248
1249
  	pgoff_t index, end;
  	struct pagevec pvec;
c267ec152   Jaegeuk Kim   f2fs: report unwr...
1250
  	int ret = 0;
608514deb   Jaegeuk Kim   f2fs: set fsync m...
1251
1252
  	struct page *last_page = NULL;
  	bool marked = false;
26de9b117   Jaegeuk Kim   f2fs: avoid unnec...
1253
  	nid_t ino = inode->i_ino;
3f5f4959b   Chao Yu   f2fs: fix to comm...
1254
  	int nwritten = 0;
526813756   Jaegeuk Kim   f2fs: split sync_...
1255

608514deb   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: set fsync m...
1278
  				f2fs_put_page(last_page, 0);
526813756   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: set fsync m...
1297
  			if (!PageDirty(page) && page != last_page) {
526813756   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: split sync_...
1304

608514deb   Jaegeuk Kim   f2fs: set fsync m...
1305
1306
  			if (!atomic || page == last_page) {
  				set_fsync_mark(page, 1);
26de9b117   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: set fsync m...
1311
  					set_dentry_mark(page,
526813756   Jaegeuk Kim   f2fs: split sync_...
1312
  						need_dentry_mark(sbi, ino));
26de9b117   Jaegeuk Kim   f2fs: avoid unnec...
1313
  				}
608514deb   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: split sync_...
1321

c267ec152   Jaegeuk Kim   f2fs: report unwr...
1322
1323
  			ret = NODE_MAPPING(sbi)->a_ops->writepage(page, wbc);
  			if (ret) {
526813756   Jaegeuk Kim   f2fs: split sync_...
1324
  				unlock_page(page);
608514deb   Jaegeuk Kim   f2fs: set fsync m...
1325
1326
  				f2fs_put_page(last_page, 0);
  				break;
3f5f4959b   Chao Yu   f2fs: fix to comm...
1327
1328
  			} else {
  				nwritten++;
608514deb   Jaegeuk Kim   f2fs: set fsync m...
1329
  			}
3f5f4959b   Chao Yu   f2fs: fix to comm...
1330

608514deb   Jaegeuk Kim   f2fs: set fsync m...
1331
1332
1333
  			if (page == last_page) {
  				f2fs_put_page(page, 0);
  				marked = true;
526813756   Jaegeuk Kim   f2fs: split sync_...
1334
  				break;
c267ec152   Jaegeuk Kim   f2fs: report unwr...
1335
  			}
526813756   Jaegeuk Kim   f2fs: split sync_...
1336
1337
1338
  		}
  		pagevec_release(&pvec);
  		cond_resched();
608514deb   Jaegeuk Kim   f2fs: set fsync m...
1339
  		if (ret || marked)
526813756   Jaegeuk Kim   f2fs: split sync_...
1340
1341
  			break;
  	}
608514deb   Jaegeuk Kim   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   Chao Yu   f2fs: fix to comm...
1351
1352
1353
  
  	if (nwritten)
  		f2fs_submit_merged_bio_cond(sbi, NULL, NULL, ino, NODE, WRITE);
c267ec152   Jaegeuk Kim   f2fs: report unwr...
1354
  	return ret ? -EIO: 0;
526813756   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: submit node...
1362
  	int nwritten = 0;
3f5f4959b   Chao Yu   f2fs: fix to comm...
1363
  	int ret = 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1364
1365
1366
1367
1368
  
  	pagevec_init(&pvec, 0);
  
  next_step:
  	index = 0;
80dd9c0e9   Chao Yu   f2fs: fix incorre...
1369
  	end = ULONG_MAX;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1370
1371
1372
  
  	while (index <= end) {
  		int i, nr_pages;
4ef51a8fc   Jaegeuk Kim   f2fs: introduce N...
1373
  		nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index,
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: let user be...
1381
1382
  			if (unlikely(f2fs_cp_error(sbi))) {
  				pagevec_release(&pvec);
3f5f4959b   Chao Yu   f2fs: fix to comm...
1383
1384
  				ret = -EIO;
  				goto out;
6d5a1495e   Chao Yu   f2fs: let user be...
1385
  			}
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: try to flus...
1400
  lock_node:
526813756   Jaegeuk Kim   f2fs: split sync_...
1401
  			if (!trylock_page(page))
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1402
  				continue;
4ef51a8fc   Jaegeuk Kim   f2fs: introduce N...
1403
  			if (unlikely(page->mapping != NODE_MAPPING(sbi))) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1404
1405
1406
1407
  continue_unlock:
  				unlock_page(page);
  				continue;
  			}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1408
1409
1410
1411
1412
  
  			if (!PageDirty(page)) {
  				/* someone wrote it for us */
  				goto continue_unlock;
  			}
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1413
  			/* flush inline_data */
526813756   Jaegeuk Kim   f2fs: split sync_...
1414
  			if (is_inline_node(page)) {
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1415
1416
1417
  				clear_inline_node(page);
  				unlock_page(page);
  				flush_inline_data(sbi, ino_of_node(page));
9a4cbc9e5   Chao Yu   f2fs: try to flus...
1418
  				goto lock_node;
2049d4fcb   Jaegeuk Kim   f2fs: avoid multi...
1419
  			}
fa3d2bdf9   Jaegeuk Kim   f2fs: wait on pag...
1420
1421
1422
  			f2fs_wait_on_page_writeback(page, NODE, true);
  
  			BUG_ON(PageWriteback(page));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1423
1424
  			if (!clear_page_dirty_for_io(page))
  				goto continue_unlock;
526813756   Jaegeuk Kim   f2fs: split sync_...
1425
1426
  			set_fsync_mark(page, 0);
  			set_dentry_mark(page, 0);
527465192   Jaegeuk Kim   f2fs: unlock_page...
1427
1428
1429
  
  			if (NODE_MAPPING(sbi)->a_ops->writepage(page, wbc))
  				unlock_page(page);
3f5f4959b   Chao Yu   f2fs: fix to comm...
1430
1431
  			else
  				nwritten++;
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: fix to comm...
1449
1450
1451
1452
  out:
  	if (nwritten)
  		f2fs_submit_merged_bio(sbi, NODE, WRITE);
  	return ret;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1453
  }
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1454
1455
  int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino)
  {
80dd9c0e9   Chao Yu   f2fs: fix incorre...
1456
  	pgoff_t index = 0, end = ULONG_MAX;
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1457
  	struct pagevec pvec;
280db3c88   Miklos Szeredi   f2fs: use filemap...
1458
  	int ret2, ret = 0;
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1459
1460
  
  	pagevec_init(&pvec, 0);
4ef51a8fc   Jaegeuk Kim   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   Jaegeuk Kim   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   Chao Yu   f2fs: add unlikel...
1474
  			if (unlikely(page->index > end))
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1475
  				continue;
4bf08ff6f   Chao Yu   f2fs: remove unne...
1476
  			if (ino && ino_of_node(page) == ino) {
fec1d6576   Jaegeuk Kim   f2fs: use wait_fo...
1477
  				f2fs_wait_on_page_writeback(page, NODE, true);
4bf08ff6f   Chao Yu   f2fs: remove unne...
1478
1479
1480
  				if (TestClearPageError(page))
  					ret = -EIO;
  			}
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1481
1482
1483
1484
  		}
  		pagevec_release(&pvec);
  		cond_resched();
  	}
280db3c88   Miklos Szeredi   f2fs: use filemap...
1485
  	ret2 = filemap_check_errors(NODE_MAPPING(sbi));
cfe58f9dc   Jaegeuk Kim   f2fs: avoid to wa...
1486
1487
1488
1489
  	if (!ret)
  		ret = ret2;
  	return ret;
  }
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1490
1491
1492
  static int f2fs_write_node_page(struct page *page,
  				struct writeback_control *wbc)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1493
  	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1494
  	nid_t nid;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1495
  	struct node_info ni;
fb5566da9   Jaegeuk Kim   f2fs: improve wri...
1496
  	struct f2fs_io_info fio = {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1497
  		.sbi = sbi,
fb5566da9   Jaegeuk Kim   f2fs: improve wri...
1498
  		.type = NODE,
04d328def   Mike Christie   f2fs: use bio op ...
1499
1500
  		.op = REQ_OP_WRITE,
  		.op_flags = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : 0,
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1501
  		.page = page,
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
1502
  		.encrypted_page = NULL,
fb5566da9   Jaegeuk Kim   f2fs: improve wri...
1503
  	};
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1504

ecda0de34   Chao Yu   f2fs: add a trace...
1505
  	trace_f2fs_writepage(page, NODE);
caf0047e7   Chao Yu   f2fs: merge flags...
1506
  	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
87a9bd265   Jaegeuk Kim   f2fs: avoid to wr...
1507
  		goto redirty_out;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1508
1509
  	if (unlikely(f2fs_cp_error(sbi)))
  		goto redirty_out;
87a9bd265   Jaegeuk Kim   f2fs: avoid to wr...
1510

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1511
1512
  	/* get old block addr of this node page */
  	nid = nid_of_node(page);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1513
  	f2fs_bug_on(sbi, page->index != nid);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1514

25b93346a   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
1521
1522
1523
  	get_node_info(sbi, nid, &ni);
  
  	/* This page is already truncated */
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
1524
  	if (unlikely(ni.blk_addr == NULL_ADDR)) {
2bca1e238   Jaegeuk Kim   f2fs: clear page'...
1525
  		ClearPageUptodate(page);
399368372   Jaegeuk Kim   f2fs: introduce a...
1526
  		dec_page_count(sbi, F2FS_DIRTY_NODES);
25b93346a   Jaegeuk Kim   f2fs: cover numbe...
1527
  		up_read(&sbi->node_write);
399368372   Jaegeuk Kim   f2fs: introduce a...
1528
1529
1530
  		unlock_page(page);
  		return 0;
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1531
1532
  
  	set_page_writeback(page);
7a9d75481   Chao Yu   f2fs: trace old b...
1533
  	fio.old_blkaddr = ni.blk_addr;
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
1534
  	write_node_page(nid, &fio);
7a9d75481   Chao Yu   f2fs: trace old b...
1535
  	set_node_addr(sbi, &ni, fio.new_blkaddr, is_fsync_dnode(page));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1536
  	dec_page_count(sbi, F2FS_DIRTY_NODES);
b3582c689   Chao Yu   f2fs: reduce comp...
1537
  	up_read(&sbi->node_write);
0c3a57975   Chao Yu   f2fs: introduce f...
1538
1539
1540
  
  	if (wbc->for_reclaim)
  		f2fs_submit_merged_bio_cond(sbi, NULL, page, 0, NODE, WRITE);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1541
  	unlock_page(page);
27c6bd60a   Jaegeuk Kim   f2fs: submit bio ...
1542

0c3a57975   Chao Yu   f2fs: introduce f...
1543
  	if (unlikely(f2fs_cp_error(sbi)))
27c6bd60a   Jaegeuk Kim   f2fs: submit bio ...
1544
  		f2fs_submit_merged_bio(sbi, NODE, WRITE);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1545
  	return 0;
87a9bd265   Jaegeuk Kim   f2fs: avoid to wr...
1546
1547
  
  redirty_out:
76f60268e   Jaegeuk Kim   f2fs: call redirt...
1548
  	redirty_page_for_writepage(wbc, page);
87a9bd265   Jaegeuk Kim   f2fs: avoid to wr...
1549
  	return AOP_WRITEPAGE_ACTIVATE;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1550
1551
1552
1553
1554
  }
  
  static int f2fs_write_node_pages(struct address_space *mapping,
  			    struct writeback_control *wbc)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1555
  	struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
1556
  	struct blk_plug plug;
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
1557
  	long diff;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1558

4660f9c0f   Jaegeuk Kim   f2fs: introduce f...
1559
1560
  	/* balancing f2fs's metadata in background */
  	f2fs_balance_fs_bg(sbi);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1561

a7fdffbd3   Jaegeuk Kim   f2fs: avoid issui...
1562
  	/* collect a number of dirty node pages and write together */
87d6f8909   Jaegeuk Kim   f2fs: avoid small...
1563
  	if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE))
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
1564
  		goto skip_write;
a7fdffbd3   Jaegeuk Kim   f2fs: avoid issui...
1565

d31c7c3f0   Yunlei He   f2fs: fix missing...
1566
  	trace_f2fs_writepages(mapping->host, wbc, NODE);
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
1567
  	diff = nr_pages_to_write(sbi, NODE, wbc);
fb5566da9   Jaegeuk Kim   f2fs: improve wri...
1568
  	wbc->sync_mode = WB_SYNC_NONE;
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
1569
  	blk_start_plug(&plug);
526813756   Jaegeuk Kim   f2fs: split sync_...
1570
  	sync_node_pages(sbi, wbc);
9dfa1baff   Jaegeuk Kim   f2fs: use blk_plu...
1571
  	blk_finish_plug(&plug);
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
1572
  	wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1573
  	return 0;
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
1574
1575
1576
  
  skip_write:
  	wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES);
d31c7c3f0   Yunlei He   f2fs: fix missing...
1577
  	trace_f2fs_writepages(mapping->host, wbc, NODE);
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
1578
  	return 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1579
1580
1581
1582
  }
  
  static int f2fs_set_node_page_dirty(struct page *page)
  {
26c6b8879   Jaegeuk Kim   f2fs: add tracepo...
1583
  	trace_f2fs_set_page_dirty(page, NODE);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
1584
1585
  	if (!PageUptodate(page))
  		SetPageUptodate(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1586
  	if (!PageDirty(page)) {
fe76b796f   Jaegeuk Kim   f2fs: introduce f...
1587
  		f2fs_set_page_dirty_nobuffers(page);
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1588
  		inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_NODES);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1589
  		SetPagePrivate(page);
9e4ded3f3   Jaegeuk Kim   f2fs: activate f2...
1590
  		f2fs_trace_pid(page);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1591
1592
1593
1594
  		return 1;
  	}
  	return 0;
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1595
  /*
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: merge {inva...
1602
1603
  	.invalidatepage	= f2fs_invalidate_page,
  	.releasepage	= f2fs_release_page,
5b7a487cf   Weichao Guo   f2fs: add customi...
1604
1605
1606
  #ifdef CONFIG_MIGRATION
  	.migratepage    = f2fs_migrate_page,
  #endif
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1607
  };
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1608
1609
  static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i,
  						nid_t n)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1610
  {
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1611
  	return radix_tree_lookup(&nm_i->free_nid_root, n);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1612
  }
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1613
1614
  static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i,
  						struct free_nid *i)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1615
1616
  {
  	list_del(&i->list);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1617
  	radix_tree_delete(&nm_i->free_nid_root, i->nid);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1618
  }
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1619
  static int add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1620
  {
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1621
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1622
  	struct free_nid *i;
59bbd474a   Jaegeuk Kim   f2fs: cover free_...
1623
  	struct nat_entry *ne;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1624

6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1625
  	if (!available_free_memory(sbi, FREE_NIDS))
23d388442   Haicheng Li   f2fs: optimize sc...
1626
  		return -1;
9198aceb5   Jaegeuk Kim   f2fs: check nid =...
1627
1628
  
  	/* 0 nid should not be used */
cfb271d48   Chao Yu   f2fs: add unlikel...
1629
  	if (unlikely(nid == 0))
9198aceb5   Jaegeuk Kim   f2fs: check nid =...
1630
  		return 0;
59bbd474a   Jaegeuk Kim   f2fs: cover free_...
1631

7bd59381c   Gu Zheng   f2fs: introduce f...
1632
1633
  	if (build) {
  		/* do not add allocated nids */
7bd59381c   Gu Zheng   f2fs: introduce f...
1634
  		ne = __lookup_nat_cache(nm_i, nid);
a51311938   Jaegeuk Kim   f2fs: cover more ...
1635
  		if (ne && (!get_nat_flag(ne, IS_CHECKPOINTED) ||
7ef35e3b9   Jaegeuk Kim   f2fs: introduce a...
1636
  				nat_get_blkaddr(ne) != NULL_ADDR))
7bd59381c   Gu Zheng   f2fs: introduce f...
1637
  			return 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1638
  	}
7bd59381c   Gu Zheng   f2fs: introduce f...
1639
1640
  
  	i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1641
1642
  	i->nid = nid;
  	i->state = NID_NEW;
769ec6e5b   Jaegeuk Kim   f2fs: call radix_...
1643
1644
1645
1646
  	if (radix_tree_preload(GFP_NOFS)) {
  		kmem_cache_free(free_nid_slab, i);
  		return 0;
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1647
  	spin_lock(&nm_i->free_nid_list_lock);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1648
  	if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1649
  		spin_unlock(&nm_i->free_nid_list_lock);
769ec6e5b   Jaegeuk Kim   f2fs: call radix_...
1650
  		radix_tree_preload_end();
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: call radix_...
1657
  	radix_tree_preload_end();
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: avoid free ...
1664
  	bool need_free = false;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1665
  	spin_lock(&nm_i->free_nid_list_lock);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1666
  	i = __lookup_free_nid_list(nm_i, nid);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1667
  	if (i && i->state == NID_NEW) {
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1668
  		__del_from_free_nid_list(nm_i, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1669
  		nm_i->fcnt--;
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1670
  		need_free = true;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1671
1672
  	}
  	spin_unlock(&nm_i->free_nid_list_lock);
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1673
1674
1675
  
  	if (need_free)
  		kmem_cache_free(free_nid_slab, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1676
  }
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1677
  static void scan_nat_page(struct f2fs_sb_info *sbi,
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1678
1679
  			struct page *nat_page, nid_t start_nid)
  {
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1680
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1681
1682
  	struct f2fs_nat_block *nat_blk = page_address(nat_page);
  	block_t blk_addr;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1683
  	int i;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1684
1685
1686
  	i = start_nid % NAT_ENTRY_PER_BLOCK;
  
  	for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) {
23d388442   Haicheng Li   f2fs: optimize sc...
1687

cfb271d48   Chao Yu   f2fs: add unlikel...
1688
  		if (unlikely(start_nid >= nm_i->max_nid))
04431c44e   Jaegeuk Kim   f2fs: fix not to ...
1689
  			break;
23d388442   Haicheng Li   f2fs: optimize sc...
1690
1691
  
  		blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1692
  		f2fs_bug_on(sbi, blk_addr == NEW_ADDR);
23d388442   Haicheng Li   f2fs: optimize sc...
1693
  		if (blk_addr == NULL_ADDR) {
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1694
  			if (add_free_nid(sbi, start_nid, true) < 0)
23d388442   Haicheng Li   f2fs: optimize sc...
1695
1696
  				break;
  		}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1697
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1698
  }
ad4edb831   Jaegeuk Kim   f2fs: produce mor...
1699
  void build_free_nids(struct f2fs_sb_info *sbi)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1700
  {
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: split journ...
1703
  	struct f2fs_journal *journal = curseg->journal;
8760952d9   Haicheng Li   f2fs: code cleanu...
1704
  	int i = 0;
55008d845   Jaegeuk Kim   f2fs: enhance all...
1705
  	nid_t nid = nm_i->next_scan_nid;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1706

55008d845   Jaegeuk Kim   f2fs: enhance all...
1707
  	/* Enough entries */
ad4edb831   Jaegeuk Kim   f2fs: produce mor...
1708
  	if (nm_i->fcnt >= NAT_ENTRY_PER_BLOCK)
55008d845   Jaegeuk Kim   f2fs: enhance all...
1709
  		return;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1710

55008d845   Jaegeuk Kim   f2fs: enhance all...
1711
  	/* readahead nat pages to be scanned */
26879fb10   Chao Yu   f2fs: support low...
1712
1713
  	ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES,
  							META_NAT, true);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1714

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
1715
  	down_read(&nm_i->nat_tree_lock);
a51311938   Jaegeuk Kim   f2fs: cover more ...
1716

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1717
1718
  	while (1) {
  		struct page *page = get_current_nat_page(sbi, nid);
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1719
  		scan_nat_page(sbi, page, nid);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1720
1721
1722
  		f2fs_put_page(page, 1);
  
  		nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK));
cfb271d48   Chao Yu   f2fs: add unlikel...
1723
  		if (unlikely(nid >= nm_i->max_nid))
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1724
  			nid = 0;
55008d845   Jaegeuk Kim   f2fs: enhance all...
1725

a6d494b6d   Chao Yu   f2fs: fix to buil...
1726
  		if (++i >= FREE_NID_PAGES)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1727
1728
  			break;
  	}
55008d845   Jaegeuk Kim   f2fs: enhance all...
1729
1730
  	/* go to the next free nat pages to find free nids abundantly */
  	nm_i->next_scan_nid = nid;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1731
1732
  
  	/* find free nids from current sum_pages */
b7ad7512b   Chao Yu   f2fs: split journ...
1733
  	down_read(&curseg->journal_rwsem);
dfc08a12e   Chao Yu   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   Jaegeuk Kim   f2fs: add node op...
1739
  		if (addr == NULL_ADDR)
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1740
  			add_free_nid(sbi, nid, true);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1741
1742
1743
  		else
  			remove_free_nid(nm_i, nid);
  	}
b7ad7512b   Chao Yu   f2fs: split journ...
1744
  	up_read(&curseg->journal_rwsem);
b873b798a   Jaegeuk Kim   Revert "f2fs: use...
1745
  	up_read(&nm_i->nat_tree_lock);
2db2388fc   Chao Yu   f2fs: readahead f...
1746
1747
  
  	ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nm_i->next_scan_nid),
ea1a29a0b   Chao Yu   f2fs: export ra_n...
1748
  					nm_i->ra_nid_pages, META_NAT, false);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
1760
  retry:
cb78942b8   Jaegeuk Kim   f2fs: inject ENOS...
1761
  #ifdef CONFIG_F2FS_FAULT_INJECTION
1ecc0c5c5   Chao Yu   f2fs: support con...
1762
  	if (time_to_inject(sbi, FAULT_ALLOC_NID))
cb78942b8   Jaegeuk Kim   f2fs: inject ENOS...
1763
1764
  		return false;
  #endif
7ee0eeabc   Jaegeuk Kim   f2fs: add availab...
1765
  	if (unlikely(sbi->total_valid_node_count + 1 > nm_i->available_nids))
55008d845   Jaegeuk Kim   f2fs: enhance all...
1766
  		return false;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1767

e05df3b11   Jaegeuk Kim   f2fs: add node op...
1768
  	spin_lock(&nm_i->free_nid_list_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1769

55008d845   Jaegeuk Kim   f2fs: enhance all...
1770
  	/* We should not use stale free nids created by build_free_nids */
f978f5a06   Gu Zheng   f2fs: introduce h...
1771
  	if (nm_i->fcnt && !on_build_free_nids(nm_i)) {
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1772
  		f2fs_bug_on(sbi, list_empty(&nm_i->free_nid_list));
2d7b822ad   Chao Yu   f2fs: use list_fo...
1773
  		list_for_each_entry(i, &nm_i->free_nid_list, list)
55008d845   Jaegeuk Kim   f2fs: enhance all...
1774
1775
  			if (i->state == NID_NEW)
  				break;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1776

9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1777
  		f2fs_bug_on(sbi, i->state != NID_NEW);
55008d845   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
1784
  	spin_unlock(&nm_i->free_nid_list_lock);
55008d845   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: enhance all...
1788
  	build_free_nids(sbi);
55008d845   Jaegeuk Kim   f2fs: enhance all...
1789
1790
  	mutex_unlock(&nm_i->build_lock);
  	goto retry;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1791
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1792
  /*
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: introduce a...
1801
  	i = __lookup_free_nid_list(nm_i, nid);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1802
  	f2fs_bug_on(sbi, !i || i->state != NID_ALLOC);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1803
  	__del_from_free_nid_list(nm_i, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1804
  	spin_unlock(&nm_i->free_nid_list_lock);
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1805
1806
  
  	kmem_cache_free(free_nid_slab, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1807
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1808
  /*
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: reduce redu...
1813
1814
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
  	struct free_nid *i;
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1815
  	bool need_free = false;
49952fa18   Jaegeuk Kim   f2fs: reduce redu...
1816

65985d935   Jaegeuk Kim   f2fs: support the...
1817
1818
  	if (!nid)
  		return;
49952fa18   Jaegeuk Kim   f2fs: reduce redu...
1819
  	spin_lock(&nm_i->free_nid_list_lock);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1820
  	i = __lookup_free_nid_list(nm_i, nid);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1821
  	f2fs_bug_on(sbi, !i || i->state != NID_ALLOC);
6fb03f3a4   Jaegeuk Kim   f2fs: adjust free...
1822
  	if (!available_free_memory(sbi, FREE_NIDS)) {
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
1823
  		__del_from_free_nid_list(nm_i, i);
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1824
  		need_free = true;
95630cbad   Haicheng Li   f2fs: bugfix for ...
1825
1826
1827
1828
  	} else {
  		i->state = NID_NEW;
  		nm_i->fcnt++;
  	}
49952fa18   Jaegeuk Kim   f2fs: reduce redu...
1829
  	spin_unlock(&nm_i->free_nid_list_lock);
cf0ee0f09   Chao Yu   f2fs: avoid free ...
1830
1831
1832
  
  	if (need_free)
  		kmem_cache_free(free_nid_slab, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1833
  }
31696580b   Chao Yu   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   Jaegeuk Kim   f2fs: produce mor...
1839
1840
  	if (nm_i->fcnt <= MAX_FREE_NIDS)
  		return 0;
31696580b   Chao Yu   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   Jaegeuk Kim   f2fs: produce mor...
1846
  		if (nr_shrink <= 0 || nm_i->fcnt <= MAX_FREE_NIDS)
31696580b   Chao Yu   f2fs: shrink free...
1847
1848
1849
1850
  			break;
  		if (i->state == NID_ALLOC)
  			continue;
  		__del_from_free_nid_list(nm_i, i);
31696580b   Chao Yu   f2fs: shrink free...
1851
  		kmem_cache_free(free_nid_slab, i);
f7409d0fa   Jaegeuk Kim   f2fs: fix wrong p...
1852
  		nm_i->fcnt--;
31696580b   Chao Yu   f2fs: shrink free...
1853
  		nr_shrink--;
31696580b   Chao Yu   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   Chao Yu   f2fs: avoid skipp...
1860
  void recover_inline_xattr(struct inode *inode, struct page *page)
28cdce045   Chao Yu   f2fs: recover inl...
1861
  {
28cdce045   Chao Yu   f2fs: recover inl...
1862
1863
1864
1865
  	void *src_addr, *dst_addr;
  	size_t inline_size;
  	struct page *ipage;
  	struct f2fs_inode *ri;
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1866
  	ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino);
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1867
  	f2fs_bug_on(F2FS_I_SB(inode), IS_ERR(ipage));
28cdce045   Chao Yu   f2fs: recover inl...
1868

e3b4d43f7   Jaegeuk Kim   f2fs: should clea...
1869
1870
  	ri = F2FS_INODE(page);
  	if (!(ri->i_inline & F2FS_INLINE_XATTR)) {
91942321e   Jaegeuk Kim   f2fs: use inode p...
1871
  		clear_inode_flag(inode, FI_INLINE_XATTR);
e3b4d43f7   Jaegeuk Kim   f2fs: should clea...
1872
1873
  		goto update_inode;
  	}
28cdce045   Chao Yu   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   Jaegeuk Kim   f2fs: use wait_fo...
1877
  	f2fs_wait_on_page_writeback(ipage, NODE, true);
28cdce045   Chao Yu   f2fs: recover inl...
1878
  	memcpy(dst_addr, src_addr, inline_size);
e3b4d43f7   Jaegeuk Kim   f2fs: should clea...
1879
  update_inode:
28cdce045   Chao Yu   f2fs: recover inl...
1880
1881
1882
  	update_inode(inode, ipage);
  	f2fs_put_page(ipage, 1);
  }
1c35a90e8   Jaegeuk Kim   f2fs: fix to reco...
1883
  void recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
abb2366c8   Jaegeuk Kim   f2fs: fix to reco...
1884
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
1885
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
abb2366c8   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: need fsck.f...
1895
  	f2fs_bug_on(sbi, ni.blk_addr == NULL_ADDR);
abb2366c8   Jaegeuk Kim   f2fs: fix to reco...
1896
1897
  	invalidate_blocks(sbi, ni.blk_addr);
  	dec_valid_node_count(sbi, inode);
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
1898
  	set_node_addr(sbi, &ni, NULL_ADDR, false);
abb2366c8   Jaegeuk Kim   f2fs: fix to reco...
1899
1900
1901
1902
  
  recover_xnid:
  	/* 2: allocate new xattr nid */
  	if (unlikely(!inc_valid_node_count(sbi, inode)))
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
1903
  		f2fs_bug_on(sbi, 1);
abb2366c8   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: skip unnece...
1908
  	set_node_addr(sbi, &ni, NEW_ADDR, false);
205b98221   Jaegeuk Kim   f2fs: call mark_i...
1909
  	f2fs_i_xnid_write(inode, new_xnid);
abb2366c8   Jaegeuk Kim   f2fs: fix to reco...
1910
1911
1912
  
  	/* 3: update xattr blkaddr */
  	refresh_sit_entry(sbi, NEW_ADDR, blkaddr);
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
1913
  	set_node_addr(sbi, &ni, blkaddr, false);
abb2366c8   Jaegeuk Kim   f2fs: fix to reco...
1914
  }
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1915
1916
  int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
  {
58bfaf44d   Jaegeuk Kim   f2fs: introduce F...
1917
  	struct f2fs_inode *src, *dst;
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: avoid ENOME...
1925
  retry:
300e129c1   Jaegeuk Kim   f2fs: use f2fs_gr...
1926
  	ipage = f2fs_grab_cache_page(NODE_MAPPING(sbi), ino, false);
e8ea9b3d7   Jaegeuk Kim   f2fs: avoid ENOME...
1927
1928
1929
1930
  	if (!ipage) {
  		congestion_wait(BLK_RW_ASYNC, HZ/50);
  		goto retry;
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1931

e1c420452   arter97   f2fs: fix typo
1932
  	/* Should not use this inode from free nid list */
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1933
  	remove_free_nid(NM_I(sbi), ino);
237c0790e   Jaegeuk Kim   f2fs: call SetPag...
1934
1935
  	if (!PageUptodate(ipage))
  		SetPageUptodate(ipage);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1936
  	fill_node_footer(ipage, ino, ino, 0, true);
58bfaf44d   Jaegeuk Kim   f2fs: introduce F...
1937
1938
  	src = F2FS_INODE(page);
  	dst = F2FS_INODE(ipage);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1939

58bfaf44d   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: fix the ini...
1945
  	dst->i_inline = src->i_inline & F2FS_INLINE_XATTR;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1946
1947
1948
  
  	new_ni = old_ni;
  	new_ni.ino = ino;
cfb271d48   Chao Yu   f2fs: add unlikel...
1949
  	if (unlikely(!inc_valid_node_count(sbi, NULL)))
65e5cd0a1   Jaegeuk Kim   f2fs: fix inconsi...
1950
  		WARN_ON(1);
479f40c44   Jaegeuk Kim   f2fs: skip unnece...
1951
  	set_node_addr(sbi, &new_ni, NEW_ADDR, false);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1952
  	inc_valid_inode_count(sbi);
617deb8c0   Jaegeuk Kim   f2fs: fix the ini...
1953
  	set_page_dirty(ipage);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
1963
  	block_t addr;
90a893c74   Jaegeuk Kim   f2fs: use MAX_BIO...
1964
  	int bio_blocks = MAX_BIO_BLOCKS(sbi);
9ecf4b80b   Chao Yu   f2fs: use ra_meta...
1965
  	int i, idx, last_offset, nrpages;
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: use ra_meta...
1971
  	for (i = 0; i < last_offset; i += nrpages, addr += nrpages) {
9af0ff1c5   Chao Yu   f2fs: readahead c...
1972
  		nrpages = min(last_offset - i, bio_blocks);
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
1973

e1c420452   arter97   f2fs: fix typo
1974
  		/* readahead node pages */
26879fb10   Chao Yu   f2fs: support low...
1975
  		ra_meta_pages(sbi, addr, nrpages, META_POR, true);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1976

9ecf4b80b   Chao Yu   f2fs: use ra_meta...
1977
  		for (idx = addr; idx < addr + nrpages; idx++) {
2b947003f   Chao Yu   f2fs: don't tag R...
1978
  			struct page *page = get_tmp_page(sbi, idx);
9af0ff1c5   Chao Yu   f2fs: readahead c...
1979

9ecf4b80b   Chao Yu   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   Chao Yu   f2fs: readahead c...
1986
  		}
bac4eef65   Chao Yu   f2fs: avoid crash...
1987

9ecf4b80b   Chao Yu   f2fs: use ra_meta...
1988
  		invalidate_mapping_pages(META_MAPPING(sbi), addr,
bac4eef65   Chao Yu   f2fs: avoid crash...
1989
  							addr + nrpages);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1990
  	}
9ecf4b80b   Chao Yu   f2fs: use ra_meta...
1991
  	return 0;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1992
  }
aec71382c   Chao Yu   f2fs: refactor fl...
1993
  static void remove_nats_in_journal(struct f2fs_sb_info *sbi)
e05df3b11   Jaegeuk Kim   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   Chao Yu   f2fs: split journ...
1997
  	struct f2fs_journal *journal = curseg->journal;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
1998
  	int i;
b7ad7512b   Chao Yu   f2fs: split journ...
1999
  	down_write(&curseg->journal_rwsem);
dfc08a12e   Chao Yu   f2fs: introduce f...
2000
  	for (i = 0; i < nats_in_cursum(journal); i++) {
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2001
2002
  		struct nat_entry *ne;
  		struct f2fs_nat_entry raw_ne;
dfc08a12e   Chao Yu   f2fs: introduce f...
2003
  		nid_t nid = le32_to_cpu(nid_in_journal(journal, i));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2004

dfc08a12e   Chao Yu   f2fs: introduce f...
2005
  		raw_ne = nat_in_journal(journal, i);
9be32d72b   Jaegeuk Kim   f2fs: do retry op...
2006

e05df3b11   Jaegeuk Kim   f2fs: add node op...
2007
  		ne = __lookup_nat_cache(nm_i, nid);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2008
  		if (!ne) {
9be32d72b   Jaegeuk Kim   f2fs: do retry op...
2009
2010
  			ne = grab_nat_entry(nm_i, nid);
  			node_info_from_raw_nat(&ne->ni, &raw_ne);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2011
  		}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2012
  		__set_nat_cache_dirty(nm_i, ne);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2013
  	}
dfc08a12e   Chao Yu   f2fs: introduce f...
2014
  	update_nats_in_cursum(journal, -i);
b7ad7512b   Chao Yu   f2fs: split journ...
2015
  	up_write(&curseg->journal_rwsem);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2016
  }
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2017
2018
  static void __adjust_nat_entry_set(struct nat_entry_set *nes,
  						struct list_head *head, int max)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2019
  {
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2020
  	struct nat_entry_set *cur;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2021

309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2022
2023
  	if (nes->entry_cnt >= max)
  		goto add_out;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2024

309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: refactor fl...
2030
  	}
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2031
2032
2033
  add_out:
  	list_add_tail(&nes->set_list, head);
  }
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2034

309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: split journ...
2039
  	struct f2fs_journal *journal = curseg->journal;
309cc2b6e   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
2045

aec71382c   Chao Yu   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   Chao Yu   f2fs: introduce f...
2051
  	if (!__has_cursum_space(journal, set->entry_cnt, NAT_JOURNAL))
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2052
2053
2054
  		to_journal = false;
  
  	if (to_journal) {
b7ad7512b   Chao Yu   f2fs: split journ...
2055
  		down_write(&curseg->journal_rwsem);
309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: refactor fl...
2061

309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: refactor fl...
2070
2071
  
  		if (to_journal) {
dfc08a12e   Chao Yu   f2fs: introduce f...
2072
  			offset = lookup_journal_in_cursum(journal,
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2073
2074
  							NAT_JOURNAL, nid, 1);
  			f2fs_bug_on(sbi, offset < 0);
dfc08a12e   Chao Yu   f2fs: introduce f...
2075
2076
  			raw_ne = &nat_in_journal(journal, offset);
  			nid_in_journal(journal, offset) = cpu_to_le32(nid);
aec71382c   Chao Yu   f2fs: refactor fl...
2077
  		} else {
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2078
  			raw_ne = &nat_blk->entries[nid - start_nid];
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2079
  		}
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2080
  		raw_nat_from_node_info(raw_ne, &ne->ni);
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2081
2082
  		nat_reset_flag(ne);
  		__clear_nat_cache_dirty(NM_I(sbi), ne);
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2083
2084
2085
  		if (nat_get_blkaddr(ne) == NULL_ADDR)
  			add_free_nid(sbi, nid, false);
  	}
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2086

309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2087
  	if (to_journal)
b7ad7512b   Chao Yu   f2fs: split journ...
2088
  		up_write(&curseg->journal_rwsem);
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2089
2090
  	else
  		f2fs_put_page(page, 1);
aec71382c   Chao Yu   f2fs: refactor fl...
2091

80ec2e914   Changman Lee   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   Jaegeuk Kim   f2fs: refactor fl...
2096
  }
aec71382c   Chao Yu   f2fs: refactor fl...
2097

309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: split journ...
2105
  	struct f2fs_journal *journal = curseg->journal;
7aed0d453   Jaegeuk Kim   f2fs: free radix_...
2106
  	struct nat_entry_set *setvec[SETVEC_SIZE];
309cc2b6e   Jaegeuk Kim   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   Changman Lee   f2fs: check dirty...
2111
2112
  	if (!nm_i->dirty_nat_cnt)
  		return;
a51311938   Jaegeuk Kim   f2fs: cover more ...
2113

b873b798a   Jaegeuk Kim   Revert "f2fs: use...
2114
  	down_write(&nm_i->nat_tree_lock);
a51311938   Jaegeuk Kim   f2fs: cover more ...
2115

309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: introduce f...
2121
  	if (!__has_cursum_space(journal, nm_i->dirty_nat_cnt, NAT_JOURNAL))
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2122
  		remove_nats_in_journal(sbi);
309cc2b6e   Jaegeuk Kim   f2fs: refactor fl...
2123
  	while ((found = __gang_lookup_nat_set(nm_i,
7aed0d453   Jaegeuk Kim   f2fs: free radix_...
2124
  					set_idx, SETVEC_SIZE, setvec))) {
309cc2b6e   Jaegeuk Kim   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   Chao Yu   f2fs: introduce f...
2129
  						MAX_NAT_JENTRIES(journal));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2130
  	}
aec71382c   Chao Yu   f2fs: refactor fl...
2131

309cc2b6e   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
2135
  	up_write(&nm_i->nat_tree_lock);
a51311938   Jaegeuk Kim   f2fs: cover more ...
2136

9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
2137
  	f2fs_bug_on(sbi, nm_i->dirty_nat_cnt);
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: fix the cal...
2152

7ee0eeabc   Jaegeuk Kim   f2fs: add availab...
2153
  	nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks;
b63da15e8   Jaegeuk Kim   f2fs: fix the cal...
2154
  	/* not used nids: 0, node, meta, (and root counted as valid node) */
c200b1aa6   Chao Yu   f2fs: fix incorre...
2155
  	nm_i->available_nids = nm_i->max_nid - F2FS_RESERVED_NODE_NUM;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2156
2157
  	nm_i->fcnt = 0;
  	nm_i->nat_cnt = 0;
cdfc41c13   Jaegeuk Kim   f2fs: throttle th...
2158
  	nm_i->ram_thresh = DEF_RAM_THRESHOLD;
ea1a29a0b   Chao Yu   f2fs: export ra_n...
2159
  	nm_i->ra_nid_pages = DEF_RA_NID_PAGES;
2304cb0c4   Chao Yu   f2fs: export dirt...
2160
  	nm_i->dirty_nats_ratio = DEF_DIRTY_NAT_RATIO_THRESHOLD;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2161

8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
2162
  	INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2163
  	INIT_LIST_HEAD(&nm_i->free_nid_list);
769ec6e5b   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: add node op...
2166
  	INIT_LIST_HEAD(&nm_i->nat_entries);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2167
2168
2169
  
  	mutex_init(&nm_i->build_lock);
  	spin_lock_init(&nm_i->free_nid_list_lock);
b873b798a   Jaegeuk Kim   Revert "f2fs: use...
2170
  	init_rwsem(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2171

e05df3b11   Jaegeuk Kim   f2fs: add node op...
2172
  	nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid);
79b5793be   Alexandru Gheorghiu   f2fs: use kmemdup
2173
  	nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2174
2175
2176
  	version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP);
  	if (!version_bitmap)
  		return -EFAULT;
79b5793be   Alexandru Gheorghiu   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   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: free radix_...
2205
  	struct nat_entry_set *setvec[SETVEC_SIZE];
e05df3b11   Jaegeuk Kim   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   Jaegeuk Kim   f2fs: need fsck.f...
2215
  		f2fs_bug_on(sbi, i->state == NID_ALLOC);
8a7ed66aa   Jaegeuk Kim   f2fs: introduce a...
2216
  		__del_from_free_nid_list(nm_i, i);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2217
  		nm_i->fcnt--;
cf0ee0f09   Chao Yu   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   Jaegeuk Kim   f2fs: add node op...
2221
  	}
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
2222
  	f2fs_bug_on(sbi, nm_i->fcnt);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2223
2224
2225
  	spin_unlock(&nm_i->free_nid_list_lock);
  
  	/* destroy nat cache */
b873b798a   Jaegeuk Kim   Revert "f2fs: use...
2226
  	down_write(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2227
2228
2229
  	while ((found = __gang_lookup_nat_cache(nm_i,
  					nid, NATVEC_SIZE, natvec))) {
  		unsigned idx;
7aed0d453   Jaegeuk Kim   f2fs: free radix_...
2230

b6ce391e6   Gu Zheng   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   Jaegeuk Kim   f2fs: add node op...
2234
  	}
9850cf4a8   Jaegeuk Kim   f2fs: need fsck.f...
2235
  	f2fs_bug_on(sbi, nm_i->nat_cnt);
7aed0d453   Jaegeuk Kim   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   Jaegeuk Kim   Revert "f2fs: use...
2251
  	up_write(&nm_i->nat_tree_lock);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2252
2253
2254
2255
2256
  
  	kfree(nm_i->nat_bitmap);
  	sbi->nm_info = NULL;
  	kfree(nm_i);
  }
6e6093a8f   Namjae Jeon   f2fs: add __init ...
2257
  int __init create_node_manager_caches(void)
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2258
2259
  {
  	nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
e8512d2e0   Gu Zheng   f2fs: remove the ...
2260
  			sizeof(struct nat_entry));
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2261
  	if (!nat_entry_slab)
aec71382c   Chao Yu   f2fs: refactor fl...
2262
  		goto fail;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2263
2264
  
  	free_nid_slab = f2fs_kmem_cache_create("free_nid",
e8512d2e0   Gu Zheng   f2fs: remove the ...
2265
  			sizeof(struct free_nid));
aec71382c   Chao Yu   f2fs: refactor fl...
2266
  	if (!free_nid_slab)
ce3e6d25f   Markus Elfring   f2fs: fix typos f...
2267
  		goto destroy_nat_entry;
aec71382c   Chao Yu   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   Markus Elfring   f2fs: fix typos f...
2272
  		goto destroy_free_nid;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2273
  	return 0;
aec71382c   Chao Yu   f2fs: refactor fl...
2274

ce3e6d25f   Markus Elfring   f2fs: fix typos f...
2275
  destroy_free_nid:
aec71382c   Chao Yu   f2fs: refactor fl...
2276
  	kmem_cache_destroy(free_nid_slab);
ce3e6d25f   Markus Elfring   f2fs: fix typos f...
2277
  destroy_nat_entry:
aec71382c   Chao Yu   f2fs: refactor fl...
2278
2279
2280
  	kmem_cache_destroy(nat_entry_slab);
  fail:
  	return -ENOMEM;
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2281
2282
2283
2284
  }
  
  void destroy_node_manager_caches(void)
  {
aec71382c   Chao Yu   f2fs: refactor fl...
2285
  	kmem_cache_destroy(nat_entry_set_slab);
e05df3b11   Jaegeuk Kim   f2fs: add node op...
2286
2287
2288
  	kmem_cache_destroy(free_nid_slab);
  	kmem_cache_destroy(nat_entry_slab);
  }