Blame view

fs/f2fs/checkpoint.c 28.9 KB
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1
  /*
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
   * fs/f2fs/checkpoint.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/bio.h>
  #include <linux/mpage.h>
  #include <linux/writeback.h>
  #include <linux/blkdev.h>
  #include <linux/f2fs_fs.h>
  #include <linux/pagevec.h>
  #include <linux/swap.h>
  
  #include "f2fs.h"
  #include "node.h"
  #include "segment.h"
9e4ded3f3   Jaegeuk Kim   f2fs: activate f2...
23
  #include "trace.h"
2af4bd6ca   Namjae Jeon   f2fs: add tracepo...
24
  #include <trace/events/f2fs.h>
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
25

6451e041c   Jaegeuk Kim   f2fs: add infra f...
26
  static struct kmem_cache *ino_entry_slab;
062920734   Chao Yu   f2fs: reuse inode...
27
  struct kmem_cache *inode_entry_slab;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
28

0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
29
  /*
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
30
31
32
33
   * We guarantee no failure on the returned page.
   */
  struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
  {
9df27d982   Gu Zheng   f2fs: add help fu...
34
  	struct address_space *mapping = META_MAPPING(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
35
36
  	struct page *page = NULL;
  repeat:
bde446866   Jaegeuk Kim   f2fs: no need to ...
37
  	page = grab_cache_page(mapping, index);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
38
39
40
41
  	if (!page) {
  		cond_resched();
  		goto repeat;
  	}
bde446866   Jaegeuk Kim   f2fs: no need to ...
42
  	f2fs_wait_on_page_writeback(page, META);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
43
44
45
  	SetPageUptodate(page);
  	return page;
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
46
  /*
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
47
48
   * We guarantee no failure on the returned page.
   */
2b947003f   Chao Yu   f2fs: don't tag R...
49
50
  static struct page *__get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index,
  							bool is_meta)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
51
  {
9df27d982   Gu Zheng   f2fs: add help fu...
52
  	struct address_space *mapping = META_MAPPING(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
53
  	struct page *page;
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
54
  	struct f2fs_io_info fio = {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
55
  		.sbi = sbi,
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
56
57
58
  		.type = META,
  		.rw = READ_SYNC | REQ_META | REQ_PRIO,
  		.blk_addr = index,
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
59
  		.encrypted_page = NULL,
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
60
  	};
2b947003f   Chao Yu   f2fs: don't tag R...
61
62
63
  
  	if (unlikely(!is_meta))
  		fio.rw &= ~REQ_META;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
64
65
66
67
68
69
  repeat:
  	page = grab_cache_page(mapping, index);
  	if (!page) {
  		cond_resched();
  		goto repeat;
  	}
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
70
71
  	if (PageUptodate(page))
  		goto out;
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
72
  	fio.page = page;
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
73
74
  	if (f2fs_submit_page_bio(&fio)) {
  		f2fs_put_page(page, 1);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
75
  		goto repeat;
86531d6b8   Jaegeuk Kim   f2fs: callers tak...
76
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
77

393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
78
  	lock_page(page);
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
79
  	if (unlikely(page->mapping != mapping)) {
afcb7ca01   Jaegeuk Kim   f2fs: check trunc...
80
81
82
  		f2fs_put_page(page, 1);
  		goto repeat;
  	}
f3f338caa   Chao Yu   f2fs: freeze file...
83
84
85
86
87
88
89
90
  
  	/*
  	 * if there is any IO error when accessing device, make our filesystem
  	 * readonly and make sure do not write checkpoint with non-uptodate
  	 * meta page.
  	 */
  	if (unlikely(!PageUptodate(page)))
  		f2fs_stop_checkpoint(sbi);
393ff91f5   Jaegeuk Kim   f2fs: reduce unnc...
91
  out:
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
92
93
  	return page;
  }
2b947003f   Chao Yu   f2fs: don't tag R...
94
95
96
97
98
99
100
101
102
103
  struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index)
  {
  	return __get_meta_page(sbi, index, true);
  }
  
  /* for POR only */
  struct page *get_tmp_page(struct f2fs_sb_info *sbi, pgoff_t index)
  {
  	return __get_meta_page(sbi, index, false);
  }
f0c9cadae   Chao Yu   f2fs: use is_vali...
104
  bool is_valid_blkaddr(struct f2fs_sb_info *sbi, block_t blkaddr, int type)
662befda2   Chao Yu   f2fs: introduce r...
105
106
107
  {
  	switch (type) {
  	case META_NAT:
66b00c186   Chao Yu   f2fs: introduce i...
108
  		break;
662befda2   Chao Yu   f2fs: introduce r...
109
  	case META_SIT:
66b00c186   Chao Yu   f2fs: introduce i...
110
111
112
  		if (unlikely(blkaddr >= SIT_BLK_CNT(sbi)))
  			return false;
  		break;
81c1a0f13   Chao Yu   f2fs: readahead c...
113
  	case META_SSA:
66b00c186   Chao Yu   f2fs: introduce i...
114
115
116
117
  		if (unlikely(blkaddr >= MAIN_BLKADDR(sbi) ||
  			blkaddr < SM_I(sbi)->ssa_blkaddr))
  			return false;
  		break;
662befda2   Chao Yu   f2fs: introduce r...
118
  	case META_CP:
66b00c186   Chao Yu   f2fs: introduce i...
119
120
121
122
  		if (unlikely(blkaddr >= SIT_I(sbi)->sit_base_addr ||
  			blkaddr < __start_cp_addr(sbi)))
  			return false;
  		break;
4c521f493   Jaegeuk Kim   f2fs: use meta_in...
123
  	case META_POR:
66b00c186   Chao Yu   f2fs: introduce i...
124
125
126
127
  		if (unlikely(blkaddr >= MAX_BLKADDR(sbi) ||
  			blkaddr < MAIN_BLKADDR(sbi)))
  			return false;
  		break;
662befda2   Chao Yu   f2fs: introduce r...
128
129
130
  	default:
  		BUG();
  	}
66b00c186   Chao Yu   f2fs: introduce i...
131
132
  
  	return true;
662befda2   Chao Yu   f2fs: introduce r...
133
134
135
  }
  
  /*
81c1a0f13   Chao Yu   f2fs: readahead c...
136
   * Readahead CP/NAT/SIT/SSA pages
662befda2   Chao Yu   f2fs: introduce r...
137
   */
26879fb10   Chao Yu   f2fs: support low...
138
139
  int ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages,
  							int type, bool sync)
662befda2   Chao Yu   f2fs: introduce r...
140
141
142
  {
  	block_t prev_blk_addr = 0;
  	struct page *page;
4c521f493   Jaegeuk Kim   f2fs: use meta_in...
143
  	block_t blkno = start;
662befda2   Chao Yu   f2fs: introduce r...
144
  	struct f2fs_io_info fio = {
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
145
  		.sbi = sbi,
662befda2   Chao Yu   f2fs: introduce r...
146
  		.type = META,
26879fb10   Chao Yu   f2fs: support low...
147
  		.rw = sync ? (READ_SYNC | REQ_META | REQ_PRIO) : READA,
4375a3366   Jaegeuk Kim   f2fs crypto: add ...
148
  		.encrypted_page = NULL,
662befda2   Chao Yu   f2fs: introduce r...
149
  	};
2b947003f   Chao Yu   f2fs: don't tag R...
150
151
  	if (unlikely(type == META_POR))
  		fio.rw &= ~REQ_META;
662befda2   Chao Yu   f2fs: introduce r...
152
  	for (; nrpages-- > 0; blkno++) {
662befda2   Chao Yu   f2fs: introduce r...
153

66b00c186   Chao Yu   f2fs: introduce i...
154
155
  		if (!is_valid_blkaddr(sbi, blkno, type))
  			goto out;
662befda2   Chao Yu   f2fs: introduce r...
156
157
  		switch (type) {
  		case META_NAT:
66b00c186   Chao Yu   f2fs: introduce i...
158
159
  			if (unlikely(blkno >=
  					NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)))
662befda2   Chao Yu   f2fs: introduce r...
160
  				blkno = 0;
66b00c186   Chao Yu   f2fs: introduce i...
161
  			/* get nat block addr */
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
162
  			fio.blk_addr = current_nat_addr(sbi,
662befda2   Chao Yu   f2fs: introduce r...
163
164
165
166
  					blkno * NAT_ENTRY_PER_BLOCK);
  			break;
  		case META_SIT:
  			/* get sit block addr */
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
167
  			fio.blk_addr = current_sit_addr(sbi,
662befda2   Chao Yu   f2fs: introduce r...
168
  					blkno * SIT_ENTRY_PER_BLOCK);
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
169
  			if (blkno != start && prev_blk_addr + 1 != fio.blk_addr)
662befda2   Chao Yu   f2fs: introduce r...
170
  				goto out;
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
171
  			prev_blk_addr = fio.blk_addr;
662befda2   Chao Yu   f2fs: introduce r...
172
  			break;
81c1a0f13   Chao Yu   f2fs: readahead c...
173
  		case META_SSA:
662befda2   Chao Yu   f2fs: introduce r...
174
  		case META_CP:
4c521f493   Jaegeuk Kim   f2fs: use meta_in...
175
  		case META_POR:
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
176
  			fio.blk_addr = blkno;
662befda2   Chao Yu   f2fs: introduce r...
177
178
179
180
  			break;
  		default:
  			BUG();
  		}
cf04e8eb5   Jaegeuk Kim   f2fs: use f2fs_io...
181
  		page = grab_cache_page(META_MAPPING(sbi), fio.blk_addr);
662befda2   Chao Yu   f2fs: introduce r...
182
183
184
  		if (!page)
  			continue;
  		if (PageUptodate(page)) {
662befda2   Chao Yu   f2fs: introduce r...
185
186
187
  			f2fs_put_page(page, 1);
  			continue;
  		}
05ca3632e   Jaegeuk Kim   f2fs: add sbi and...
188
189
  		fio.page = page;
  		f2fs_submit_page_mbio(&fio);
662befda2   Chao Yu   f2fs: introduce r...
190
191
192
193
194
195
  		f2fs_put_page(page, 0);
  	}
  out:
  	f2fs_submit_merged_bio(sbi, META, READ);
  	return blkno - start;
  }
