recovery.c 9.8 KB
Newer Older
J
Jaegeuk Kim 已提交
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 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
 * 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"

static struct kmem_cache *fsync_entry_slab;

bool space_for_roll_forward(struct f2fs_sb_info *sbi)
{
	if (sbi->last_valid_block_count + sbi->alloc_valid_block_count
			> sbi->user_block_count)
		return false;
	return true;
}

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

	list_for_each(this, head) {
		entry = list_entry(this, struct fsync_inode_entry, list);
		if (entry->inode->i_ino == ino)
			return entry;
	}
	return NULL;
}

static int recover_dentry(struct page *ipage, struct inode *inode)
{
43 44
	void *kaddr = page_address(ipage);
	struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
45
	struct f2fs_inode *raw_inode = &(raw_node->i);
46
	nid_t pino = le32_to_cpu(raw_inode->i_pino);
47
	struct qstr name;
48 49 50 51
	struct page *page;
	struct inode *dir;
	int err = 0;

52 53 54 55 56 57 58 59
	dir = check_dirty_dir_inode(F2FS_SB(inode->i_sb), pino);
	if (!dir) {
		dir = f2fs_iget(inode->i_sb, pino);
		if (IS_ERR(dir)) {
			err = PTR_ERR(dir);
			goto out;
		}
		set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT);
60 61
	}

62 63
	name.len = le32_to_cpu(raw_inode->i_namelen);
	name.name = raw_inode->i_name;
64

65
	if (f2fs_find_entry(dir, &name, &page)) {
66 67 68
		kunmap(page);
		f2fs_put_page(page, 0);
	} else {
69
		err = __f2fs_add_link(dir, &name, inode);
70 71
	}
out:
72 73 74
	f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode and its dentry: "
			"ino = %x, name = %s, dir = %lx, err = %d",
			ino_of_node(ipage), raw_inode->i_name, dir->i_ino, err);
75 76 77 78 79 80 81 82 83
	return err;
}

static int recover_inode(struct inode *inode, struct page *node_page)
{
	void *kaddr = page_address(node_page);
	struct f2fs_node *raw_node = (struct f2fs_node *)kaddr;
	struct f2fs_inode *raw_inode = &(raw_node->i);

84 85 86
	if (!IS_INODE(node_page))
		return 0;

87
	inode->i_mode = le16_to_cpu(raw_inode->i_mode);
88 89 90 91 92 93 94 95
	i_size_write(inode, le64_to_cpu(raw_inode->i_size));
	inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
	inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime);
	inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime);
	inode->i_atime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);
	inode->i_ctime.tv_nsec = le32_to_cpu(raw_inode->i_ctime_nsec);
	inode->i_mtime.tv_nsec = le32_to_cpu(raw_inode->i_mtime_nsec);

96 97 98 99 100 101
	if (is_dent_dnode(node_page))
		return recover_dentry(node_page, inode);

	f2fs_msg(inode->i_sb, KERN_NOTICE, "recover_inode: ino = %x, name = %s",
			ino_of_node(node_page), raw_inode->i_name);
	return 0;
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
}

static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head)
{
	unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
	struct curseg_info *curseg;
	struct page *page;
	block_t blkaddr;
	int err = 0;

	/* get node pages in the current segment */
	curseg = CURSEG_I(sbi, CURSEG_WARM_NODE);
	blkaddr = START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff;

	/* read node page */
	page = alloc_page(GFP_F2FS_ZERO);
	if (IS_ERR(page))
		return PTR_ERR(page);
	lock_page(page);

	while (1) {
		struct fsync_inode_entry *entry;

125 126
		err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
		if (err)
127 128
			goto out;

129 130
		lock_page(page);

131
		if (cp_ver != cpver_of_node(page))
132
			break;
133 134 135 136 137 138 139 140 141 142 143

		if (!is_fsync_dnode(page))
			goto next;

		entry = get_fsync_inode(head, ino_of_node(page));
		if (entry) {
			if (IS_INODE(page) && is_dent_dnode(page))
				set_inode_flag(F2FS_I(entry->inode),
							FI_INC_LINK);
		} else {
			if (IS_INODE(page) && is_dent_dnode(page)) {
144 145
				err = recover_inode_page(sbi, page);
				if (err)
146
					break;
147 148 149 150 151 152
			}

			/* add this fsync inode to the list */
			entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS);
			if (!entry) {
				err = -ENOMEM;
153
				break;
154 155 156 157 158
			}

			entry->inode = f2fs_iget(sbi->sb, ino_of_node(page));
			if (IS_ERR(entry->inode)) {
				err = PTR_ERR(entry->inode);
159
				kmem_cache_free(fsync_entry_slab, entry);
160
				break;
161
			}
162
			list_add_tail(&entry->list, head);
163
		}
J
Jaegeuk Kim 已提交
164 165
		entry->blkaddr = blkaddr;

166 167 168
		err = recover_inode(entry->inode, page);
		if (err && err != -ENOENT)
			break;
169 170 171 172 173
next:
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
	}
	unlock_page(page);
