recovery.c 16.8 KB
Newer Older
J
Jaegeuk Kim 已提交
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
 * fs/f2fs/recovery.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 "f2fs.h"
#include "node.h"
#include "segment.h"

17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
/*
 * Roll forward recovery scenarios.
 *
 * [Term] F: fsync_mark, D: dentry_mark
 *
 * 1. inode(x) | CP | inode(x) | dnode(F)
 * -> Update the latest inode(x).
 *
 * 2. inode(x) | CP | inode(F) | dnode(F)
 * -> No problem.
 *
 * 3. inode(x) | CP | dnode(F) | inode(x)
 * -> Recover to the latest dnode(F), and drop the last inode(x)
 *
 * 4. inode(x) | CP | dnode(F) | inode(F)
 * -> No problem.
 *
 * 5. CP | inode(x) | dnode(F)
 * -> The inode(DF) was missing. Should drop this dnode(F).
 *
 * 6. CP | inode(DF) | dnode(F)
 * -> No problem.
 *
 * 7. CP | dnode(F) | inode(DF)
 * -> If f2fs_iget fails, then goto next to find inode(DF).
 *
 * 8. CP | dnode(F) | inode(x)
 * -> If f2fs_iget fails, then goto next to find inode(DF).
 *    But it will fail due to no inode(DF).
 */

48 49
static struct kmem_cache *fsync_entry_slab;

C
Chao Yu 已提交
50
bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi)
51
{
52 53 54
	s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count);

	if (sbi->last_valid_block_count + nalloc > sbi->user_block_count)
55 56 57 58 59 60 61 62 63
		return false;
	return true;
}

static struct fsync_inode_entry *get_fsync_inode(struct list_head *head,
								nid_t ino)
{
	struct fsync_inode_entry *entry;

64
	list_for_each_entry(entry, head, list)
65 66
		if (entry->inode->i_ino == ino)
			return entry;
67

68 69 70
	return NULL;
}

71
static struct fsync_inode_entry *add_fsync_inode(struct f2fs_sb_info *sbi,
C
Chao Yu 已提交
72
			struct list_head *head, nid_t ino, bool quota_inode)
73
{
74
	struct inode *inode;
75
	struct fsync_inode_entry *entry;
C
Chao Yu 已提交
76
	int err;
77

78
	inode = f2fs_iget_retry(sbi->sb, ino);
79 80 81
	if (IS_ERR(inode))
		return ERR_CAST(inode);

C
Chao Yu 已提交
82 83 84 85 86 87 88 89 90 91
	err = dquot_initialize(inode);
	if (err)
		goto err_out;

	if (quota_inode) {
		err = dquot_alloc_inode(inode);
		if (err)
			goto err_out;
	}

92
	entry = f2fs_kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
93 94 95 96
	entry->inode = inode;
	list_add_tail(&entry->list, head);

	return entry;
C
Chao Yu 已提交
97 98 99
err_out:
	iput(inode);
	return ERR_PTR(err);
100 101 102 103 104 105 106 107 108
}

static void del_fsync_inode(struct fsync_inode_entry *entry)
{
	iput(entry->inode);
	list_del(&entry->list);
	kmem_cache_free(fsync_entry_slab, entry);
}

C
Chao Yu 已提交
109 110
static int recover_dentry(struct inode *inode, struct page *ipage,
						struct list_head *dir_list)
111
{
112
	struct f2fs_inode *raw_inode = F2FS_INODE(ipage);
113
	nid_t pino = le32_to_cpu(raw_inode->i_pino);
J
Jaegeuk Kim 已提交
114
	struct f2fs_dir_entry *de;
115
	struct fscrypt_name fname;
116
	struct page *page;
J
Jaegeuk Kim 已提交
117
	struct inode *dir, *einode;
C
Chao Yu 已提交
118
	struct fsync_inode_entry *entry;
119
	int err = 0;
120
	char *name;
121

C
Chao Yu 已提交
122 123
	entry = get_fsync_inode(dir_list, pino);
	if (!entry) {
C
Chao Yu 已提交
124 125
		entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
							pino, false);
126 127 128
		if (IS_ERR(entry)) {
			dir = ERR_CAST(entry);
			err = PTR_ERR(entry);
C
Chao Yu 已提交
129 130
			goto out;
		}
131 132
	}

C
Chao Yu 已提交
133 134
	dir = entry->inode;