635aee1fe   Chao Yu   f2fs: avoid to ra...
196
197
198
199
200
201
202
203
204
205
206
  void ra_meta_pages_cond(struct f2fs_sb_info *sbi, pgoff_t index)
  {
  	struct page *page;
  	bool readahead = false;
  
  	page = find_get_page(META_MAPPING(sbi), index);
  	if (!page || (page && !PageUptodate(page)))
  		readahead = true;
  	f2fs_put_page(page, 0);
  
  	if (readahead)
26879fb10   Chao Yu   f2fs: support low...
207
  		ra_meta_pages(sbi, index, MAX_BIO_BLOCKS(sbi), META_POR, true);
635aee1fe   Chao Yu   f2fs: avoid to ra...
208
  }
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
209
210
211
  static int f2fs_write_meta_page(struct page *page,
  				struct writeback_control *wbc)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
212
  	struct f2fs_sb_info *sbi = F2FS_P_SB(page);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
213

ecda0de34   Chao Yu   f2fs: add a trace...
214
  	trace_f2fs_writepage(page, META);
caf0047e7   Chao Yu   f2fs: merge flags...
215
  	if (unlikely(is_sbi_flag_set(sbi, SBI_POR_DOING)))
cfb271d48   Chao Yu   f2fs: add unlikel...
216
  		goto redirty_out;
857dc4e05   Jaegeuk Kim   f2fs: write SSA p...
217
  	if (wbc->for_reclaim && page->index < GET_SUM_BLOCK(sbi, 0))
cfb271d48   Chao Yu   f2fs: add unlikel...
218
  		goto redirty_out;
1e968fdfe   Jaegeuk Kim   f2fs: introduce f...
219
  	if (unlikely(f2fs_cp_error(sbi)))
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
220
  		goto redirty_out;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
221

3cb5ad152   Jaegeuk Kim   f2fs: call f2fs_w...
222
  	f2fs_wait_on_page_writeback(page, META);
577e34951   Jaegeuk Kim   f2fs: prevent che...
223
224
225
  	write_meta_page(sbi, page);
  	dec_page_count(sbi, F2FS_DIRTY_META);
  	unlock_page(page);
857dc4e05   Jaegeuk Kim   f2fs: write SSA p...
226

8d4ea29b6   Jaegeuk Kim   f2fs: write pendi...
227
  	if (wbc->for_reclaim || unlikely(f2fs_cp_error(sbi)))
857dc4e05   Jaegeuk Kim   f2fs: write SSA p...
228
  		f2fs_submit_merged_bio(sbi, META, WRITE);
577e34951   Jaegeuk Kim   f2fs: prevent che...
229
  	return 0;
cfb271d48   Chao Yu   f2fs: add unlikel...
230
231
  
  redirty_out:
76f60268e   Jaegeuk Kim   f2fs: call redirt...
232
  	redirty_page_for_writepage(wbc, page);
cfb271d48   Chao Yu   f2fs: add unlikel...
233
  	return AOP_WRITEPAGE_ACTIVATE;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
234
235
236
237
238
  }
  
  static int f2fs_write_meta_pages(struct address_space *mapping,
  				struct writeback_control *wbc)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
239
  	struct f2fs_sb_info *sbi = F2FS_M_SB(mapping);
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
240
  	long diff, written;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
241

e57484343   Chao Yu   f2fs: add a trace...
242
  	trace_f2fs_writepages(mapping->host, wbc, META);
5459aa977   Jaegeuk Kim   f2fs: write dirty...
243
  	/* collect a number of dirty meta pages and write together */
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
244
245
  	if (wbc->for_kupdate ||
  		get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META))
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
246
  		goto skip_write;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
247
248
249
  
  	/* if mounting is failed, skip writing node pages */
  	mutex_lock(&sbi->cp_mutex);
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
250
251
  	diff = nr_pages_to_write(sbi, META, wbc);
  	written = sync_meta_pages(sbi, META, wbc->nr_to_write);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
252
  	mutex_unlock(&sbi->cp_mutex);
50c8cdb35   Jaegeuk Kim   f2fs: introduce n...
253
  	wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
254
  	return 0;
d3baf95da   Jaegeuk Kim   f2fs: increase pa...
255
256
257
258
  
  skip_write:
  	wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META);
  	return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
