recovery.c 19.2 KB
Newer Older
Chao Yu's avatar
Chao Yu committed
1
// SPDX-License-Identifier: GPL-2.0
Jaegeuk Kim's avatar
Jaegeuk Kim committed
2
/*
3 4 5 6 7 8 9 10 11 12 13
 * fs/f2fs/recovery.c
 *
 * Copyright (c) 2012 Samsung Electronics Co., Ltd.
 *             http://www.samsung.com/
 */
#include <linux/fs.h>
#include <linux/f2fs_fs.h>
#include "f2fs.h"
#include "node.h"
#include "segment.h"

14 15 16 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
/*
 * 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).
 */

45 46
static struct kmem_cache *fsync_entry_slab;

Chao Yu's avatar
Chao Yu committed
47
bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi)
48
{
49 50 51
	s64 nalloc = percpu_counter_sum_positive(&sbi->alloc_valid_block_count);

	if (sbi->last_valid_block_count + nalloc > sbi->user_block_count)
52 53 54 55 56 57 58 59 60
		return false;
	return true;
}

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

61
	list_for_each_entry(entry, head, list)
62 63
		if (entry->inode->i_ino == ino)
			return entry;
64

65 66 67
	return NULL;
}

68
static struct fsync_inode_entry *add_fsync_inode(struct f2fs_sb_info *sbi,
Chao Yu's avatar
Chao Yu committed
69
			struct list_head *head, nid_t ino, bool quota_inode)
70
{
71
	struct inode *inode;
72
	struct fsync_inode_entry *entry;
Chao Yu's avatar
Chao Yu committed
73
	int err;
74

75
	inode = f2fs_iget_retry(sbi->sb, ino);
76 77 78
	if (IS_ERR(inode))
		return ERR_CAST(inode);

Chao Yu's avatar
Chao Yu committed
79 80 81 82 83 84 85 86 87 88
	err = dquot_initialize(inode);
	if (err)
		goto err_out;

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

89
	entry = f2fs_kmem_cache_alloc(fsync_entry_slab, GFP_F2FS_ZERO);
90 91 92 93
	entry->inode = inode;
	list_add_tail(&entry->list, head);

	return entry;
Chao Yu's avatar
Chao Yu committed
94 95 96
err_out:
	iput(inode);
	return ERR_PTR(err);
97 98
}

99
static void del_fsync_inode(struct fsync_inode_entry *entry, int drop)
100
{
101 102 103 104
	if (drop) {
		/* inode should not be recovered, drop it */
		f2fs_inode_synced(entry->inode);
	}
105 106 107 108 109
	iput(entry->inode);
	list_del(&entry->list);
	kmem_cache_free(fsync_entry_slab, entry);
}

Chao Yu's avatar
Chao Yu committed
110 111
static int recover_dentry(struct inode *inode, struct page *ipage,
						struct list_head *dir_list)