135 136 137
	memset(&fname, 0, sizeof(struct fscrypt_name));
	fname.disk_name.len = le32_to_cpu(raw_inode->i_namelen);
	fname.disk_name.name = raw_inode->i_name;
138

139
	if (unlikely(fname.disk_name.len > F2FS_NAME_LEN)) {
140 141
		WARN_ON(1);
		err = -ENAMETOOLONG;
C
Chao Yu 已提交
142
		goto out;
143
	}
J
Jaegeuk Kim 已提交
144
retry:
145
	de = __f2fs_find_entry(dir, &fname, &page);
146
	if (de && inode->i_ino == le32_to_cpu(de->ino))
147
		goto out_put;
148

J
Jaegeuk Kim 已提交
149
	if (de) {
150
		einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino));
J
Jaegeuk Kim 已提交
151 152
		if (IS_ERR(einode)) {
			WARN_ON(1);
153 154
			err = PTR_ERR(einode);
			if (err == -ENOENT)
J
Jaegeuk Kim 已提交
155
				err = -EEXIST;
156
			goto out_put;
157
		}
C
Chao Yu 已提交
158 159 160 161

		err = dquot_initialize(einode);
		if (err) {
			iput(einode);
162
			goto out_put;
C
Chao Yu 已提交
163 164
		}

C
Chao Yu 已提交
165
		err = f2fs_acquire_orphan_inode(F2FS_I_SB(inode));
166 167
		if (err) {
			iput(einode);
168
			goto out_put;
J
Jaegeuk Kim 已提交
169
		}
170
		f2fs_delete_entry(de, page, dir, einode);
J
Jaegeuk Kim 已提交
171 172
		iput(einode);
		goto retry;
173 174 175
	} else if (IS_ERR(page)) {
		err = PTR_ERR(page);
	} else {
C
Chao Yu 已提交
176
		err = f2fs_add_dentry(dir, &fname, inode,
177
					inode->i_ino, inode->i_mode);
178
	}
179 180
	if (err == -ENOMEM)
		goto retry;
181 182
	goto out;

183
out_put:
184
	f2fs_put_page(page, 0);
185
out:
186 187 188 189
	if (file_enc_name(inode))
		name = "<encrypted>";
	else
		name = raw_inode->i_name;
C
Chris Fries 已提交
190 191
	f2fs_msg(inode->i_sb, KERN_NOTICE,
			"%s: ino = %x, name = %s, dir = %lx, err = %d",
192
			__func__, ino_of_node(ipage), name,
D
Dan Carpenter 已提交
193
			IS_ERR(dir) ? 0 : dir->i_ino, err);
194 195 196
	return err;
}

J
Jaegeuk Kim 已提交
197 198 199 200 201 202 203 204 205 206 207 208
static void recover_inline_flags(struct inode *inode, struct f2fs_inode *ri)
{
	if (ri->i_inline & F2FS_PIN_FILE)
		set_inode_flag(inode, FI_PIN_FILE);
	else
		clear_inode_flag(inode, FI_PIN_FILE);
	if (ri->i_inline & F2FS_DATA_EXIST)
		set_inode_flag(inode, FI_DATA_EXIST);
	else
		clear_inode_flag(inode, FI_DATA_EXIST);
}

209
static void recover_inode(struct inode *inode, struct page *page)
210
{
211
	struct f2fs_inode *raw = F2FS_INODE(page);
212
	char *name;
213 214

	inode->i_mode = le16_to_cpu(raw->i_mode);
215
	f2fs_i_size_write(inode, le64_to_cpu(raw->i_size));
C
Chao Yu 已提交
216
	inode->i_atime.tv_sec = le64_to_cpu(raw->i_atime);
217 218
	inode->i_ctime.tv_sec = le64_to_cpu(raw->i_ctime);
	inode->i_mtime.tv_sec = le64_to_cpu(raw->i_mtime);
C
Chao Yu 已提交
219
	inode->i_atime.tv_nsec = le32_to_cpu(raw->i_atime_nsec);
220 221
	inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
	inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
222

223 224
	F2FS_I(inode)->i_advise = raw->i_advise;

J
Jaegeuk Kim 已提交
225 226
	recover_inline_flags(inode, raw);

227 228 229 230 231
	if (file_enc_name(inode))
		name = "<encrypted>";
	else
		name = F2FS_INODE(page)->i_name;

J
Jaegeuk Kim 已提交
232 233 234
	f2fs_msg(inode->i_sb, KERN_NOTICE,
		"recover_inode: ino = %x, name = %s, inline = %x",
			ino_of_node(page), name, raw->i_inline);
235 236
}