259
260
261
262
263
  }
  
  long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type,
  						long nr_to_write)
  {
9df27d982   Gu Zheng   f2fs: add help fu...
264
  	struct address_space *mapping = META_MAPPING(sbi);
6066d8cdb   Jaegeuk Kim   f2fs: merge meta ...
265
  	pgoff_t index = 0, end = LONG_MAX, prev = LONG_MAX;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
266
267
268
269
270
271
272
273
274
275
276
277
278
  	struct pagevec pvec;
  	long nwritten = 0;
  	struct writeback_control wbc = {
  		.for_reclaim = 0,
  	};
  
  	pagevec_init(&pvec, 0);
  
  	while (index <= end) {
  		int i, nr_pages;
  		nr_pages = pagevec_lookup_tag(&pvec, mapping, &index,
  				PAGECACHE_TAG_DIRTY,
  				min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1);
cfb271d48   Chao Yu   f2fs: add unlikel...
279
  		if (unlikely(nr_pages == 0))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
280
281
282
283
  			break;
  
  		for (i = 0; i < nr_pages; i++) {
  			struct page *page = pvec.pages[i];
203681f65   Jaegeuk Kim   f2fs: fix f2fs_wr...
284

6066d8cdb   Jaegeuk Kim   f2fs: merge meta ...
285
286
287
288
289
290
  			if (prev == LONG_MAX)
  				prev = page->index - 1;
  			if (nr_to_write != LONG_MAX && page->index != prev + 1) {
  				pagevec_release(&pvec);
  				goto stop;
  			}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
291
  			lock_page(page);
203681f65   Jaegeuk Kim   f2fs: fix f2fs_wr...
292
293
294
295
296
297
298
299
300
301
302
303
304
  
  			if (unlikely(page->mapping != mapping)) {
  continue_unlock:
  				unlock_page(page);
  				continue;
  			}
  			if (!PageDirty(page)) {
  				/* someone wrote it for us */
  				goto continue_unlock;
  			}
  
  			if (!clear_page_dirty_for_io(page))
  				goto continue_unlock;
97dc3fd2c   Chao Yu   f2fs: use ->write...
305
  			if (mapping->a_ops->writepage(page, &wbc)) {
577e34951   Jaegeuk Kim   f2fs: prevent che...
306
307
308
  				unlock_page(page);
  				break;
  			}
cfb271d48   Chao Yu   f2fs: add unlikel...
309
  			nwritten++;
6066d8cdb   Jaegeuk Kim   f2fs: merge meta ...
310
  			prev = page->index;
cfb271d48   Chao Yu   f2fs: add unlikel...
311
  			if (unlikely(nwritten >= nr_to_write))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
312
313
314
315
316
  				break;
  		}
  		pagevec_release(&pvec);
  		cond_resched();
  	}
6066d8cdb   Jaegeuk Kim   f2fs: merge meta ...
317
  stop:
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
318
  	if (nwritten)
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
319
  		f2fs_submit_merged_bio(sbi, type, WRITE);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
320
321
322
323
324
325
  
  	return nwritten;
  }
  
  static int f2fs_set_meta_page_dirty(struct page *page)
  {
26c6b8879   Jaegeuk Kim   f2fs: add tracepo...
326
  	trace_f2fs_set_page_dirty(page, META);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
327
328
329
  	SetPageUptodate(page);
  	if (!PageDirty(page)) {
  		__set_page_dirty_nobuffers(page);
4081363fb   Jaegeuk Kim   f2fs: introduce F...
330
  		inc_page_count(F2FS_P_SB(page), F2FS_DIRTY_META);
1601839e9   Chao Yu   f2fs: fix to rele...
331
  		SetPagePrivate(page);
9e4ded3f3   Jaegeuk Kim   f2fs: activate f2...
332
  		f2fs_trace_pid(page);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
333
334
335
336
337
338
339
340
341
  		return 1;
  	}
  	return 0;
  }
  
  const struct address_space_operations f2fs_meta_aops = {
  	.writepage	= f2fs_write_meta_page,
  	.writepages	= f2fs_write_meta_pages,
  	.set_page_dirty	= f2fs_set_meta_page_dirty,
487261f39   Chao Yu   f2fs: merge {inva...
342
343
  	.invalidatepage = f2fs_invalidate_page,
  	.releasepage	= f2fs_release_page,
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
344
  };
6451e041c   Jaegeuk Kim   f2fs: add infra f...
345
  static void __add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
346
  {
67298804f   Chao Yu   f2fs: introduce s...
347
  	struct inode_management *im = &sbi->im[type];
80c545055   Jaegeuk Kim   f2fs: use __GFP_N...
348
349
350
  	struct ino_entry *e, *tmp;
  
  	tmp = f2fs_kmem_cache_alloc(ino_entry_slab, GFP_NOFS);
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
351
  retry:
80c545055   Jaegeuk Kim   f2fs: use __GFP_N...
352
  	radix_tree_preload(GFP_NOFS | __GFP_NOFAIL);
769ec6e5b   Jaegeuk Kim   f2fs: call radix_...
353

67298804f   Chao Yu   f2fs: introduce s...
354
  	spin_lock(&im->ino_lock);
67298804f   Chao Yu   f2fs: introduce s...
355
  	e = radix_tree_lookup(&im->ino_root, ino);
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
356
  	if (!e) {
80c545055   Jaegeuk Kim   f2fs: use __GFP_N...
357
  		e = tmp;
67298804f   Chao Yu   f2fs: introduce s...
358
359
  		if (radix_tree_insert(&im->ino_root, ino, e)) {
  			spin_unlock(&im->ino_lock);
769ec6e5b   Jaegeuk Kim   f2fs: call radix_...
360
  			radix_tree_preload_end();
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
361
362
363
364
  			goto retry;
  		}
  		memset(e, 0, sizeof(struct ino_entry));
  		e->ino = ino;
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
365

67298804f   Chao Yu   f2fs: introduce s...
366
  		list_add_tail(&e->list, &im->ino_list);
8c402946f   Jaegeuk Kim   f2fs: introduce t...
367
  		if (type != ORPHAN_INO)
67298804f   Chao Yu   f2fs: introduce s...
368
  			im->ino_num++;
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
369
  	}
67298804f   Chao Yu   f2fs: introduce s...
370
  	spin_unlock(&im->ino_lock);
769ec6e5b   Jaegeuk Kim   f2fs: call radix_...
371
  	radix_tree_preload_end();
80c545055   Jaegeuk Kim   f2fs: use __GFP_N...
372
373
374
  
  	if (e != tmp)
  		kmem_cache_free(ino_entry_slab, tmp);
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
375
  }
6451e041c   Jaegeuk Kim   f2fs: add infra f...
376
  static void __remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
377
  {
67298804f   Chao Yu   f2fs: introduce s...
378
  	struct inode_management *im = &sbi->im[type];
6451e041c   Jaegeuk Kim   f2fs: add infra f...
379
  	struct ino_entry *e;
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
380

67298804f   Chao Yu   f2fs: introduce s...
381
382
  	spin_lock(&im->ino_lock);
  	e = radix_tree_lookup(&im->ino_root, ino);
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
383
384
  	if (e) {
  		list_del(&e->list);
67298804f   Chao Yu   f2fs: introduce s...
385
386
387
  		radix_tree_delete(&im->ino_root, ino);
  		im->ino_num--;
  		spin_unlock(&im->ino_lock);
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
388
389
  		kmem_cache_free(ino_entry_slab, e);
  		return;
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
390
  	}
67298804f   Chao Yu   f2fs: introduce s...
391
  	spin_unlock(&im->ino_lock);
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
392
  }
a49324f12   Chao Yu   f2fs: rename {add...
393
  void add_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
fff04f90c   Jaegeuk Kim   f2fs: add info of...
394
395
396
397
  {
  	/* add new dirty ino entry into list */
  	__add_ino_entry(sbi, ino, type);
  }
a49324f12   Chao Yu   f2fs: rename {add...
398
  void remove_ino_entry(struct f2fs_sb_info *sbi, nid_t ino, int type)
fff04f90c   Jaegeuk Kim   f2fs: add info of...
399
400
401
402
403
404
405
406
  {
  	/* remove dirty ino entry from list */
  	__remove_ino_entry(sbi, ino, type);
  }
  
  /* mode should be APPEND_INO or UPDATE_INO */
  bool exist_written_data(struct f2fs_sb_info *sbi, nid_t ino, int mode)
  {
67298804f   Chao Yu   f2fs: introduce s...
407
  	struct inode_management *im = &sbi->im[mode];
fff04f90c   Jaegeuk Kim   f2fs: add info of...
408
  	struct ino_entry *e;
67298804f   Chao Yu   f2fs: introduce s...
409
410
411
412
  
  	spin_lock(&im->ino_lock);
  	e = radix_tree_lookup(&im->ino_root, ino);
  	spin_unlock(&im->ino_lock);
fff04f90c   Jaegeuk Kim   f2fs: add info of...
413
414
  	return e ? true : false;
  }
a49324f12   Chao Yu   f2fs: rename {add...
415
  void release_ino_entry(struct f2fs_sb_info *sbi)
fff04f90c   Jaegeuk Kim   f2fs: add info of...
416
417
418
419
420
  {
  	struct ino_entry *e, *tmp;
  	int i;
  
  	for (i = APPEND_INO; i <= UPDATE_INO; i++) {
67298804f   Chao Yu   f2fs: introduce s...
421
422
423
424
  		struct inode_management *im = &sbi->im[i];
  
  		spin_lock(&im->ino_lock);
  		list_for_each_entry_safe(e, tmp, &im->ino_list, list) {
fff04f90c   Jaegeuk Kim   f2fs: add info of...
425
  			list_del(&e->list);
67298804f   Chao Yu   f2fs: introduce s...
426
  			radix_tree_delete(&im->ino_root, e->ino);
fff04f90c   Jaegeuk Kim   f2fs: add info of...
427
  			kmem_cache_free(ino_entry_slab, e);
67298804f   Chao Yu   f2fs: introduce s...
428
  			im->ino_num--;
fff04f90c   Jaegeuk Kim   f2fs: add info of...
429
  		}
67298804f   Chao Yu   f2fs: introduce s...
430
  		spin_unlock(&im->ino_lock);
fff04f90c   Jaegeuk Kim   f2fs: add info of...
431
432
  	}
  }
cbd56e7d2   Jaegeuk Kim   f2fs: fix handlin...
433
  int acquire_orphan_inode(struct f2fs_sb_info *sbi)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
434
  {
67298804f   Chao Yu   f2fs: introduce s...
435
  	struct inode_management *im = &sbi->im[ORPHAN_INO];
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
436
  	int err = 0;
67298804f   Chao Yu   f2fs: introduce s...
437
438
  	spin_lock(&im->ino_lock);
  	if (unlikely(im->ino_num >= sbi->max_orphans))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
439
  		err = -ENOSPC;
cbd56e7d2   Jaegeuk Kim   f2fs: fix handlin...
440
  	else
67298804f   Chao Yu   f2fs: introduce s...
441
442
  		im->ino_num++;
  	spin_unlock(&im->ino_lock);
0d47c1adc   Gu Zheng   f2fs: convert max...
443

127e670ab   Jaegeuk Kim   f2fs: add checkpo...
444
445
  	return err;
  }
cbd56e7d2   Jaegeuk Kim   f2fs: fix handlin...
446
447
  void release_orphan_inode(struct f2fs_sb_info *sbi)
  {
67298804f   Chao Yu   f2fs: introduce s...
448
449
450
451
452
453
  	struct inode_management *im = &sbi->im[ORPHAN_INO];
  
  	spin_lock(&im->ino_lock);
  	f2fs_bug_on(sbi, im->ino_num == 0);
  	im->ino_num--;
  	spin_unlock(&im->ino_lock);
cbd56e7d2   Jaegeuk Kim   f2fs: fix handlin...
454
  }
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
455
456
  void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
  {
39efac41f   Jaegeuk Kim   f2fs: use radix_t...
457
  	/* add new orphan ino entry into list */
6451e041c   Jaegeuk Kim   f2fs: add infra f...
458
  	__add_ino_entry(sbi, ino, ORPHAN_INO);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
459
460
461
462
  }
  
  void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
  {
953e6cc6b   Jaegeuk Kim   f2fs: punch the c...
463
  	/* remove orphan entry from orphan list */
6451e041c   Jaegeuk Kim   f2fs: add infra f...
464
  	__remove_ino_entry(sbi, ino, ORPHAN_INO);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
465
  }
8c14bfade   Chao Yu   f2fs: handle erro...
466
  static int recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
467
  {
8c14bfade   Chao Yu   f2fs: handle erro...
468
469
470
471
472
473
474
475
476
477
478
  	struct inode *inode;
  
  	inode = f2fs_iget(sbi->sb, ino);
  	if (IS_ERR(inode)) {
  		/*
  		 * there should be a bug that we can't find the entry
  		 * to orphan inode.
  		 */
  		f2fs_bug_on(sbi, PTR_ERR(inode) == -ENOENT);
  		return PTR_ERR(inode);
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
479
480
481
482
  	clear_nlink(inode);
  
  	/* truncate all the data during iput */
  	iput(inode);
8c14bfade   Chao Yu   f2fs: handle erro...
483
  	return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
484
  }
8c14bfade   Chao Yu   f2fs: handle erro...
485
  int recover_orphan_inodes(struct f2fs_sb_info *sbi)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
486
  {
3c6429857   Wanpeng Li   f2fs: fix the num...
487
  	block_t start_blk, orphan_blocks, i, j;
8c14bfade   Chao Yu   f2fs: handle erro...
488
  	int err;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
489

25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
490
  	if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG))
8c14bfade   Chao Yu   f2fs: handle erro...
491
  		return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
492

551414861   Wanpeng Li   f2fs: introduce m...
493
  	start_blk = __start_cp_addr(sbi) + 1 + __cp_payload(sbi);
3c6429857   Wanpeng Li   f2fs: fix the num...
494
  	orphan_blocks = __start_sum_addr(sbi) - 1 - __cp_payload(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
495

26879fb10   Chao Yu   f2fs: support low...
496
  	ra_meta_pages(sbi, start_blk, orphan_blocks, META_CP, true);
662befda2   Chao Yu   f2fs: introduce r...
497

3c6429857   Wanpeng Li   f2fs: fix the num...
498
  	for (i = 0; i < orphan_blocks; i++) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
499
500
501
502
503
504
  		struct page *page = get_meta_page(sbi, start_blk + i);
  		struct f2fs_orphan_block *orphan_blk;
  
  		orphan_blk = (struct f2fs_orphan_block *)page_address(page);
  		for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) {
  			nid_t ino = le32_to_cpu(orphan_blk->ino[j]);
8c14bfade   Chao Yu   f2fs: handle erro...
505
506
507
  			err = recover_orphan_inode(sbi, ino);
  			if (err) {
  				f2fs_put_page(page, 1);
8c14bfade   Chao Yu   f2fs: handle erro...
508
509
  				return err;
  			}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
510
511
512
513
  		}
  		f2fs_put_page(page, 1);
  	}
  	/* clear Orphan Flag */
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
514
  	clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG);
8c14bfade   Chao Yu   f2fs: handle erro...
515
  	return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
516
517
518
519
  }
  
  static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk)
  {
502c6e0bc   Gu Zheng   f2fs: simplify wr...
520
  	struct list_head *head;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
521
  	struct f2fs_orphan_block *orphan_blk = NULL;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
522
  	unsigned int nentries = 0;
bd936f840   Chao Yu   f2fs: cleanup wri...
523
  	unsigned short index = 1;
8c402946f   Jaegeuk Kim   f2fs: introduce t...
524
  	unsigned short orphan_blocks;
4531929e3   Gu Zheng   f2fs: move grabin...
525
  	struct page *page = NULL;
6451e041c   Jaegeuk Kim   f2fs: add infra f...
526
  	struct ino_entry *orphan = NULL;
67298804f   Chao Yu   f2fs: introduce s...
527
  	struct inode_management *im = &sbi->im[ORPHAN_INO];
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
528

67298804f   Chao Yu   f2fs: introduce s...
529
  	orphan_blocks = GET_ORPHAN_BLOCKS(im->ino_num);
8c402946f   Jaegeuk Kim   f2fs: introduce t...
530

d6c67a4fe   Jaegeuk Kim   f2fs: revmove spi...
531
532
533
534
535
  	/*
  	 * we don't need to do spin_lock(&im->ino_lock) here, since all the
  	 * orphan inode operations are covered under f2fs_lock_op().
  	 * And, spin_lock should be avoided due to page operations below.
  	 */
67298804f   Chao Yu   f2fs: introduce s...
536
  	head = &im->ino_list;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
537
538
  
  	/* loop for each orphan inode entry and write them in Jornal block */
502c6e0bc   Gu Zheng   f2fs: simplify wr...
539
540
  	list_for_each_entry(orphan, head, list) {
  		if (!page) {
bd936f840   Chao Yu   f2fs: cleanup wri...
541
  			page = grab_meta_page(sbi, start_blk++);
502c6e0bc   Gu Zheng   f2fs: simplify wr...
542
543
544
545
  			orphan_blk =
  				(struct f2fs_orphan_block *)page_address(page);
  			memset(orphan_blk, 0, sizeof(*orphan_blk));
  		}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
546

367955679   Gu Zheng   f2fs: fix a poten...
547
  		orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
548

367955679   Gu Zheng   f2fs: fix a poten...
549
  		if (nentries == F2FS_ORPHANS_PER_BLOCK) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
550
551
552
553
554
555
556
557
558
559
560
  			/*
  			 * an orphan block is full of 1020 entries,
  			 * then we need to flush current orphan blocks
  			 * and bring another one in memory
  			 */
  			orphan_blk->blk_addr = cpu_to_le16(index);
  			orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
  			orphan_blk->entry_count = cpu_to_le32(nentries);
  			set_page_dirty(page);
  			f2fs_put_page(page, 1);
  			index++;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
561
562
563
  			nentries = 0;
  			page = NULL;
  		}
502c6e0bc   Gu Zheng   f2fs: simplify wr...
564
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
565

502c6e0bc   Gu Zheng   f2fs: simplify wr...
566
567
568
569
570
571
  	if (page) {
  		orphan_blk->blk_addr = cpu_to_le16(index);
  		orphan_blk->blk_count = cpu_to_le16(orphan_blocks);
  		orphan_blk->entry_count = cpu_to_le32(nentries);
  		set_page_dirty(page);
  		f2fs_put_page(page, 1);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
572
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
573
574
575
576
577
578
579
580
581
  }
  
  static struct page *validate_checkpoint(struct f2fs_sb_info *sbi,
  				block_t cp_addr, unsigned long long *version)
  {
  	struct page *cp_page_1, *cp_page_2 = NULL;
  	unsigned long blk_size = sbi->blocksize;
  	struct f2fs_checkpoint *cp_block;
  	unsigned long long cur_version = 0, pre_version = 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
582
  	size_t crc_offset;
7e586fa02   Jaegeuk Kim   f2fs: fix crc end...
583
  	__u32 crc = 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
584
585
586
587
588
589
590
591
592
  
  	/* Read the 1st cp block in this CP pack */
  	cp_page_1 = get_meta_page(sbi, cp_addr);
  
  	/* get the version number */
  	cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1);
  	crc_offset = le32_to_cpu(cp_block->checksum_offset);
  	if (crc_offset >= blk_size)
  		goto invalid_cp1;
29e7043f4   Jaegeuk Kim   f2fs: fix sparse ...
593
  	crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset)));
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
594
595
  	if (!f2fs_crc_valid(crc, cp_block, crc_offset))
  		goto invalid_cp1;
