recovery.c 17.5 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
static void del_fsync_inode(struct fsync_inode_entry *entry, int drop)
103
{
104 105 106 107
	if (drop) {
		/* inode should not be recovered, drop it */
		f2fs_inode_synced(entry->inode);
	}
108 109 110 111 112
	iput(entry->inode);
	list_del(&entry->list);
	kmem_cache_free(fsync_entry_slab, entry);
}

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

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

C
Chao Yu 已提交
137 138
	dir = entry->inode;

139 140 141
	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;
142

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

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

		err = dquot_initialize(einode);
		if (err) {
			iput(einode);
166
			goto out_put;
C
Chao Yu 已提交
167 168
		}

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

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

J
Jaegeuk Kim 已提交
201 202 203 204 205 206 207 208 209 210 211 212
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);
}

213
static void recover_inode(struct inode *inode, struct page *page)
214
{
215
	struct f2fs_inode *raw = F2FS_INODE(page);
216
	char *name;
217 218

	inode->i_mode = le16_to_cpu(raw->i_mode);
219
	f2fs_i_size_write(inode, le64_to_cpu(raw->i_size));
C
Chao Yu 已提交
220
	inode->i_atime.tv_sec = le64_to_cpu(raw->i_atime);
221 222
	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 已提交
223
	inode->i_atime.tv_nsec = le32_to_cpu(raw->i_atime_nsec);
224 225
	inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
	inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
226

227
	F2FS_I(inode)->i_advise = raw->i_advise;
228
	F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
229

J
Jaegeuk Kim 已提交
230 231
	recover_inline_flags(inode, raw);

232 233 234 235 236
	if (file_enc_name(inode))
		name = "<encrypted>";
	else
		name = F2FS_INODE(page)->i_name;

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

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

	/* get node pages in the current segment */
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
255
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
256 257 258 259

	while (1) {
		struct fsync_inode_entry *entry;

260
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
261
			return 0;
262

C
Chao Yu 已提交
263
		page = f2fs_get_tmp_page(sbi, blkaddr);
264 265 266 267
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
268

269
		if (!is_recoverable_dnode(page))
270
			break;
271 272 273 274 275

		if (!is_fsync_dnode(page))
			goto next;

		entry = get_fsync_inode(head, ino_of_node(page));
276
		if (!entry) {
C
Chao Yu 已提交
277 278
			bool quota_inode = false;

279 280
			if (!check_only &&
					IS_INODE(page) && is_dent_dnode(page)) {
C
Chao Yu 已提交
281
				err = f2fs_recover_inode_page(sbi, page);
282
				if (err)
283
					break;
C
Chao Yu 已提交
284
				quota_inode = true;
285 286
			}

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

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

318 319
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
320
		f2fs_put_page(page, 1);
321

C
Chao Yu 已提交
322
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
323
	}
324
	f2fs_put_page(page, 1);
325 326 327
	return err;
}

328
static void destroy_fsync_dnodes(struct list_head *head, int drop)
329
{
330 331
	struct fsync_inode_entry *entry, *tmp;

332
	list_for_each_entry_safe(entry, tmp, head, list)
333
		del_fsync_inode(entry, drop);
334 335
}

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

	sentry = get_seg_entry(sbi, segno);
	if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
354
		return 0;
355 356

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

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

384
	/* Get the node page */
C
Chao Yu 已提交
385
	node_page = f2fs_get_node_page(sbi, nid);
386 387
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);
388 389

	offset = ofs_of_node(node_page);
390 391 392
	ino = ino_of_node(node_page);
	f2fs_put_page(node_page, 1);

393
	if (ino != dn->inode->i_ino) {
C
Chao Yu 已提交
394 395
		int ret;

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

		ret = dquot_initialize(inode);
		if (ret) {
			iput(inode);
			return ret;
		}
406 407 408
	} else {
		inode = dn->inode;
	}
409

C
Chao Yu 已提交
410 411
	bidx = f2fs_start_bidx_of_node(offset, inode) +
				le16_to_cpu(sum.ofs_in_node);
412

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

	if (tdn.data_blkaddr == blkaddr)
C
Chao Yu 已提交
425
		f2fs_truncate_data_blocks_range(&tdn, 1);
426 427 428 429

	f2fs_put_dnode(&tdn);
out:
	if (ino != dn->inode->i_ino)
430
		iput(inode);
431 432 433 434 435
	else if (dn->inode_page_locked)
		lock_page(dn->inode_page);
	return 0;

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

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

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

462
	/* step 2: recover inline data */