237 238
static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
				bool check_only)
239 240
{
	struct curseg_info *curseg;
241
	struct page *page = NULL;
242
	block_t blkaddr;
243
	unsigned int loop_cnt = 0;
244 245
	unsigned int free_blocks = MAIN_SEGS(sbi) * sbi->blocks_per_seg -
						valid_user_blocks(sbi);
246 247 248 249
	int err = 0;

	/* get node pages in the current segment */
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
250
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
251 252 253 254

	while (1) {
		struct fsync_inode_entry *entry;

255
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
256
			return 0;
257

C
Chao Yu 已提交
258
		page = f2fs_get_tmp_page(sbi, blkaddr);
259 260 261 262
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
263

264
		if (!is_recoverable_dnode(page))
265
			break;
266 267 268 269 270

		if (!is_fsync_dnode(page))
			goto next;

		entry = get_fsync_inode(head, ino_of_node(page));
271
		if (!entry) {
C
Chao Yu 已提交
272 273
			bool quota_inode = false;

274 275
			if (!check_only &&
					IS_INODE(page) && is_dent_dnode(page)) {
C
Chao Yu 已提交
276
				err = f2fs_recover_inode_page(sbi, page);
277
				if (err)
278
					break;
C
Chao Yu 已提交
279
				quota_inode = true;
280 281
			}

282 283 284 285
			/*
			 * CP | dnode(F) | inode(DF)
			 * For this case, we should not give up now.
			 */
C
Chao Yu 已提交
286 287
			entry = add_fsync_inode(sbi, head, ino_of_node(page),
								quota_inode);
288 289
			if (IS_ERR(entry)) {
				err = PTR_ERR(entry);
290 291
				if (err == -ENOENT) {
					err = 0;
292
					goto next;
293
				}
294
				break;
295 296
			}
		}
J
Jaegeuk Kim 已提交
297 298
		entry->blkaddr = blkaddr;

299 300
		if (IS_INODE(page) && is_dent_dnode(page))
			entry->last_dentry = blkaddr;
301
next:
302 303 304 305 306 307 308 309 310 311 312
		/* sanity check in order to detect looped node chain */
		if (++loop_cnt >= free_blocks ||
			blkaddr == next_blkaddr_of_node(page)) {
			f2fs_msg(sbi->sb, KERN_NOTICE,
				"%s: detect looped node chain, "
				"blkaddr:%u, next:%u",
				__func__, blkaddr, next_blkaddr_of_node(page));
			err = -EINVAL;
			break;
		}

313 314
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
315
		f2fs_put_page(page, 1);
316

C
Chao Yu 已提交
317
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
318
	}
319
	f2fs_put_page(page, 1);
320 321 322
	return err;
}

323
static void destroy_fsync_dnodes(struct list_head *head)
324
{
325 326
	struct fsync_inode_entry *entry, *tmp;

327 328
	list_for_each_entry_safe(entry, tmp, head, list)
		del_fsync_inode(entry);
329 330
}

331
static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
332
			block_t blkaddr, struct dnode_of_data *dn)
333 334 335
{
	struct seg_entry *sentry;
	unsigned int segno = GET_SEGNO(sbi, blkaddr);
J
Jaegeuk Kim 已提交
336
	unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
J
Jaegeuk Kim 已提交
337
	struct f2fs_summary_block *sum_node;
338
	struct f2fs_summary sum;
J
Jaegeuk Kim 已提交
339
	struct page *sum_page, *node_page;
340
	struct dnode_of_data tdn = *dn;
341
	nid_t ino, nid;
342
	struct inode *inode;
343
	unsigned int offset;
344 345 346 347 348
	block_t bidx;
	int i;

	sentry = get_seg_entry(sbi, segno);
	if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
349
		return 0;
350 351

	/* Get the previous summary */
352
	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
353 354 355
		struct curseg_info *curseg = CURSEG_I(sbi, i);
		if (curseg->segno == segno) {
			sum = curseg->sum_blk->entries[blkoff];
J
Jaegeuk Kim 已提交
356
			goto got_it;
357 358 359
		}
	}

C
Chao Yu 已提交
360
	sum_page = f2fs_get_sum_page(sbi, segno);