d71b5564c   Jaegeuk Kim   f2fs: introduce c...
596
  	pre_version = cur_cp_version(cp_block);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
597
598
  
  	/* Read the 2nd cp block in this CP pack */
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
599
  	cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
600
601
602
603
604
605
  	cp_page_2 = get_meta_page(sbi, cp_addr);
  
  	cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2);
  	crc_offset = le32_to_cpu(cp_block->checksum_offset);
  	if (crc_offset >= blk_size)
  		goto invalid_cp2;
29e7043f4   Jaegeuk Kim   f2fs: fix sparse ...
606
  	crc = le32_to_cpu(*((__le32 *)((unsigned char *)cp_block + crc_offset)));
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
607
608
  	if (!f2fs_crc_valid(crc, cp_block, crc_offset))
  		goto invalid_cp2;
d71b5564c   Jaegeuk Kim   f2fs: introduce c...
609
  	cur_version = cur_cp_version(cp_block);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
  
  	if (cur_version == pre_version) {
  		*version = cur_version;
  		f2fs_put_page(cp_page_2, 1);
  		return cp_page_1;
  	}
  invalid_cp2:
  	f2fs_put_page(cp_page_2, 1);
  invalid_cp1:
  	f2fs_put_page(cp_page_1, 1);
  	return NULL;
  }
  
  int get_valid_checkpoint(struct f2fs_sb_info *sbi)
  {
  	struct f2fs_checkpoint *cp_block;
  	struct f2fs_super_block *fsb = sbi->raw_super;
  	struct page *cp1, *cp2, *cur_page;
  	unsigned long blk_size = sbi->blocksize;
  	unsigned long long cp1_version = 0, cp2_version = 0;
  	unsigned long long cp_start_blk_no;
551414861   Wanpeng Li   f2fs: introduce m...
631
  	unsigned int cp_blks = 1 + __cp_payload(sbi);
1dbe41521   Changman Lee   f2fs: large volum...
632
633
  	block_t cp_blk_no;
  	int i;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
634

1dbe41521   Changman Lee   f2fs: large volum...
635
  	sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
636
637
638
639
640
641
642
643
644
645
  	if (!sbi->ckpt)
  		return -ENOMEM;
  	/*
  	 * Finding out valid cp block involves read both
  	 * sets( cp pack1 and cp pack 2)
  	 */
  	cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr);
  	cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version);
  
  	/* The second checkpoint pack should start at the next segment */