112
{
113
	struct f2fs_inode *raw_inode = F2FS_INODE(ipage);
114
	nid_t pino = le32_to_cpu(raw_inode->i_pino);
115
	struct f2fs_dir_entry *de;
116
	struct fscrypt_name fname;
117
	struct page *page;
118
	struct inode *dir, *einode;
Chao Yu's avatar
Chao Yu committed
119
	struct fsync_inode_entry *entry;
120
	int err = 0;
121
	char *name;
122

Chao Yu's avatar
Chao Yu committed
123 124
	entry = get_fsync_inode(dir_list, pino);
	if (!entry) {
Chao Yu's avatar
Chao Yu committed
125 126
		entry = add_fsync_inode(F2FS_I_SB(inode), dir_list,
							pino, false);
127 128 129
		if (IS_ERR(entry)) {
			dir = ERR_CAST(entry);
			err = PTR_ERR(entry);
Chao Yu's avatar
Chao Yu committed
130 131
			goto out;
		}
132 133
	}

Chao Yu's avatar
Chao Yu committed
134 135
	dir = entry->inode;

136 137 138
	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;
139

140
	if (unlikely(fname.disk_name.len > F2FS_NAME_LEN)) {
141 142
		WARN_ON(1);
		err = -ENAMETOOLONG;
Chao Yu's avatar
Chao Yu committed
143
		goto out;
144
	}
145
retry:
146
	de = __f2fs_find_entry(dir, &fname, &page);
147
	if (de && inode->i_ino == le32_to_cpu(de->ino))
148
		goto out_put;
149

150
	if (de) {
151
		einode = f2fs_iget_retry(inode->i_sb, le32_to_cpu(de->ino));
152 153
		if (IS_ERR(einode)) {
			WARN_ON(1);
154 155
			err = PTR_ERR(einode);
			if (err == -ENOENT)
156
				err = -EEXIST;
157
			goto out_put;
158
		}
Chao Yu's avatar
Chao Yu committed
159 160 161 162

		err = dquot_initialize(einode);
		if (err) {
			iput(einode);
163
			goto out_put;
Chao Yu's avatar
Chao Yu committed
164 165
		}

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

184
out_put:
185
	f2fs_put_page(page, 0);
186
out:
187 188 189 190
	if (file_enc_name(inode))
		name = "<encrypted>";
	else
		name = raw_inode->i_name;
191 192 193
	f2fs_notice(F2FS_I_SB(inode), "%s: ino = %x, name = %s, dir = %lx, err = %d",
		    __func__, ino_of_node(ipage), name,
		    IS_ERR(dir) ? 0 : dir->i_ino, err);
194 195 196
	return err;
}

197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223
static int recover_quota_data(struct inode *inode, struct page *page)
{
	struct f2fs_inode *raw = F2FS_INODE(page);
	struct iattr attr;
	uid_t i_uid = le32_to_cpu(raw->i_uid);
	gid_t i_gid = le32_to_cpu(raw->i_gid);
	int err;

	memset(&attr, 0, sizeof(attr));

	attr.ia_uid = make_kuid(inode->i_sb->s_user_ns, i_uid);
	attr.ia_gid = make_kgid(inode->i_sb->s_user_ns, i_gid);

	if (!uid_eq(attr.ia_uid, inode->i_uid))
		attr.ia_valid |= ATTR_UID;
	if (!gid_eq(attr.ia_gid, inode->i_gid))
		attr.ia_valid |= ATTR_GID;

	if (!attr.ia_valid)
		return 0;

	err = dquot_transfer(inode, &attr);
	if (err)
		set_sbi_flag(F2FS_I_SB(inode), SBI_QUOTA_NEED_REPAIR);
	return err;
}

224 225 226 227 228 229 230 231 232 233 234 235
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);
}

236
static int recover_inode(struct inode *inode, struct page *page)
237
{
238
	struct f2fs_inode *raw = F2FS_INODE(page);
239
	char *name;
240
	int err;
241 242

	inode->i_mode = le16_to_cpu(raw->i_mode);
243 244 245 246 247

	err = recover_quota_data(inode, page);
	if (err)
		return err;

248 249
	i_uid_write(inode, le32_to_cpu(raw->i_uid));
	i_gid_write(inode, le32_to_cpu(raw->i_gid));
250 251

	if (raw->i_inline & F2FS_EXTRA_ATTR) {
252
		if (f2fs_sb_has_project_quota(F2FS_I_SB(inode)) &&
253 254 255
			F2FS_FITS_IN_INODE(raw, le16_to_cpu(raw->i_extra_isize),
								i_projid)) {
			projid_t i_projid;
256
			kprojid_t kprojid;
257 258

			i_projid = (projid_t)le32_to_cpu(raw->i_projid);
259 260 261 262 263 264 265 266 267
			kprojid = make_kprojid(&init_user_ns, i_projid);

			if (!projid_eq(kprojid, F2FS_I(inode)->i_projid)) {
				err = f2fs_transfer_project_quota(inode,
								kprojid);
				if (err)
					return err;
				F2FS_I(inode)->i_projid = kprojid;
			}
268 269 270
		}
	}

271
	f2fs_i_size_write(inode, le64_to_cpu(raw->i_size));
Chao Yu's avatar
Chao Yu committed
272
	inode->i_atime.tv_sec = le64_to_cpu(raw->i_atime);
273 274
	inode->i_ctime.tv_sec = le64_to_cpu(raw->i_ctime);
	inode->i_mtime.tv_sec = le64_to_cpu(raw->i_mtime);
Chao Yu's avatar
Chao Yu committed
275
	inode->i_atime.tv_nsec = le32_to_cpu(raw->i_atime_nsec);
276 277
	inode->i_ctime.tv_nsec = le32_to_cpu(raw->i_ctime_nsec);
	inode->i_mtime.tv_nsec = le32_to_cpu(raw->i_mtime_nsec);
278

279
	F2FS_I(inode)->i_advise = raw->i_advise;
280
	F2FS_I(inode)->i_flags = le32_to_cpu(raw->i_flags);
281
	f2fs_set_inode_flags(inode);
282 283
	F2FS_I(inode)->i_gc_failures[GC_FAILURE_PIN] =
				le16_to_cpu(raw->i_gc_failures);
284

285 286
	recover_inline_flags(inode, raw);

287 288
	f2fs_mark_inode_dirty_sync(inode, true);

289 290 291 292 293
	if (file_enc_name(inode))
		name = "<encrypted>";
	else
		name = F2FS_INODE(page)->i_name;

294 295
	f2fs_notice(F2FS_I_SB(inode), "recover_inode: ino = %x, name = %s, inline = %x",
		    ino_of_node(page), name, raw->i_inline);
296
	return 0;
297 298
}