174
out:
175 176 177 178 179 180 181
	__free_pages(page, 0);
	return err;
}

static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
					struct list_head *head)
{
182 183 184
	struct fsync_inode_entry *entry, *tmp;

	list_for_each_entry_safe(entry, tmp, head, list) {
185 186 187 188 189 190 191 192 193 194 195 196 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 224 225 226 227 228 229 230 231 232 233 234
		iput(entry->inode);
		list_del(&entry->list);
		kmem_cache_free(fsync_entry_slab, entry);
	}
}

static void check_index_in_prev_nodes(struct f2fs_sb_info *sbi,
						block_t blkaddr)
{
	struct seg_entry *sentry;
	unsigned int segno = GET_SEGNO(sbi, blkaddr);
	unsigned short blkoff = GET_SEGOFF_FROM_SEG0(sbi, blkaddr) &
					(sbi->blocks_per_seg - 1);
	struct f2fs_summary sum;
	nid_t ino;
	void *kaddr;
	struct inode *inode;
	struct page *node_page;
	block_t bidx;
	int i;

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

	/* Get the previous summary */
	for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) {
		struct curseg_info *curseg = CURSEG_I(sbi, i);
		if (curseg->segno == segno) {
			sum = curseg->sum_blk->entries[blkoff];
			break;
		}
	}
	if (i > CURSEG_COLD_DATA) {
		struct page *sum_page = get_sum_page(sbi, segno);
		struct f2fs_summary_block *sum_node;
		kaddr = page_address(sum_page);
		sum_node = (struct f2fs_summary_block *)kaddr;
		sum = sum_node->entries[blkoff];
		f2fs_put_page(sum_page, 1);
	}

	/* Get the node page */
	node_page = get_node_page(sbi, le32_to_cpu(sum.nid));
	bidx = start_bidx_of_node(ofs_of_node(node_page)) +
				le16_to_cpu(sum.ofs_in_node);
	ino = ino_of_node(node_page);
	f2fs_put_page(node_page, 1);

	/* Deallocate previous index in the node page */
235
	inode = f2fs_iget(sbi->sb, ino);
236 237 238
	if (IS_ERR(inode))
		return;

239 240 241 242
	truncate_hole(inode, bidx, bidx + 1);
	iput(inode);
}

243
static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
244 245 246 247 248 249
					struct page *page, block_t blkaddr)
{
	unsigned int start, end;
	struct dnode_of_data dn;
	struct f2fs_summary sum;
	struct node_info ni;
250
	int err = 0, recovered = 0;
251
	int ilock;
252 253 254 255 256 257 258

	start = start_bidx_of_node(ofs_of_node(page));
	if (IS_INODE(page))
		end = start + ADDRS_PER_INODE;
	else
		end = start + ADDRS_PER_BLOCK;

259
	ilock = mutex_lock_op(sbi);
260
	set_new_dnode(&dn, inode, NULL, NULL, 0);
261

262
	err = get_dnode_of_data(&dn, start, ALLOC_NODE);
263 264
	if (err) {
		mutex_unlock_op(sbi, ilock);
265
		return err;
266
	}
267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

	wait_on_page_writeback(dn.node_page);