f9a4e6df5   Jaegeuk Kim   f2fs: bug fix on ...
646
647
  	cp_start_blk_no += ((unsigned long long)1) <<
  				le32_to_cpu(fsb->log_blocks_per_seg);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
  	cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version);
  
  	if (cp1 && cp2) {
  		if (ver_after(cp2_version, cp1_version))
  			cur_page = cp2;
  		else
  			cur_page = cp1;
  	} else if (cp1) {
  		cur_page = cp1;
  	} else if (cp2) {
  		cur_page = cp2;
  	} else {
  		goto fail_no_cp;
  	}
  
  	cp_block = (struct f2fs_checkpoint *)page_address(cur_page);
  	memcpy(sbi->ckpt, cp_block, blk_size);
1dbe41521   Changman Lee   f2fs: large volum...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
  	if (cp_blks <= 1)
  		goto done;
  
  	cp_blk_no = le32_to_cpu(fsb->cp_blkaddr);
  	if (cur_page == cp2)
  		cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg);
  
  	for (i = 1; i < cp_blks; i++) {
  		void *sit_bitmap_ptr;
  		unsigned char *ckpt = (unsigned char *)sbi->ckpt;
  
  		cur_page = get_meta_page(sbi, cp_blk_no + i);
  		sit_bitmap_ptr = page_address(cur_page);
  		memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size);
  		f2fs_put_page(cur_page, 1);
  	}
  done:
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
682
683
684
685
686
687
688
689
  	f2fs_put_page(cp1, 1);
  	f2fs_put_page(cp2, 1);
  	return 0;
  
  fail_no_cp:
  	kfree(sbi->ckpt);
  	return -EINVAL;
  }
c227f9127   Chao Yu   f2fs: record dirt...
690
  static void __add_dirty_inode(struct inode *inode, enum inode_type type)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
691
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
692
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2710fd7e0   Chao Yu   f2fs: introduce d...
693
  	struct f2fs_inode_info *fi = F2FS_I(inode);
c227f9127   Chao Yu   f2fs: record dirt...
694
  	int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
695

c227f9127   Chao Yu   f2fs: record dirt...
696
  	if (is_inode_flag_set(fi, flag))
2710fd7e0   Chao Yu   f2fs: introduce d...
697
  		return;
2d7b822ad   Chao Yu   f2fs: use list_fo...
698

c227f9127   Chao Yu   f2fs: record dirt...
699
700
  	set_inode_flag(fi, flag);
  	list_add_tail(&fi->dirty_list, &sbi->inode_list[type]);
33fbd5100   Chao Yu   f2fs: stat dirty ...
701
  	stat_inc_dirty_inode(sbi, type);
5deb82671   Jaegeuk Kim   f2fs: fix iget/ip...
702
  }
c227f9127   Chao Yu   f2fs: record dirt...
703
  static void __remove_dirty_inode(struct inode *inode, enum inode_type type)
6ad7609a1   Chao Yu   f2fs: introduce _...
704
  {
6ad7609a1   Chao Yu   f2fs: introduce _...
705
  	struct f2fs_inode_info *fi = F2FS_I(inode);
c227f9127   Chao Yu   f2fs: record dirt...
706
  	int flag = (type == DIR_INODE) ? FI_DIRTY_DIR : FI_DIRTY_FILE;
6ad7609a1   Chao Yu   f2fs: introduce _...
707
708
  
  	if (get_dirty_pages(inode) ||
c227f9127   Chao Yu   f2fs: record dirt...
709
  			!is_inode_flag_set(F2FS_I(inode), flag))
6ad7609a1   Chao Yu   f2fs: introduce _...
710
711
712
  		return;
  
  	list_del_init(&fi->dirty_list);
c227f9127   Chao Yu   f2fs: record dirt...
713
  	clear_inode_flag(fi, flag);
33fbd5100   Chao Yu   f2fs: stat dirty ...
714
  	stat_dec_dirty_inode(F2FS_I_SB(inode), type);
6ad7609a1   Chao Yu   f2fs: introduce _...
715
  }
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
716
  void update_dirty_page(struct inode *inode, struct page *page)
5deb82671   Jaegeuk Kim   f2fs: fix iget/ip...
717
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
718
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
c227f9127   Chao Yu   f2fs: record dirt...
719
  	enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
5deb82671   Jaegeuk Kim   f2fs: fix iget/ip...
720

5ac9f36fc   Chao Yu   f2fs: fix to reco...
721
722
  	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
  			!S_ISLNK(inode->i_mode))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
723
  		return;
7bd59381c   Gu Zheng   f2fs: introduce f...
724

c227f9127   Chao Yu   f2fs: record dirt...
725
726
  	spin_lock(&sbi->inode_lock[type]);
  	__add_dirty_inode(inode, type);
a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
727
  	inode_inc_dirty_pages(inode);
c227f9127   Chao Yu   f2fs: record dirt...
728
  	spin_unlock(&sbi->inode_lock[type]);
cf0ee0f09   Chao Yu   f2fs: avoid free ...
729

a7ffdbe22   Jaegeuk Kim   f2fs: expand coun...
730
  	SetPagePrivate(page);
9e4ded3f3   Jaegeuk Kim   f2fs: activate f2...
731
  	f2fs_trace_pid(page);
5deb82671   Jaegeuk Kim   f2fs: fix iget/ip...
732
733
734
735
  }
  
  void add_dirty_dir_inode(struct inode *inode)
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
736
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
737