299 300
static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head,
				bool check_only)
301 302
{
	struct curseg_info *curseg;
303
	struct page *page = NULL;
304
	block_t blkaddr;
305
	unsigned int loop_cnt = 0;
306 307
	unsigned int free_blocks = MAIN_SEGS(sbi) * sbi->blocks_per_seg -
						valid_user_blocks(sbi);
308 309 310 311
	int err = 0;

	/* get node pages in the current segment */
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
312
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);
313 314 315 316

	while (1) {
		struct fsync_inode_entry *entry;

317
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
318
			return 0;
319

Chao Yu's avatar
Chao Yu committed
320
		page = f2fs_get_tmp_page(sbi, blkaddr);
321 322 323 324
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
325

Chao Yu's avatar
Chao Yu committed
326 327
		if (!is_recoverable_dnode(page)) {
			f2fs_put_page(page, 1);
328
			break;
Chao Yu's avatar
Chao Yu committed
329
		}
330 331 332 333 334

		if (!is_fsync_dnode(page))
			goto next;

		entry = get_fsync_inode(head, ino_of_node(page));
335
		if (!entry) {
Chao Yu's avatar
Chao Yu committed
336 337
			bool quota_inode = false;

338 339
			if (!check_only &&
					IS_INODE(page) && is_dent_dnode(page)) {
Chao Yu's avatar
Chao Yu committed
340
				err = f2fs_recover_inode_page(sbi, page);
Chao Yu's avatar
Chao Yu committed
341 342
				if (err) {
					f2fs_put_page(page, 1);
343
					break;
Chao Yu's avatar
Chao Yu committed
344
				}
Chao Yu's avatar
Chao Yu committed
345
				quota_inode = true;
346 347
			}

348 349 350 351
			/*
			 * CP | dnode(F) | inode(DF)
			 * For this case, we should not give up now.
			 */
Chao Yu's avatar
Chao Yu committed
352 353
			entry = add_fsync_inode(sbi, head, ino_of_node(page),
								quota_inode);
354 355
			if (IS_ERR(entry)) {
				err = PTR_ERR(entry);
356 357
				if (err == -ENOENT) {
					err = 0;
358
					goto next;
359
				}
Chao Yu's avatar
Chao Yu committed
360
				f2fs_put_page(page, 1);
361
				break;
362 363
			}
		}
364 365
		entry->blkaddr = blkaddr;

366 367
		if (IS_INODE(page) && is_dent_dnode(page))
			entry->last_dentry = blkaddr;
368
next:
369 370 371
		/* sanity check in order to detect looped node chain */
		if (++loop_cnt >= free_blocks ||
			blkaddr == next_blkaddr_of_node(page)) {
372 373 374
			f2fs_notice(sbi, "%s: detect looped node chain, blkaddr:%u, next:%u",
				    __func__, blkaddr,
				    next_blkaddr_of_node(page));
Chao Yu's avatar
Chao Yu committed
375
			f2fs_put_page(page, 1);
376 377 378 379
			err = -EINVAL;
			break;
		}

380 381
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
382
		f2fs_put_page(page, 1);
383

Chao Yu's avatar
Chao Yu committed
384
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
385 386 387 388
	}
	return err;
}