C
Chao Yu 已提交
463
	if (f2fs_recover_inline_data(inode, page))
464 465
		goto out;

466
	/* step 3: recover data indices */
C
Chao Yu 已提交
467
	start = f2fs_start_bidx_of_node(ofs_of_node(page), inode);
468
	end = start + ADDRS_PER_PAGE(page, inode);
469 470

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

481
	f2fs_wait_on_page_writeback(dn.node_page, NODE, true);
482

483 484 485 486
	err = f2fs_get_node_info(sbi, dn.nid, &ni);
	if (err)
		goto err;

487
	f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
488 489 490 491 492 493

	if (ofs_of_node(dn.node_page) != ofs_of_node(page)) {
		f2fs_msg(sbi->sb, KERN_WARNING,
			"Inconsistent ofs_of_node, ino:%lu, ofs:%u, %u",
			inode->i_ino, ofs_of_node(dn.node_page),
			ofs_of_node(page));
C
Chao Yu 已提交
494
		err = -EFSCORRUPTED;
495 496
		goto err;
	}
497

498
	for (; start < end; start++, dn.ofs_in_node++) {
499 500
		block_t src, dest;

501 502
		src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
		dest = datablock_addr(dn.inode, page, dn.ofs_in_node);
503

504 505 506 507 508 509
		/* 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 已提交
510
			f2fs_truncate_data_blocks_range(&dn, 1);
511 512 513
			continue;
		}

514
		if (!file_keep_isize(inode) &&
515 516 517
			(i_size_read(inode) <= ((loff_t)start << PAGE_SHIFT)))
			f2fs_i_size_write(inode,
				(loff_t)(start + 1) << PAGE_SHIFT);
518

519 520 521 522 523
		/*
		 * dest is reserved block, invalidate src block
		 * and then reserve one new block in dnode page.
		 */
		if (dest == NEW_ADDR) {
C
Chao Yu 已提交
524 525
			f2fs_truncate_data_blocks_range(&dn, 1);
			f2fs_reserve_new_block(&dn);
526 527 528 529
			continue;
		}

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

532
			if (src == NULL_ADDR) {
C
Chao Yu 已提交
533
				err = f2fs_reserve_new_block(&dn);
534 535
				while (err &&
				       IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION))
C
Chao Yu 已提交
536
					err = f2fs_reserve_new_block(&dn);
537
				/* We should not get -ENOSPC */
538
				f2fs_bug_on(sbi, err);
539 540
				if (err)
					goto err;
541
			}
542
retry_prev:
543
			/* Check the previous node page having this index */
544
			err = check_index_in_prev_nodes(sbi, dest, &dn);
545 546 547 548 549
			if (err) {
				if (err == -ENOMEM) {
					congestion_wait(BLK_RW_ASYNC, HZ/50);
					goto retry_prev;
				}
550
				goto err;
551
			}
552 553

			/* write dummy data page */
554
			f2fs_replace_block(sbi, &dn, src, dest,
555
						ni.version, false, false);
556
			recovered++;
557 558 559 560 561 562 563
		}
	}

	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);
564
err:
565
	f2fs_put_dnode(&dn);
566
out:
C
Chris Fries 已提交
567
	f2fs_msg(sbi->sb, KERN_NOTICE,
568 569 570 571
		"recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
		inode->i_ino,
		file_keep_isize(inode) ? "keep" : "recover",
		recovered, err);
572
	return err;
573 574
}

C
Chao Yu 已提交
575
static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
576
		struct list_head *tmp_inode_list, struct list_head *dir_list)
577 578
{
	struct curseg_info *curseg;
579
	struct page *page = NULL;
580
	int err = 0;
581 582 583
	block_t blkaddr;

	/* get node pages in the current segment */
C
Chao Yu 已提交
584
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
585 586 587 588 589
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);

	while (1) {
		struct fsync_inode_entry *entry;

590
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
591
			break;
592

C
Chao Yu 已提交
593
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
594

C
Chao Yu 已提交
595
		page = f2fs_get_tmp_page(sbi, blkaddr);
596 597 598 599
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
600

601
		if (!is_recoverable_dnode(page)) {
602
			f2fs_put_page(page, 1);
603
			break;
604
		}
605

C
Chao Yu 已提交
606
		entry = get_fsync_inode(inode_list, ino_of_node(page));
607 608
		if (!entry)
			goto next;
609 610 611
		/*
		 * inode(x) | CP | inode(x) | dnode(F)
		 * In this case, we can lose the latest inode(x).
612
		 * So, call recover_inode for the inode update.
613
		 */
614
		if (IS_INODE(page))
615 616
			recover_inode(entry->inode, page);
		if (entry->last_dentry == blkaddr) {
C
Chao Yu 已提交
617
			err = recover_dentry(entry->inode, page, dir_list);
618 619 620 621 622
			if (err) {
				f2fs_put_page(page, 1);
				break;
			}
		}
S
Sheng Yong 已提交
623
		err = do_recover_data(sbi, entry->inode, page);
624 625
		if (err) {
			f2fs_put_page(page, 1);
626
			break;
627
		}
628

629
		if (entry->blkaddr == blkaddr)
630
			list_move_tail(&entry->list, tmp_inode_list);
631 632 633
next:
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
634
		f2fs_put_page(page, 1);
635
	}