c227f9127   Chao Yu   f2fs: record dirt...
738
739
740
  	spin_lock(&sbi->inode_lock[DIR_INODE]);
  	__add_dirty_inode(inode, DIR_INODE);
  	spin_unlock(&sbi->inode_lock[DIR_INODE]);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
741
  }
c227f9127   Chao Yu   f2fs: record dirt...
742
  void remove_dirty_inode(struct inode *inode)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
743
  {
4081363fb   Jaegeuk Kim   f2fs: introduce F...
744
  	struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
2710fd7e0   Chao Yu   f2fs: introduce d...
745
  	struct f2fs_inode_info *fi = F2FS_I(inode);
c227f9127   Chao Yu   f2fs: record dirt...
746
  	enum inode_type type = S_ISDIR(inode->i_mode) ? DIR_INODE : FILE_INODE;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
747

c227f9127   Chao Yu   f2fs: record dirt...
748
749
  	if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
  			!S_ISLNK(inode->i_mode))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
750
  		return;
c227f9127   Chao Yu   f2fs: record dirt...
751
752
753
  	spin_lock(&sbi->inode_lock[type]);
  	__remove_dirty_inode(inode, type);
  	spin_unlock(&sbi->inode_lock[type]);
74d0b917e   Jaegeuk Kim   f2fs: fix BUG_ON ...
754
755
  
  	/* Only from the recovery routine */
2710fd7e0   Chao Yu   f2fs: introduce d...
756
757
  	if (is_inode_flag_set(fi, FI_DELAY_IPUT)) {
  		clear_inode_flag(fi, FI_DELAY_IPUT);
74d0b917e   Jaegeuk Kim   f2fs: fix BUG_ON ...
758
  		iput(inode);
afc3eda2a   Jaegeuk Kim   f2fs: fix incorre...
759
  	}
74d0b917e   Jaegeuk Kim   f2fs: fix BUG_ON ...
760
  }
6d5a1495e   Chao Yu   f2fs: let user be...
761
  int sync_dirty_inodes(struct f2fs_sb_info *sbi, enum inode_type type)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
762
  {
ce3b7d80e   Gu Zheng   f2fs: move the li...
763
  	struct list_head *head;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
764
  	struct inode *inode;
2710fd7e0   Chao Yu   f2fs: introduce d...
765
  	struct f2fs_inode_info *fi;
4cf185379   Chao Yu   f2fs: add a trace...
766
767
768
769
770
  	bool is_dir = (type == DIR_INODE);
  
  	trace_f2fs_sync_dirty_inodes_enter(sbi->sb, is_dir,
  				get_pages(sbi, is_dir ?
  				F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA));
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
771
  retry:
af41d3ee0   Jaegeuk Kim   f2fs: avoid infin...
772
  	if (unlikely(f2fs_cp_error(sbi)))
6d5a1495e   Chao Yu   f2fs: let user be...
773
  		return -EIO;
af41d3ee0   Jaegeuk Kim   f2fs: avoid infin...
774

c227f9127   Chao Yu   f2fs: record dirt...
775
  	spin_lock(&sbi->inode_lock[type]);
ce3b7d80e   Gu Zheng   f2fs: move the li...
776

c227f9127   Chao Yu   f2fs: record dirt...
777
  	head = &sbi->inode_list[type];
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
778
  	if (list_empty(head)) {
c227f9127   Chao Yu   f2fs: record dirt...
779
  		spin_unlock(&sbi->inode_lock[type]);
4cf185379   Chao Yu   f2fs: add a trace...
780
781
782
  		trace_f2fs_sync_dirty_inodes_exit(sbi->sb, is_dir,
  				get_pages(sbi, is_dir ?
  				F2FS_DIRTY_DENTS : F2FS_DIRTY_DATA));
6d5a1495e   Chao Yu   f2fs: let user be...
783
  		return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
784
  	}
2710fd7e0   Chao Yu   f2fs: introduce d...
785
786
  	fi = list_entry(head->next, struct f2fs_inode_info, dirty_list);
  	inode = igrab(&fi->vfs_inode);
c227f9127   Chao Yu   f2fs: record dirt...
787
  	spin_unlock(&sbi->inode_lock[type]);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
788
  	if (inode) {
87d6f8909   Jaegeuk Kim   f2fs: avoid small...
789
  		filemap_fdatawrite(inode->i_mapping);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
790
791
792
793
794
795
  		iput(inode);
  	} else {
  		/*
  		 * We should submit bio, since it exists several
  		 * wribacking dentry pages in the freeing inode.
  		 */
458e6197c   Jaegeuk Kim   f2fs: refactor bi...
796
  		f2fs_submit_merged_bio(sbi, DATA, WRITE);
7ecebe5e0   Sebastian Andrzej Siewior   f2fs: add cond_re...
797
  		cond_resched();
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
798
799
800
  	}
  	goto retry;
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
801
  /*
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
802
803
   * Freeze all the FS-operations for checkpoint.
   */
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
804
  static int block_operations(struct f2fs_sb_info *sbi)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
805
  {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
806
807
808
809
810
  	struct writeback_control wbc = {
  		.sync_mode = WB_SYNC_ALL,
  		.nr_to_write = LONG_MAX,
  		.for_reclaim = 0,
  	};
c718379b6   Jaegeuk Kim   f2fs: give a chan...
811
  	struct blk_plug plug;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
812
  	int err = 0;
c718379b6   Jaegeuk Kim   f2fs: give a chan...
813
814
  
  	blk_start_plug(&plug);
399368372   Jaegeuk Kim   f2fs: introduce a...
815
  retry_flush_dents:
e479556bf   Gu Zheng   f2fs: use rw_sem ...
816
  	f2fs_lock_all(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
817
  	/* write all the dirty dentry pages */
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
818
  	if (get_pages(sbi, F2FS_DIRTY_DENTS)) {
e479556bf   Gu Zheng   f2fs: use rw_sem ...
819
  		f2fs_unlock_all(sbi);
6d5a1495e   Chao Yu   f2fs: let user be...
820
821
  		err = sync_dirty_inodes(sbi, DIR_INODE);
  		if (err)
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
822
  			goto out;
399368372   Jaegeuk Kim   f2fs: introduce a...
823
  		goto retry_flush_dents;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
824
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
825
  	/*
e1c420452   arter97   f2fs: fix typo
826
  	 * POR: we should ensure that there are no dirty node pages
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
827
828
  	 * until finishing nat/sit flush.
  	 */
399368372   Jaegeuk Kim   f2fs: introduce a...
829
  retry_flush_nodes:
b3582c689   Chao Yu   f2fs: reduce comp...
830
  	down_write(&sbi->node_write);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
831
832
  
  	if (get_pages(sbi, F2FS_DIRTY_NODES)) {
b3582c689   Chao Yu   f2fs: reduce comp...
833
  		up_write(&sbi->node_write);
6d5a1495e   Chao Yu   f2fs: let user be...
834
835
  		err = sync_node_pages(sbi, 0, &wbc);
  		if (err) {
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
836
  			f2fs_unlock_all(sbi);
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
837
838
  			goto out;
  		}
399368372   Jaegeuk Kim   f2fs: introduce a...
839
  		goto retry_flush_nodes;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
840
  	}
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
841
  out:
c718379b6   Jaegeuk Kim   f2fs: give a chan...
842
  	blk_finish_plug(&plug);
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
843
  	return err;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
844
845
846
847
  }
  
  static void unblock_operations(struct f2fs_sb_info *sbi)
  {
b3582c689   Chao Yu   f2fs: reduce comp...
848
  	up_write(&sbi->node_write);
e479556bf   Gu Zheng   f2fs: use rw_sem ...
849
  	f2fs_unlock_all(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
850
  }
fb51b5ef9   Changman Lee   f2fs: cleanup wai...
851
852
853
854
855
856
857
858
859
860
861
862
863
864
  static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi)
  {
  	DEFINE_WAIT(wait);
  
  	for (;;) {
  		prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE);
  
  		if (!get_pages(sbi, F2FS_WRITEBACK))
  			break;
  
  		io_schedule();
  	}
  	finish_wait(&sbi->cp_wait, &wait);
  }
c34f42e2c   Chao Yu   f2fs: report erro...
865
  static int do_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
866
867
  {
  	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
cf2271e78   Jaegeuk Kim   f2fs: avoid retry...
868
  	struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
770418238   Huang Ying   f2fs: use nm_i->n...
869
  	struct f2fs_nm_info *nm_i = NM_I(sbi);
67298804f   Chao Yu   f2fs: introduce s...
870
  	unsigned long orphan_num = sbi->im[ORPHAN_INO].ino_num;
770418238   Huang Ying   f2fs: use nm_i->n...
871
  	nid_t last_nid = nm_i->next_scan_nid;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
872
  	block_t start_blk;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
873
  	unsigned int data_sum_blocks, orphan_blocks;
7e586fa02   Jaegeuk Kim   f2fs: fix crc end...
874
  	__u32 crc32 = 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
875
  	int i;
551414861   Wanpeng Li   f2fs: introduce m...
876
  	int cp_payload_blks = __cp_payload(sbi);
e90c2d285   Chao Yu   f2fs: invalidate ...
877
878
  	block_t discard_blk = NEXT_FREE_BLKADDR(sbi, curseg);
  	bool invalidate = false;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
879

1e87a78d9   Jaegeuk Kim   f2fs: avoid to co...
880
881
882
883
  	/*
  	 * This avoids to conduct wrong roll-forward operations and uses
  	 * metapages, so should be called prior to sync_meta_pages below.
  	 */
e90c2d285   Chao Yu   f2fs: invalidate ...
884
885
  	if (discard_next_dnode(sbi, discard_blk))
  		invalidate = true;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
886
887
  
  	/* Flush all the NAT/SIT pages */
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
888
  	while (get_pages(sbi, F2FS_DIRTY_META)) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
889
  		sync_meta_pages(sbi, META, LONG_MAX);
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
890
  		if (unlikely(f2fs_cp_error(sbi)))
c34f42e2c   Chao Yu   f2fs: report erro...
891
  			return -EIO;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
892
  	}
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
893
894
895
896
897
898
899
900
901
902
  
  	next_free_nid(sbi, &last_nid);
  
  	/*
  	 * modify checkpoint
  	 * version number is already updated
  	 */
  	ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi));
  	ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi));
  	ckpt->free_segment_count = cpu_to_le32(free_segments(sbi));
