recovery.c 16.9 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
	F2FS_I(inode)->i_advise = raw->i_advise;
224
	F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
225

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

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

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

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

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

	while (1) {
		struct fsync_inode_entry *entry;

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

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

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

		if (!is_fsync_dnode(page))
			goto next;

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

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

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

300 301
		if (IS_INODE(page) && is_dent_dnode(page))
			entry->last_dentry = blkaddr;
302
next:
303 304 305 306 307 308 309 310 311 312 313
		/* 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;
		}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

409 410 411 412 413 414 415 416
	/*
	 * 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 已提交
417
	if (f2fs_get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
418 419 420
		goto out;

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

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

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

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

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

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

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

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

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

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

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

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

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

492 493 494 495 496 497
		/* 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 已提交
498
			f2fs_truncate_data_blocks_range(&dn, 1);
499 500 501
			continue;
		}

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

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

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

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

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

	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);
552
err:
553
	f2fs_put_dnode(&dn);
554
out:
C
Chris Fries 已提交
555
	f2fs_msg(sbi->sb, KERN_NOTICE,
556 557 558 559
		"recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
		inode->i_ino,
		file_keep_isize(inode) ? "keep" : "recover",
		recovered, err);
560
	return err;
561 562
}

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

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

	while (1) {
		struct fsync_inode_entry *entry;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

701 702 703 704 705 706 707 708 709
	if (need_writecp) {
		set_sbi_flag(sbi, SBI_IS_RECOVERED);

		if (!err) {
			struct cp_control cpc = {
				.reason = CP_RECOVERY,
			};
			err = f2fs_write_checkpoint(sbi, &cpc);
		}
710
	}
C
Chao Yu 已提交
711 712

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

721
	return ret ? ret: err;
722
}