389
static void destroy_fsync_dnodes(struct list_head *head, int drop)
390
{
391 392
	struct fsync_inode_entry *entry, *tmp;

393
	list_for_each_entry_safe(entry, tmp, head, list)
394
		del_fsync_inode(entry, drop);
395 396
}

397
static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
398
			block_t blkaddr, struct dnode_of_data *dn)
399 400 401
{
	struct seg_entry *sentry;
	unsigned int segno = GET_SEGNO(sbi, blkaddr);
Jaegeuk Kim's avatar
Jaegeuk Kim committed
402
	unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr);
Jaegeuk Kim's avatar
Jaegeuk Kim committed
403
	struct f2fs_summary_block *sum_node;
404
	struct f2fs_summary sum;
Jaegeuk Kim's avatar
Jaegeuk Kim committed
405
	struct page *sum_page, *node_page;
406
	struct dnode_of_data tdn = *dn;
407
	nid_t ino, nid;
408
	struct inode *inode;
409
	unsigned int offset;
410 411 412 413 414
	block_t bidx;
	int i;

	sentry = get_seg_entry(sbi, segno);
	if (!f2fs_test_bit(blkoff, sentry->cur_valid_map))
415
		return 0;
416 417

	/* Get the previous summary */
418
	for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) {
419 420 421
		struct curseg_info *curseg = CURSEG_I(sbi, i);
		if (curseg->segno == segno) {
			sum = curseg->sum_blk->entries[blkoff];
Jaegeuk Kim's avatar
Jaegeuk Kim committed
422
			goto got_it;
423 424 425
		}
	}

Chao Yu's avatar
Chao Yu committed
426
	sum_page = f2fs_get_sum_page(sbi, segno);
427 428
	if (IS_ERR(sum_page))
		return PTR_ERR(sum_page);
Jaegeuk Kim's avatar
Jaegeuk Kim committed
429 430 431 432
	sum_node = (struct f2fs_summary_block *)page_address(sum_page);
	sum = sum_node->entries[blkoff];
	f2fs_put_page(sum_page, 1);
got_it:
433 434 435 436
	/* Use the locked dnode page and inode */
	nid = le32_to_cpu(sum.nid);
	if (dn->inode->i_ino == nid) {
		tdn.nid = nid;
437 438
		if (!dn->inode_page_locked)
			lock_page(dn->inode_page);
439
		tdn.node_page = dn->inode_page;
440
		tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
441
		goto truncate_out;
442
	} else if (dn->nid == nid) {
443
		tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node);
444
		goto truncate_out;
445 446
	}

447
	/* Get the node page */
Chao Yu's avatar
Chao Yu committed
448
	node_page = f2fs_get_node_page(sbi, nid);
449 450
	if (IS_ERR(node_page))
		return PTR_ERR(node_page);
451 452

	offset = ofs_of_node(node_page);
453 454 455
	ino = ino_of_node(node_page);
	f2fs_put_page(node_page, 1);

456
	if (ino != dn->inode->i_ino) {
Chao Yu's avatar
Chao Yu committed
457 458
		int ret;

459
		/* Deallocate previous index in the node page */
460
		inode = f2fs_iget_retry(sbi->sb, ino);
461 462
		if (IS_ERR(inode))
			return PTR_ERR(inode);
Chao Yu's avatar
Chao Yu committed
463 464 465 466 467 468

		ret = dquot_initialize(inode);
		if (ret) {
			iput(inode);
			return ret;
		}
469 470 471
	} else {
		inode = dn->inode;
	}
472

Chao Yu's avatar
Chao Yu committed
473 474
	bidx = f2fs_start_bidx_of_node(offset, inode) +
				le16_to_cpu(sum.ofs_in_node);
475

