12c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim/**
22c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * defrag.c
32c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim *
42c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org>
52c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim *
62c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * This program is free software; you can redistribute it and/or modify
72c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * it under the terms of the GNU General Public License version 2 as
82c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * published by the Free Software Foundation.
92c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim */
102c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim#include "fsck.h"
112c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
122c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kimstatic int migrate_block(struct f2fs_sb_info *sbi, u64 from, u64 to)
132c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim{
142c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	void *raw = calloc(BLOCK_SZ, 1);
152c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	struct seg_entry *se;
162c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	struct f2fs_summary sum;
172c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	u64 offset;
182c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	int ret, type;
192c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
202c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	ASSERT(raw != NULL);
212c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
222c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* read from */
232c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	ret = dev_read_block(raw, from);
242c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	ASSERT(ret >= 0);
252c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
262c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* write to */
272c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	ret = dev_write_block(raw, to);
282c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	ASSERT(ret >= 0);
292c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
302c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* update sit bitmap & valid_blocks && se->type */
312c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se = get_seg_entry(sbi, GET_SEGNO(sbi, from));
322c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	offset = OFFSET_IN_SEG(sbi, from);
332c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	type = se->type;
342c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se->valid_blocks--;
352c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	f2fs_clear_bit(offset, (char *)se->cur_valid_map);
362c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se->dirty = 1;
372c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
382c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se = get_seg_entry(sbi, GET_SEGNO(sbi, to));
392c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	offset = OFFSET_IN_SEG(sbi, to);
402c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se->type = type;
412c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se->valid_blocks++;
422c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	f2fs_set_bit(offset, (char *)se->cur_valid_map);
432c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	se->dirty = 1;
442c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
452c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* read/write SSA */
462c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	get_sum_entry(sbi, from, &sum);
472c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	update_sum_entry(sbi, to, &sum);
482c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
492c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* if data block, read node and update node block */
502c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	if (IS_DATASEG(type))
512c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		update_data_blkaddr(sbi, le32_to_cpu(sum.nid),
522c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim				le16_to_cpu(sum.ofs_in_node), to);
532c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	else
54603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim		update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to);
552c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
562c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	DBG(0, "Migrate %s block %"PRIx64" -> %"PRIx64"\n",
572c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim					IS_DATASEG(type) ? "data" : "node",
582c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim					from, to);
592c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	free(raw);
602c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	return 0;
612c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim}
622c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
632c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kimint f2fs_defragment(struct f2fs_sb_info *sbi, u64 from, u64 len, u64 to, int left)
642c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim{
652c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	struct seg_entry *se;
662c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	u64 idx, offset;
672c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
682c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* flush NAT/SIT journal entries */
692c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	flush_journal_entries(sbi);
702c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
712c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	for (idx = from; idx < from + len; idx++) {
722c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		u64 target = to;
732c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
742c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		se = get_seg_entry(sbi, GET_SEGNO(sbi, idx));
752c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		offset = OFFSET_IN_SEG(sbi, idx);
762c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
772c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		if (!f2fs_test_bit(offset, (const char *)se->cur_valid_map))
782c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim			continue;
792c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
802c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		if (find_next_free_block(sbi, &target, left, se->type)) {
812f2ee92b3409440bf7cbd50159840efbbd873bb4Jaegeuk Kim			MSG(0, "Not enough space to migrate blocks");
822f2ee92b3409440bf7cbd50159840efbbd873bb4Jaegeuk Kim			return -1;
832c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		}
842c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
852c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		if (migrate_block(sbi, idx, target)) {
862c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim			ASSERT_MSG("Found inconsistency: please run FSCK");
872c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim			return -1;
882c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim		}
892c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	}
902c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
912c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* update curseg info; can update sit->types */
922c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	move_curseg_info(sbi, to);
9317acba6d3da4efd60142b513b2017bddf67d49bbJaegeuk Kim	zero_journal_entries(sbi);
942c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	write_curseg_info(sbi);
952c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
962c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	/* flush dirty sit entries */
972c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	flush_sit_entries(sbi);
982c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
992c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	write_checkpoint(sbi);
1002c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim
1012c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim	return 0;
1022c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim}
103