J
Jaegeuk Kim 已提交
361 362 363 364
	sum_node = (struct f2fs_summary_block *)page_address(sum_page);
	sum = sum_node->entries[blkoff];
	f2fs_put_page(sum_page, 1);
got_it:
365 366 367 368
	/* Use the locked dnode page and inode */
	nid = le32_to_cpu(sum.nid);
	if (dn->inode->i_ino == nid) {
		tdn.nid = nid;
369 370
		if (!dn->inode_page_locked)
			lock_page(dn->inode_page);
371
		tdn.node_page = dn->inode_page;
372
		tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
373
		goto truncate_out;
374
	} else if (dn->nid == nid) {
375
		tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
376
		goto truncate_out;
377 378
	}

379
	/* Get the node page */
C
Chao Yu 已提交
380
	node_page = f2fs_get_node_page(sbi, nid);
381 382
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);
383 384

	offset = ofs_of_node(node_page);
385 386 387
	ino = ino_of_node(node_page);
	f2fs_put_page(node_page, 1);

388
	if (ino != dn->inode->i_ino) {
C
Chao Yu 已提交
389 390
		int ret;

391
		/* Deallocate previous index in the node page */
392
		inode = f2fs_iget_retry(sbi->sb, ino);
393 394
		if (IS_ERR(inode))
			return PTR_ERR(inode);
C
Chao Yu 已提交
395 396 397 398 399 400

		ret = dquot_initialize(inode);
		if (ret) {
			iput(inode);
			return ret;
		}
401 402 403
	} else {
		inode = dn->inode;
	}
404

C
Chao Yu 已提交
405 406
	bidx = f2fs_start_bidx_of_node(offset, inode) +
				le16_to_cpu(sum.ofs_in_node);
407

408 409 410 411 412 413 414 415
	/*
	 * if inode page is locked, unlock temporarily, but its reference
	 * count keeps alive.
	 */
	if (ino == dn->inode->i_ino && dn->inode_page_locked)
		unlock_page(dn->inode_page);

	set_new_dnode(&tdn, inode, NULL, NULL, 0);
C
Chao Yu 已提交
416
	if (f2fs_get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
417 418 419
		goto out;

	if (tdn.data_blkaddr == blkaddr)
C
Chao Yu 已提交
420
		f2fs_truncate_data_blocks_range(&tdn, 1);
421 422 423 424

	f2fs_put_dnode(&tdn);
out:
	if (ino != dn->inode->i_ino)
425
		iput(inode);
426 427 428 429 430
	else if (dn->inode_page_locked)
		lock_page(dn->inode_page);
	return 0;

truncate_out:
431 432
	if (datablock_addr(tdn.inode, tdn.node_page,
					tdn.ofs_in_node) == blkaddr)
C
Chao Yu 已提交
433
		f2fs_truncate_data_blocks_range(&tdn, 1);
434 435
	if (dn->inode->i_ino == nid && !dn->inode_page_locked)
		unlock_page(dn->inode_page);
436
	return 0;
437 438
}

439
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
S
Sheng Yong 已提交
440
					struct page *page)
441 442 443
{
	struct dnode_of_data dn;
	struct node_info ni;
444
	unsigned int start, end;
445
	int err = 0, recovered = 0;
446

447 448
	/* step 1: recover xattr */
	if (IS_INODE(page)) {
C
Chao Yu 已提交
449
		f2fs_recover_inline_xattr(inode, page);
450
	} else if (f2fs_has_xattr_block(ofs_of_node(page))) {
C
Chao Yu 已提交
451
		err = f2fs_recover_xattr_data(inode, page);
452 453
		if (!err)
			recovered++;
454
		goto out;
455
	}
456

457
	/* step 2: recover inline data */
C
Chao Yu 已提交
458
	if (f2fs_recover_inline_data(inode, page))
459 460
		goto out;

461
	/* step 3: recover data indices */
C
Chao Yu 已提交
462
	start = f2fs_start_bidx_of_node(ofs_of_node(page), inode);
463
	end = start + ADDRS_PER_PAGE(page, inode);
464 465

	set_new_dnode(&dn, inode, NULL, NULL, 0);
466
retry_dn:
C
Chao Yu 已提交
467
	err = f2fs_get_dnode_of_data(&dn, start, ALLOC_NODE);
468 469 470 471 472
	if (err) {
		if (err == -ENOMEM) {
			congestion_wait(BLK_RW_ASYNC, HZ/50);
			goto retry_dn;
		}
473
		goto out;
474
	}
475

476
	f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
477

478 479 480 481
	err = f2fs_get_node_info(sbi, dn.nid, &ni);
	if (err)
		goto err;

482 483
	f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
	f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page));