476 477 478 479 480 481 482 483
	/*
	 * 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);
Chao Yu's avatar
Chao Yu committed
484
	if (f2fs_get_dnode_of_data(&tdn, bidx, LOOKUP_NODE))
485 486 487
		goto out;

	if (tdn.data_blkaddr == blkaddr)
Chao Yu's avatar
Chao Yu committed
488
		f2fs_truncate_data_blocks_range(&tdn, 1);
489 490 491 492

	f2fs_put_dnode(&tdn);
out:
	if (ino != dn->inode->i_ino)
493
		iput(inode);
494 495 496 497 498
	else if (dn->inode_page_locked)
		lock_page(dn->inode_page);
	return 0;

truncate_out:
499 500
	if (datablock_addr(tdn.inode, tdn.node_page,
					tdn.ofs_in_node) == blkaddr)
Chao Yu's avatar
Chao Yu committed
501
		f2fs_truncate_data_blocks_range(&tdn, 1);
502 503
	if (dn->inode->i_ino == nid && !dn->inode_page_locked)
		unlock_page(dn->inode_page);
504
	return 0;
505 506
}

507
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
Sheng Yong's avatar
Sheng Yong committed
508
					struct page *page)
509 510 511
{
	struct dnode_of_data dn;
	struct node_info ni;
512
	unsigned int start, end;
513
	int err = 0, recovered = 0;
514

515 516
	/* step 1: recover xattr */
	if (IS_INODE(page)) {
Chao Yu's avatar
Chao Yu committed
517
		f2fs_recover_inline_xattr(inode, page);
518
	} else if (f2fs_has_xattr_block(ofs_of_node(page))) {
Chao Yu's avatar
Chao Yu committed
519
		err = f2fs_recover_xattr_data(inode, page);
520 521
		if (!err)
			recovered++;
522
		goto out;
523
	}
524

525
	/* step 2: recover inline data */
Chao Yu's avatar
Chao Yu committed
526
	if (f2fs_recover_inline_data(inode, page))
527 528
		goto out;

529
	/* step 3: recover data indices */
Chao Yu's avatar
Chao Yu committed
530
	start = f2fs_start_bidx_of_node(ofs_of_node(page), inode);
531
	end = start + ADDRS_PER_PAGE(page, inode);
532 533

	set_new_dnode(&dn, inode, NULL, NULL, 0);
534
retry_dn:
Chao Yu's avatar
Chao Yu committed
535
	err = f2fs_get_dnode_of_data(&dn, start, ALLOC_NODE);
536 537 538 539 540
	if (err) {
		if (err == -ENOMEM) {
			congestion_wait(BLK_RW_ASYNC, HZ/50);
			goto retry_dn;
		}
541
		goto out;
542
	}
543

544
	f2fs_wait_on_page_writeback(dn.node_page, NODE, true, true);
545

546 547 548 549
	err = f2fs_get_node_info(sbi, dn.nid, &ni);
	if (err)
		goto err;

550
	f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
551 552

	if (ofs_of_node(dn.node_page) != ofs_of_node(page)) {
553 554 555
		f2fs_warn(sbi, "Inconsistent ofs_of_node, ino:%lu, ofs:%u, %u",
			  inode->i_ino, ofs_of_node(dn.node_page),
			  ofs_of_node(page));
556 557 558
		err = -EFAULT;
		goto err;
	}
559

560
	for (; start < end; start++, dn.ofs_in_node++) {
561 562
		block_t src, dest;

563 564
		src = datablock_addr(dn.inode, dn.node_page, dn.ofs_in_node);
		dest = datablock_addr(dn.inode, page, dn.ofs_in_node);
565

566 567 568 569 570 571 572 573 574 575 576 577
		if (__is_valid_data_blkaddr(src) &&
			!f2fs_is_valid_blkaddr(sbi, src, META_POR)) {
			err = -EFAULT;
			goto err;
		}

		if (__is_valid_data_blkaddr(dest) &&
			!f2fs_is_valid_blkaddr(sbi, dest, META_POR)) {
			err = -EFAULT;
			goto err;
		}

578 579 580 581 582 583
		/* skip recovering if dest is the same as src */
		if (src == dest)
			continue;

		/* dest is invalid, just invalidate src block */
		if (dest == NULL_ADDR) {
Chao Yu's avatar
Chao Yu committed
584
			f2fs_truncate_data_blocks_range(&dn, 1);
585 586 587
			continue;
		}

588
		if (!file_keep_isize(inode) &&
589 590 591
			(i_size_read(inode) <= ((loff_t)start << PAGE_SHIFT)))
			f2fs_i_size_write(inode,
				(loff_t)(start + 1) << PAGE_SHIFT);
592

593 594 595 596 597
		/*
		 * dest is reserved block, invalidate src block
		 * and then reserve one new block in dnode page.
		 */
		if (dest == NEW_ADDR) {
Chao Yu's avatar
Chao Yu committed
598 599
			f2fs_truncate_data_blocks_range(&dn, 1);
			f2fs_reserve_new_block(&dn);
600 601 602 603
			continue;
		}

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

606
			if (src == NULL_ADDR) {
Chao Yu's avatar
Chao Yu committed
607
				err = f2fs_reserve_new_block(&dn);
608 609
				while (err &&
				       IS_ENABLED(CONFIG_F2FS_FAULT_INJECTION))
Chao Yu's avatar
Chao Yu committed
610
					err = f2fs_reserve_new_block(&dn);
611
				/* We should not get -ENOSPC */
612
				f2fs_bug_on(sbi, err);
613 614
				if (err)
					goto err;
615
			}
616
retry_prev:
617
			/* Check the previous node page having this index */
618
			err = check_index_in_prev_nodes(sbi, dest, &dn);
619 620 621 622 623
			if (err) {
				if (err == -ENOMEM) {
					congestion_wait(BLK_RW_ASYNC, HZ/50);
					goto retry_prev;
				}
624
				goto err;
625
			}
626 627

			/* write dummy data page */
628
			f2fs_replace_block(sbi, &dn, src, dest,
629
						ni.version, false, false);
630
			recovered++;
631 632 633 634 635 636 637
		}
	}

	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);