636
	if (!err)
C
Chao Yu 已提交
637
		f2fs_allocate_new_segments(sbi);
638
	return err;
639 640
}

C
Chao Yu 已提交
641
int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
642
{
643
	struct list_head inode_list, tmp_inode_list;
C
Chao Yu 已提交
644
	struct list_head dir_list;
645
	int err;
646
	int ret = 0;
C
Chao Yu 已提交
647
	unsigned long s_flags = sbi->sb->s_flags;
H
Haicheng Li 已提交
648
	bool need_writecp = false;
J
Jaegeuk Kim 已提交
649 650 651
#ifdef CONFIG_QUOTA
	int quota_enabled;
#endif
652

653
	if (s_flags & SB_RDONLY) {
654 655
		f2fs_msg(sbi->sb, KERN_INFO,
				"recover fsync data on readonly fs");
656
		sbi->sb->s_flags &= ~SB_RDONLY;
C
Chao Yu 已提交
657 658 659 660
	}

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

666
	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
667
			sizeof(struct fsync_inode_entry));
C
Chao Yu 已提交
668 669 670 671
	if (!fsync_entry_slab) {
		err = -ENOMEM;
		goto out;
	}
672 673

	INIT_LIST_HEAD(&inode_list);
674
	INIT_LIST_HEAD(&tmp_inode_list);
C
Chao Yu 已提交
675
	INIT_LIST_HEAD(&dir_list);
676

677 678 679
	/* prevent checkpoint */
	mutex_lock(&sbi->cp_mutex);

680
	/* step #1: find fsynced inode numbers */
681
	err = find_fsync_dnodes(sbi, &inode_list, check_only);
682
	if (err || list_empty(&inode_list))
C
Chao Yu 已提交
683
		goto skip;
684

685 686
	if (check_only) {
		ret = 1;
C
Chao Yu 已提交
687
		goto skip;
688
	}
689

H
Haicheng Li 已提交
690
	need_writecp = true;
691

692
	/* step #2: recover data */
693
	err = recover_data(sbi, &inode_list, &tmp_inode_list, &dir_list);
694
	if (!err)
695
		f2fs_bug_on(sbi, !list_empty(&inode_list));
696 697 698 699
	else {
		/* restore s_flags to let iput() trash data */
		sbi->sb->s_flags = s_flags;
	}
C
Chao Yu 已提交
700
skip:
701 702
	destroy_fsync_dnodes(&inode_list, err);
	destroy_fsync_dnodes(&tmp_inode_list, err);
703

704 705
	/* truncate meta pages to be used by the recovery */
	truncate_inode_pages_range(META_MAPPING(sbi),
706
			(loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1);
707

708 709 710
	if (err) {
		truncate_inode_pages_final(NODE_MAPPING(sbi));
		truncate_inode_pages_final(META_MAPPING(sbi));
711 712
	} else {
		clear_sbi_flag(sbi, SBI_POR_DOING);
713
	}
714 715
	mutex_unlock(&sbi->cp_mutex);

716
	/* let's drop all the directory inodes for clean checkpoint */
717
	destroy_fsync_dnodes(&dir_list, err);
718

719 720 721 722 723 724 725 726 727
	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);
		}
728
	}
C
Chao Yu 已提交
729 730

	kmem_cache_destroy(fsync_entry_slab);
C
Chao Yu 已提交
731 732 733
out:
#ifdef CONFIG_QUOTA
	/* Turn quotas off */
J
Jaegeuk Kim 已提交
734 735
	if (quota_enabled)
		f2fs_quota_off_umount(sbi->sb);
C
Chao Yu 已提交
736
#endif
737
	sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */
C
Chao Yu 已提交
738

739
	return ret ? ret: err;
740
}