b5b822050   Chao Yu   f2fs: use macro f...
903
  	for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
904
905
906
907
908
909
910
  		ckpt->cur_node_segno[i] =
  			cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE));
  		ckpt->cur_node_blkoff[i] =
  			cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE));
  		ckpt->alloc_type[i + CURSEG_HOT_NODE] =
  				curseg_alloc_type(sbi, i + CURSEG_HOT_NODE);
  	}
b5b822050   Chao Yu   f2fs: use macro f...
911
  	for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
912
913
914
915
916
917
918
919
920
921
922
923
924
  		ckpt->cur_data_segno[i] =
  			cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA));
  		ckpt->cur_data_blkoff[i] =
  			cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA));
  		ckpt->alloc_type[i + CURSEG_HOT_DATA] =
  				curseg_alloc_type(sbi, i + CURSEG_HOT_DATA);
  	}
  
  	ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi));
  	ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi));
  	ckpt->next_free_nid = cpu_to_le32(last_nid);
  
  	/* 2 cp  + n data seg summary + orphan inode blocks */
3fa06d7bc   Chao Yu   f2fs: readahead c...
925
  	data_sum_blocks = npages_for_summary_flush(sbi, false);
b5b822050   Chao Yu   f2fs: use macro f...
926
  	if (data_sum_blocks < NR_CURSEG_DATA_TYPE)
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
927
  		set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
928
  	else
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
929
  		clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
930

67298804f   Chao Yu   f2fs: introduce s...
931
  	orphan_blocks = GET_ORPHAN_BLOCKS(orphan_num);
1dbe41521   Changman Lee   f2fs: large volum...
932
933
  	ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks +
  			orphan_blocks);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
934

119ee9144   Jaegeuk Kim   f2fs: split UMOUN...
935
  	if (__remain_node_summaries(cpc->reason))
b5b822050   Chao Yu   f2fs: use macro f...
936
  		ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS+
1dbe41521   Changman Lee   f2fs: large volum...
937
938
  				cp_payload_blks + data_sum_blocks +
  				orphan_blocks + NR_CURSEG_NODE_TYPE);
119ee9144   Jaegeuk Kim   f2fs: split UMOUN...
939
  	else
b5b822050   Chao Yu   f2fs: use macro f...
940
  		ckpt->cp_pack_total_block_count = cpu_to_le32(F2FS_CP_PACKS +
1dbe41521   Changman Lee   f2fs: large volum...
941
942
  				cp_payload_blks + data_sum_blocks +
  				orphan_blocks);
119ee9144   Jaegeuk Kim   f2fs: split UMOUN...
943
944
945
946
947
948
949
950
951
952
  
  	if (cpc->reason == CP_UMOUNT)
  		set_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
  	else
  		clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG);
  
  	if (cpc->reason == CP_FASTBOOT)
  		set_ckpt_flags(ckpt, CP_FASTBOOT_FLAG);
  	else
  		clear_ckpt_flags(ckpt, CP_FASTBOOT_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
953

67298804f   Chao Yu   f2fs: introduce s...
954
  	if (orphan_num)
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
955
  		set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
956
  	else
25ca923b2   Jaegeuk Kim   f2fs: fix endian ...
957
  		clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
958

caf0047e7   Chao Yu   f2fs: merge flags...
959
  	if (is_sbi_flag_set(sbi, SBI_NEED_FSCK))
2ae4c673e   Jaegeuk Kim   f2fs: retain inco...
960
  		set_ckpt_flags(ckpt, CP_FSCK_FLAG);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
961
962
963
964
965
  	/* update SIT/NAT bitmap */
  	get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP));
  	get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP));
  
  	crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset));
7e586fa02   Jaegeuk Kim   f2fs: fix crc end...
966
967
  	*((__le32 *)((unsigned char *)ckpt +
  				le32_to_cpu(ckpt->checksum_offset)))
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
968
969
970
  				= cpu_to_le32(crc32);
  
  	start_blk = __start_cp_addr(sbi);
a7230d16d   Jaegeuk Kim   f2fs: check end_i...
971
972
973
  	/* need to wait for end_io results */
  	wait_on_all_pages_writeback(sbi);
  	if (unlikely(f2fs_cp_error(sbi)))
c34f42e2c   Chao Yu   f2fs: report erro...
974
  		return -EIO;
a7230d16d   Jaegeuk Kim   f2fs: check end_i...
975

127e670ab   Jaegeuk Kim   f2fs: add checkpo...
976
  	/* write out checkpoint buffer at block 0 */
381722d2a   Chao Yu   f2fs: introduce u...
977
978
979
980
981
  	update_meta_page(sbi, ckpt, start_blk++);
  
  	for (i = 1; i < 1 + cp_payload_blks; i++)
  		update_meta_page(sbi, (char *)ckpt + i * F2FS_BLKSIZE,
  							start_blk++);
1dbe41521   Changman Lee   f2fs: large volum...
982

67298804f   Chao Yu   f2fs: introduce s...
983
  	if (orphan_num) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
984
985
986
987
988
989
  		write_orphan_inodes(sbi, start_blk);
  		start_blk += orphan_blocks;
  	}
  
  	write_data_summaries(sbi, start_blk);
  	start_blk += data_sum_blocks;
119ee9144   Jaegeuk Kim   f2fs: split UMOUN...
990
  	if (__remain_node_summaries(cpc->reason)) {
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
991
992
993
994
995
  		write_node_summaries(sbi, start_blk);
  		start_blk += NR_CURSEG_NODE_TYPE;
  	}
  
  	/* writeout checkpoint block */
381722d2a   Chao Yu   f2fs: introduce u...
996
  	update_meta_page(sbi, ckpt, start_blk);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
997
998
  
  	/* wait for previous submitted node/meta pages writeback */
fb51b5ef9   Changman Lee   f2fs: cleanup wai...
999
  	wait_on_all_pages_writeback(sbi);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1000

cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1001
  	if (unlikely(f2fs_cp_error(sbi)))
c34f42e2c   Chao Yu   f2fs: report erro...
1002
  		return -EIO;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1003

4ef51a8fc   Jaegeuk Kim   f2fs: introduce N...
1004
  	filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX);
9df27d982   Gu Zheng   f2fs: add help fu...
1005
  	filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1006
1007
1008
1009
1010
1011
  
  	/* update user_block_counts */
  	sbi->last_valid_block_count = sbi->total_valid_block_count;
  	sbi->alloc_valid_block_count = 0;
  
  	/* Here, we only have one bio having CP pack */