638
err:
639
	f2fs_put_dnode(&dn);
640
out:
641 642 643
	f2fs_notice(sbi, "recover_data: ino = %lx (i_size: %s) recovered = %d, err = %d",
		    inode->i_ino, file_keep_isize(inode) ? "keep" : "recover",
		    recovered, err);
644
	return err;
645 646
}

Chao Yu's avatar
Chao Yu committed
647
static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list,
648
		struct list_head *tmp_inode_list, struct list_head *dir_list)
649 650
{
	struct curseg_info *curseg;
651
	struct page *page = NULL;
652
	int err = 0;
653 654 655
	block_t blkaddr;

	/* get node pages in the current segment */
656
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
657 658 659 660 661
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);

	while (1) {
		struct fsync_inode_entry *entry;

662
		if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR))
663
			break;
664

Chao Yu's avatar
Chao Yu committed
665
		f2fs_ra_meta_pages_cond(sbi, blkaddr);
666

Chao Yu's avatar
Chao Yu committed
667
		page = f2fs_get_tmp_page(sbi, blkaddr);
668 669 670 671
		if (IS_ERR(page)) {
			err = PTR_ERR(page);
			break;
		}
672

673
		if (!is_recoverable_dnode(page)) {
674
			f2fs_put_page(page, 1);
675
			break;
676
		}
677

Chao Yu's avatar
Chao Yu committed
678
		entry = get_fsync_inode(inode_list, ino_of_node(page));
679 680
		if (!entry)
			goto next;
681 682 683
		/*
		 * inode(x) | CP | inode(x) | dnode(F)
		 * In this case, we can lose the latest inode(x).
684
		 * So, call recover_inode for the inode update.
685
		 */
686 687
		if (IS_INODE(page)) {
			err = recover_inode(entry->inode, page);
Chao Yu's avatar
Chao Yu committed
688 689
			if (err) {
				f2fs_put_page(page, 1);
690
				break;
Chao Yu's avatar
Chao Yu committed
691
			}
692
		}
693
		if (entry->last_dentry == blkaddr) {
Chao Yu's avatar
Chao Yu committed
694
			err = recover_dentry(entry->inode, page, dir_list);
695 696 697 698 699
			if (err) {
				f2fs_put_page(page, 1);
				break;
			}
		}
Sheng Yong's avatar
Sheng Yong committed
700
		err = do_recover_data(sbi, entry->inode, page);
701 702
		if (err) {
			f2fs_put_page(page, 1);
703
			break;
704
		}
705

706
		if (entry->blkaddr == blkaddr)
707
			list_move_tail(&entry->list, tmp_inode_list);
708 709 710
next:
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
711
		f2fs_put_page(page, 1);
712
	}
713
	if (!err)
Chao Yu's avatar
Chao Yu committed
714
		f2fs_allocate_new_segments(sbi);
715
	return err;
716 717
}