	get_node_info(sbi, dn.nid, &ni);
	BUG_ON(ni.ino != ino_of_node(page));
	BUG_ON(ofs_of_node(dn.node_page) != ofs_of_node(page));

	for (; start < end; start++) {
		block_t src, dest;

		src = datablock_addr(dn.node_page, dn.ofs_in_node);
		dest = datablock_addr(page, dn.ofs_in_node);

		if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) {
			if (src == NULL_ADDR) {
				int err = reserve_new_block(&dn);
				/* We should not get -ENOSPC */
				BUG_ON(err);
			}

			/* Check the previous node page having this index */
			check_index_in_prev_nodes(sbi, dest);

			set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version);

			/* write dummy data page */
			recover_data_page(sbi, NULL, &sum, src, dest);
			update_extent_cache(dest, &dn);
295
			recovered++;
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311
		}
		dn.ofs_in_node++;
	}

	/* write node page in place */
	set_summary(&sum, dn.nid, 0, 0);
	if (IS_INODE(dn.node_page))
		sync_inode_page(&dn);

	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);

	recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr);
	f2fs_put_dnode(&dn);
312
	mutex_unlock_op(sbi, ilock);
313 314 315 316

	f2fs_msg(sbi->sb, KERN_NOTICE, "recover_data: ino = %lx, "
			"recovered_data = %d blocks",
			inode->i_ino, recovered);
317
	return 0;
318 319
}

320
static int recover_data(struct f2fs_sb_info *sbi,
321 322 323 324 325
				struct list_head *head, int type)
{
	unsigned long long cp_ver = le64_to_cpu(sbi->ckpt->checkpoint_ver);
	struct curseg_info *curseg;
	struct page *page;
326
	int err = 0;
327 328 329 330 331 332 333 334 335
	block_t blkaddr;

	/* get node pages in the current segment */
	curseg = CURSEG_I(sbi, type);
	blkaddr = NEXT_FREE_BLKADDR(sbi, curseg);

	/* read node page */
	page = alloc_page(GFP_NOFS | __GFP_ZERO);
	if (IS_ERR(page))
336 337
		return -ENOMEM;

338 339 340 341 342
	lock_page(page);

	while (1) {
		struct fsync_inode_entry *entry;

343 344
		err = f2fs_readpage(sbi, page, blkaddr, READ_SYNC);
		if (err)
345 346
			goto out;

347 348
		lock_page(page);

349
		if (cp_ver != cpver_of_node(page))
350
			break;
351 352 353 354 355

		entry = get_fsync_inode(head, ino_of_node(page));
		if (!entry)
			goto next;

356 357
		err = do_recover_data(sbi, entry->inode, page, blkaddr);
		if (err)
358
			break;
359 360 361 362 363 364 365 366 367 368 369

		if (entry->blkaddr == blkaddr) {
			iput(entry->inode);
			list_del(&entry->list);
			kmem_cache_free(fsync_entry_slab, entry);
		}
next:
		/* check next segment */
		blkaddr = next_blkaddr_of_node(page);
	}
	unlock_page(page);
370
out:
371 372
	__free_pages(page, 0);

373 374 375
	if (!err)
		allocate_new_segments(sbi);
	return err;
376 377
}

378
int recover_fsync_data(struct f2fs_sb_info *sbi)
379 380
{
	struct list_head inode_list;
381
	int err;
382 383 384 385

	fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry",
			sizeof(struct fsync_inode_entry), NULL);
	if (unlikely(!fsync_entry_slab))
386
		return -ENOMEM;
387 388 389 390

	INIT_LIST_HEAD(&inode_list);

	/* step #1: find fsynced inode numbers */
391
	sbi->por_doing = 1;
392 393
	err = find_fsync_dnodes(sbi, &inode_list);
	if (err)
394 395 396 397 398 399
		goto out;

	if (list_empty(&inode_list))
		goto out;

	/* step #2: recover data */
400
	err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE);
401 402 403 404
	BUG_ON(!list_empty(&inode_list));
out:
	destroy_fsync_dnodes(sbi, &inode_list);
	kmem_cache_destroy(fsync_entry_slab);
405
	sbi->por_doing = 0;
406 407
	if (!err)
		write_checkpoint(sbi, false);
408
	return err;
409
}