577e34951   Jaegeuk Kim   f2fs: prevent che...
1012
  	sync_meta_pages(sbi, META_FLUSH, LONG_MAX);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1013

6a8f8ca58   Jaegeuk Kim   f2fs: avoid race ...
1014
1015
  	/* wait for previous submitted meta pages writeback */
  	wait_on_all_pages_writeback(sbi);
e90c2d285   Chao Yu   f2fs: invalidate ...
1016
1017
1018
1019
1020
1021
1022
  	/*
  	 * invalidate meta page which is used temporarily for zeroing out
  	 * block at the end of warm node chain.
  	 */
  	if (invalidate)
  		invalidate_mapping_pages(META_MAPPING(sbi), discard_blk,
  								discard_blk);
a49324f12   Chao Yu   f2fs: rename {add...
1023
  	release_ino_entry(sbi);
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1024
1025
  
  	if (unlikely(f2fs_cp_error(sbi)))
c34f42e2c   Chao Yu   f2fs: report erro...
1026
  		return -EIO;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1027

836b5a635   Jaegeuk Kim   f2fs: issue disca...
1028
  	clear_prefree_segments(sbi, cpc);
caf0047e7   Chao Yu   f2fs: merge flags...
1029
  	clear_sbi_flag(sbi, SBI_IS_DIRTY);
c34f42e2c   Chao Yu   f2fs: report erro...
1030
1031
  
  	return 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1032
  }
0a8165d7c   Jaegeuk Kim   f2fs: adjust kern...
1033
  /*
e1c420452   arter97   f2fs: fix typo
1034
   * We guarantee that this checkpoint procedure will not fail.
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1035
   */
c34f42e2c   Chao Yu   f2fs: report erro...
1036
  int write_checkpoint(struct f2fs_sb_info *sbi, struct cp_control *cpc)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1037
1038
1039
  {
  	struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi);
  	unsigned long long ckpt_ver;
c34f42e2c   Chao Yu   f2fs: report erro...
1040
  	int err = 0;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1041

437275272   Jaegeuk Kim   f2fs: clarify and...
1042
  	mutex_lock(&sbi->cp_mutex);
8501017e5   Jaegeuk Kim   f2fs: check s_dir...
1043

caf0047e7   Chao Yu   f2fs: merge flags...
1044
  	if (!is_sbi_flag_set(sbi, SBI_IS_DIRTY) &&
a66cdd985   Jaegeuk Kim   f2fs: introduce d...
1045
1046
  		(cpc->reason == CP_FASTBOOT || cpc->reason == CP_SYNC ||
  		(cpc->reason == CP_DISCARD && !sbi->discard_blks)))
8501017e5   Jaegeuk Kim   f2fs: check s_dir...
1047
  		goto out;
c34f42e2c   Chao Yu   f2fs: report erro...
1048
1049
  	if (unlikely(f2fs_cp_error(sbi))) {
  		err = -EIO;
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1050
  		goto out;
c34f42e2c   Chao Yu   f2fs: report erro...
1051
1052
1053
  	}
  	if (f2fs_readonly(sbi->sb)) {
  		err = -EROFS;
11504a8e7   Jaegeuk Kim   f2fs: avoid write...
1054
  		goto out;
c34f42e2c   Chao Yu   f2fs: report erro...
1055
  	}
2bda542d5   Wanpeng Li   f2fs: fix block_o...
1056
1057
  
  	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "start block_ops");
c34f42e2c   Chao Yu   f2fs: report erro...
1058
1059
  	err = block_operations(sbi);
  	if (err)
cf779cab1   Jaegeuk Kim   f2fs: handle EIO ...
1060
  		goto out;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1061

75ab4cb83   Jaegeuk Kim   f2fs: introduce c...
1062
  	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish block_ops");
2af4bd6ca   Namjae Jeon   f2fs: add tracepo...
1063

458e6197c   Jaegeuk Kim   f2fs: refactor bi...
1064
1065
1066
  	f2fs_submit_merged_bio(sbi, DATA, WRITE);
  	f2fs_submit_merged_bio(sbi, NODE, WRITE);
  	f2fs_submit_merged_bio(sbi, META, WRITE);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1067
1068
1069
1070
1071
1072
  
  	/*
  	 * update checkpoint pack index
  	 * Increase the version number so that
  	 * SIT entries and seg summaries are written at correct place
  	 */
d71b5564c   Jaegeuk Kim   f2fs: introduce c...
1073
  	ckpt_ver = cur_cp_version(ckpt);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1074
1075
1076
1077
  	ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver);
  
  	/* write cached NAT/SIT entries to NAT/SIT area */
  	flush_nat_entries(sbi);
4b2fecc84   Jaegeuk Kim   f2fs: introduce F...
1078
  	flush_sit_entries(sbi, cpc);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1079

127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1080
  	/* unlock all the fs_lock[] in do_checkpoint() */
c34f42e2c   Chao Yu   f2fs: report erro...
1081
  	err = do_checkpoint(sbi, cpc);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1082
1083
  
  	unblock_operations(sbi);
942e0be62   Changman Lee   f2fs: show counts...
1084
  	stat_inc_cp_count(sbi->stat_info);
10027551c   Jaegeuk Kim   f2fs: pass checkp...
1085
1086
1087
1088
  
  	if (cpc->reason == CP_RECOVERY)
  		f2fs_msg(sbi->sb, KERN_NOTICE,
  			"checkpoint: version = %llx", ckpt_ver);
60b99b486   Jaegeuk Kim   f2fs: introduce a...
1089
1090
  
  	/* do checkpoint periodically */
6beceb542   Jaegeuk Kim   f2fs: introduce t...
1091
  	f2fs_update_time(sbi, CP_TIME);
55d1cdb25   Jaegeuk Kim   f2fs: relocate tr...
1092
  	trace_f2fs_write_checkpoint(sbi->sb, cpc->reason, "finish checkpoint");
8501017e5   Jaegeuk Kim   f2fs: check s_dir...
1093
1094
  out:
  	mutex_unlock(&sbi->cp_mutex);
c34f42e2c   Chao Yu   f2fs: report erro...
1095
  	return err;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1096
  }
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1097
  void init_ino_entry_info(struct f2fs_sb_info *sbi)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1098
  {
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1099
1100
1101
  	int i;
  
  	for (i = 0; i < MAX_INO_ENTRY; i++) {
67298804f   Chao Yu   f2fs: introduce s...
1102
1103
1104
1105
1106
1107
  		struct inode_management *im = &sbi->im[i];
  
  		INIT_RADIX_TREE(&im->ino_root, GFP_ATOMIC);
  		spin_lock_init(&im->ino_lock);
  		INIT_LIST_HEAD(&im->ino_list);
  		im->ino_num = 0;
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1108
  	}
b5b822050   Chao Yu   f2fs: use macro f...
1109
  	sbi->max_orphans = (sbi->blocks_per_seg - F2FS_CP_PACKS -
14b428177   Wanpeng Li   f2fs: fix max orp...
1110
1111
  			NR_CURSEG_TYPE - __cp_payload(sbi)) *
  				F2FS_ORPHANS_PER_BLOCK;
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1112
  }
6e6093a8f   Namjae Jeon   f2fs: add __init ...
1113
  int __init create_checkpoint_caches(void)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1114
  {
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1115
1116
1117
  	ino_entry_slab = f2fs_kmem_cache_create("f2fs_ino_entry",
  			sizeof(struct ino_entry));
  	if (!ino_entry_slab)
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1118
  		return -ENOMEM;
062920734   Chao Yu   f2fs: reuse inode...
1119
1120
  	inode_entry_slab = f2fs_kmem_cache_create("f2fs_inode_entry",
  			sizeof(struct inode_entry));
6bacf52fb   Jaegeuk Kim   f2fs: add unlikel...
1121
  	if (!inode_entry_slab) {
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1122
  		kmem_cache_destroy(ino_entry_slab);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1123
1124
1125
1126
1127
1128
1129
  		return -ENOMEM;
  	}
  	return 0;
  }
  
  void destroy_checkpoint_caches(void)
  {
6451e041c   Jaegeuk Kim   f2fs: add infra f...
1130
  	kmem_cache_destroy(ino_entry_slab);
127e670ab   Jaegeuk Kim   f2fs: add checkpo...
1131
1132
  	kmem_cache_destroy(inode_entry_slab);
  }