Chao Yu's avatar
Chao Yu committed
718
int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only)
719
{
720
	struct list_head inode_list, tmp_inode_list;
Chao Yu's avatar
Chao Yu committed
721
	struct list_head dir_list;
722
	int err;
723
	int ret = 0;
Chao Yu's avatar
Chao Yu committed
724
	unsigned long s_flags = sbi->sb->s_flags;
Haicheng Li's avatar
Haicheng Li committed
725
	bool need_writecp = false;
Jaegeuk Kim's avatar
Jaegeuk Kim committed
726 727 728
#ifdef CONFIG_QUOTA
	int quota_enabled;
#endif
729

730
	if (s_flags & SB_RDONLY) {
731
		f2fs_info(sbi, "recover fsync data on readonly fs");
732
		sbi->sb->s_flags &= ~SB_RDONLY;
Chao Yu's avatar
Chao Yu committed
733 734 735 736
	}

#ifdef CONFIG_QUOTA
	/* Needed for iput() to work correctly and not trash data */
737
	sbi->sb->s_flags |= SB_ACTIVE;
Chao Yu's avatar
Chao Yu committed
738
	/* Turn on quotas so that they are updated correctly */
739
	quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY);
Chao Yu's avatar
Chao Yu committed
740 741
#endif

742
	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
743
			sizeof(struct fsync_inode_entry));
Chao Yu's avatar
Chao Yu committed
744 745 746 747
	if (!fsync_entry_slab) {
		err = -ENOMEM;
		goto out;
	}
748 749

	INIT_LIST_HEAD(&inode_list);
750
	INIT_LIST_HEAD(&tmp_inode_list);
Chao Yu's avatar
Chao Yu committed
751
	INIT_LIST_HEAD(&dir_list);
752

753 754 755
	/* prevent checkpoint */
	mutex_lock(&sbi->cp_mutex);

756
	/* step #1: find fsynced inode numbers */
757
	err = find_fsync_dnodes(sbi, &inode_list, check_only);
758
	if (err || list_empty(&inode_list))
Chao Yu's avatar
Chao Yu committed
759
		goto skip;
760

761 762
	if (check_only) {
		ret = 1;
Chao Yu's avatar
Chao Yu committed
763
		goto skip;
764
	}
765

Haicheng Li's avatar
Haicheng Li committed
766
	need_writecp = true;
767

768
	/* step #2: recover data */
769
	err = recover_data(sbi, &inode_list, &tmp_inode_list, &dir_list);
770
	if (!err)
771
		f2fs_bug_on(sbi, !list_empty(&inode_list));
772 773 774 775
	else {
		/* restore s_flags to let iput() trash data */
		sbi->sb->s_flags = s_flags;
	}
Chao Yu's avatar
Chao Yu committed
776
skip:
777 778
	destroy_fsync_dnodes(&inode_list, err);
	destroy_fsync_dnodes(&tmp_inode_list, err);
779

780 781
	/* truncate meta pages to be used by the recovery */
	truncate_inode_pages_range(META_MAPPING(sbi),
782
			(loff_t)MAIN_BLKADDR(sbi) << PAGE_SHIFT, -1);
783

784 785 786
	if (err) {
		truncate_inode_pages_final(NODE_MAPPING(sbi));
		truncate_inode_pages_final(META_MAPPING(sbi));
787 788
	} else {
		clear_sbi_flag(sbi, SBI_POR_DOING);
789
	}
790 791
	mutex_unlock(&sbi->cp_mutex);

792
	/* let's drop all the directory inodes for clean checkpoint */
793
	destroy_fsync_dnodes(&dir_list, err);
794

795 796 797 798 799 800 801 802 803
	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);
		}
804
	}
Chao Yu's avatar
Chao Yu committed
805 806

	kmem_cache_destroy(fsync_entry_slab);
Chao Yu's avatar
Chao Yu committed
807 808 809
out:
#ifdef CONFIG_QUOTA
	/* Turn quotas off */
Jaegeuk Kim's avatar
Jaegeuk Kim committed
810 811
	if (quota_enabled)
		f2fs_quota_off_umount(sbi->sb);
Chao Yu's avatar
Chao Yu committed
812
#endif
813
	sbi->sb->s_flags = s_flags; /* Restore SB_RDONLY status */
Chao Yu's avatar
Chao Yu committed
814

815
	return ret ? ret: err;
816
}