484

485
	for (; start < end; start++, dn.ofs_in_node++) {
486 487
		block_t src, dest;

488 489
		src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
		dest = datablock_addr(dn.inode, page, dn.ofs_in_node);
490

491 492 493 494 495 496
		/* skip recovering if dest is the same as src */
		if (src == dest)
			continue;

		/* dest is invalid, just invalidate src block */
		if (dest == NULL_ADDR) {
C
Chao Yu 已提交
497
			f2fs_truncate_data_blocks_range(&dn, 1);
498 499 500
			continue;
		}

501
		if (!file_keep_isize(inode) &&
502 503 504
			(i_size_read(inode) <= ((loff_t)start << PAGE_SHIFT)))
			f2fs_i_size_write(inode,
				(loff_t)(start + 1) << PAGE_SHIFT);
505

506 507 508 509 510
		/*
		 * dest is reserved block, invalidate src block
		 * and then reserve one new block in dnode page.
		 */
		if (dest == NEW_ADDR) {
C
Chao Yu 已提交
511 512
			f2fs_truncate_data_blocks_range(&dn, 1);
			f2fs_reserve_new_block(&dn);
513 514 515 516
			continue;
		}

		/* dest is valid block, try to recover from src to dest */
517
		if (f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
518

519
			if (src == NULL_ADDR) {
C
Chao Yu 已提交
520
				err = f2fs_reserve_new_block(&dn);
521 522
				while (err &&
				       IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION))
C
Chao Yu 已提交
523
					err = f2fs_reserve_new_block(&dn);
524
				/* We should not get -ENOSPC */
525
				f2fs_bug_on(sbi, err);
526 527
				if (err)
					goto err;
528
			}
529
retry_prev:
530
			/* Check the previous node page having this index */
531
			err = check_index_in_prev_nodes(sbi, dest, &dn);
532 533 534 535 536
			if (err) {
				if (err == -ENOMEM) {
					congestion_wait(BLK_RW_ASYNC, HZ/50);
					goto retry_prev;
				}
537
				goto err;
538
			}
539 540

			/* write dummy data page */
541
			f2fs_replace_block(sbi, &dn, src, dest,
542
						ni.version, false, false);
543
			recovered++;
544 545 546 547 548 549 550
		}
	}

	copy_node_footer(dn.node_page, page);
	fill_node_footer(dn.node_page, dn.nid, ni.ino,
					ofs_of_node(page), false);
	set_page_dirty(dn.node_page);
551
err:
552
	f2fs_put_dnode(&dn);
553
out:
C
Chris Fries 已提交
554
	f2fs_msg(sbi->sb, KERN_NOTICE,
555 556 557 558
		"recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
		inode->i_ino,
		file_keep_isize(inode) ? "keep" : "recover",
		recovered, err);
559
	return err;
560 561
}

C
Chao Yu 已提交
562 563
static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
						struct list_head *dir_list)
564 565
{
	struct curseg_info *curseg;
566
	struct page *page = NULL;
567
	int err = 0;
568 569 570
	block_t blkaddr;

	/* get node pages in the current segment */
C
Chao Yu 已提交
571
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
572 573 574 575 576
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);

	while (1) {
		struct fsync_inode_entry *entry;

577
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
578
			break;
579

C
Chao Yu 已提交
580
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
581

C
Chao Yu 已提交
582
		page = f2fs_get_tmp_page(sbi, blkaddr);
583 584 585 586
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
587

588
		if (!is_recoverable_dnode(page)) {
589
			f2fs_put_page(page, 1);
590
			break;
591
		}
592

C
Chao Yu 已提交
593
		entry = get_fsync_inode(inode_list, ino_of_node(page));
594 595
		if (!entry)
			goto next;
596 597 598
		/*
		 * inode(x) | CP | inode(x) | dnode(F)
		 * In this case, we can lose the latest inode(x).
599
		 * So, call recover_inode for the inode update.
600
		 */
601
		if (IS_INODE(page))
602 603
			recover_inode(entry->inode, page);
		if (entry->last_dentry == blkaddr) {
C
Chao Yu 已提交
604
			err = recover_dentry(entry->inode, page, dir_list);
605 606 607 608 609
			if (err) {
				f2fs_put_page(page, 1);
				break;
			}
		}
S
Sheng Yong 已提交
610
		err = do_recover_data(sbi, entry->inode, page);
611 612
		if (err) {
			f2fs_put_page(page, 1);
613
			break;
614
		}
615

616 617
		if (entry->blkaddr == blkaddr)
			del_fsync_inode(entry);
618 619 620
next:
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
621
		f2fs_put_page(page, 1);
622
	}
623
	if (!err)
C
Chao Yu 已提交
624
		f2fs_allocate_new_segments(sbi);
625
	return err;
626 627
}

C
Chao Yu 已提交
628
int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
629 630
{
	struct list_head inode_list;
C
Chao Yu 已提交
631
	struct list_head dir_list;
632
	int err;
633
	int ret = 0;
C
Chao Yu 已提交
634
	unsigned long s_flags = sbi->sb->s_flags;
H
Haicheng Li 已提交
635
	bool need_writecp = false;
J
Jaegeuk Kim 已提交
636 637 638
#ifdef CONFIG_QUOTA
	int quota_enabled;
#endif
639

640
	if (s_flags & SB_RDONLY) {
641 642
		f2fs_msg(sbi->sb, KERN_INFO,
				"recover fsync data on readonly fs");
643
		sbi->sb->s_flags &= ~SB_RDONLY;
C
Chao Yu 已提交
644 645 646 647
	}

#ifdef CONFIG_QUOTA
	/* Needed for iput() to work correctly and not trash data */
648
	sbi->sb->s_flags |= SB_ACTIVE;
C
Chao Yu 已提交
649
	/* Turn on quotas so that they are updated correctly */
650
	quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY);
C
Chao Yu 已提交
651 652
#endif

653
	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
654
			sizeof(struct fsync_inode_entry));
C
Chao Yu 已提交
655 656 657 658
	if (!fsync_entry_slab) {
		err = -ENOMEM;
		goto out;
	}
659 660

	INIT_LIST_HEAD(&inode_list);
C
Chao Yu 已提交
661
	INIT_LIST_HEAD(&dir_list);
662

663 664 665
	/* prevent checkpoint */
	mutex_lock(&sbi->cp_mutex);

666
	/* step #1: find fsynced inode numbers */
667
	err = find_fsync_dnodes(sbi, &inode_list, check_only);
668
	if (err || list_empty(&inode_list))
C
Chao Yu 已提交
669
		goto skip;
670

671 672
	if (check_only) {
		ret = 1;
C
Chao Yu 已提交
673
		goto skip;
674
	}
675

H
Haicheng Li 已提交
676
	need_writecp = true;
677

678
	/* step #2: recover data */
C
Chao Yu 已提交
679
	err = recover_data(sbi, &inode_list, &dir_list);
680
	if (!err)
681
		f2fs_bug_on(sbi, !list_empty(&inode_list));
C
Chao Yu 已提交
682
skip:
683
	destroy_fsync_dnodes(&inode_list);
684

685 686
	/* truncate meta pages to be used by the recovery */
	truncate_inode_pages_range(META_MAPPING(sbi),
687
			(loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1);
688

689 690 691 692 693
	if (err) {
		truncate_inode_pages_final(NODE_MAPPING(sbi));
		truncate_inode_pages_final(META_MAPPING(sbi));
	}

694
	clear_sbi_flag(sbi, SBI_POR_DOING);
695 696
	mutex_unlock(&sbi->cp_mutex);

697 698 699
	/* let's drop all the directory inodes for clean checkpoint */
	destroy_fsync_dnodes(&dir_list);

700
	if (!err && need_writecp) {
701
		struct cp_control cpc = {
702
			.reason = CP_RECOVERY,
703
		};
C
Chao Yu 已提交
704
		err = f2fs_write_checkpoint(sbi, &cpc);
705
	}
C
Chao Yu 已提交
706 707

	kmem_cache_destroy(fsync_entry_slab);
C
Chao Yu 已提交
708 709 710
out:
#ifdef CONFIG_QUOTA
	/* Turn quotas off */
J
Jaegeuk Kim 已提交
711 712
	if (quota_enabled)
		f2fs_quota_off_umount(sbi->sb);
C
Chao Yu 已提交
713
#endif
714
	sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */
C
Chao Yu 已提交
715

716
	return ret ? ret: err;
717
}