xref: /aosp_15_r20/external/f2fs-tools/fsck/defrag.c (revision 59bfda1f02d633cd6b8b69f31eee485d40f6eef6)
1*59bfda1fSAndroid Build Coastguard Worker /**
2*59bfda1fSAndroid Build Coastguard Worker  * defrag.c
3*59bfda1fSAndroid Build Coastguard Worker  *
4*59bfda1fSAndroid Build Coastguard Worker  * Copyright (c) 2015 Jaegeuk Kim <[email protected]>
5*59bfda1fSAndroid Build Coastguard Worker  *
6*59bfda1fSAndroid Build Coastguard Worker  * This program is free software; you can redistribute it and/or modify
7*59bfda1fSAndroid Build Coastguard Worker  * it under the terms of the GNU General Public License version 2 as
8*59bfda1fSAndroid Build Coastguard Worker  * published by the Free Software Foundation.
9*59bfda1fSAndroid Build Coastguard Worker  */
10*59bfda1fSAndroid Build Coastguard Worker #include "fsck.h"
11*59bfda1fSAndroid Build Coastguard Worker 
migrate_block(struct f2fs_sb_info * sbi,u64 from,u64 to)12*59bfda1fSAndroid Build Coastguard Worker static int migrate_block(struct f2fs_sb_info *sbi, u64 from, u64 to)
13*59bfda1fSAndroid Build Coastguard Worker {
14*59bfda1fSAndroid Build Coastguard Worker 	void *raw = calloc(F2FS_BLKSIZE, 1);
15*59bfda1fSAndroid Build Coastguard Worker 	struct seg_entry *se;
16*59bfda1fSAndroid Build Coastguard Worker 	struct f2fs_summary sum;
17*59bfda1fSAndroid Build Coastguard Worker 	u64 offset;
18*59bfda1fSAndroid Build Coastguard Worker 	int ret, type;
19*59bfda1fSAndroid Build Coastguard Worker 
20*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(raw != NULL);
21*59bfda1fSAndroid Build Coastguard Worker 
22*59bfda1fSAndroid Build Coastguard Worker 	/* read from */
23*59bfda1fSAndroid Build Coastguard Worker 	ret = dev_read_block(raw, from);
24*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(ret >= 0);
25*59bfda1fSAndroid Build Coastguard Worker 
26*59bfda1fSAndroid Build Coastguard Worker 	/* get segment type */
27*59bfda1fSAndroid Build Coastguard Worker 	se = get_seg_entry(sbi, GET_SEGNO(sbi, from));
28*59bfda1fSAndroid Build Coastguard Worker 	/* write to */
29*59bfda1fSAndroid Build Coastguard Worker 	ret = dev_write_block(raw, to, f2fs_io_type_to_rw_hint(se->type));
30*59bfda1fSAndroid Build Coastguard Worker 	ASSERT(ret >= 0);
31*59bfda1fSAndroid Build Coastguard Worker 
32*59bfda1fSAndroid Build Coastguard Worker 	/* update sit bitmap & valid_blocks && se->type */
33*59bfda1fSAndroid Build Coastguard Worker 	offset = OFFSET_IN_SEG(sbi, from);
34*59bfda1fSAndroid Build Coastguard Worker 	type = se->type;
35*59bfda1fSAndroid Build Coastguard Worker 	se->valid_blocks--;
36*59bfda1fSAndroid Build Coastguard Worker 	f2fs_clear_bit(offset, (char *)se->cur_valid_map);
37*59bfda1fSAndroid Build Coastguard Worker 	se->dirty = 1;
38*59bfda1fSAndroid Build Coastguard Worker 
39*59bfda1fSAndroid Build Coastguard Worker 	se = get_seg_entry(sbi, GET_SEGNO(sbi, to));
40*59bfda1fSAndroid Build Coastguard Worker 	offset = OFFSET_IN_SEG(sbi, to);
41*59bfda1fSAndroid Build Coastguard Worker 	se->type = type;
42*59bfda1fSAndroid Build Coastguard Worker 	se->valid_blocks++;
43*59bfda1fSAndroid Build Coastguard Worker 	f2fs_set_bit(offset, (char *)se->cur_valid_map);
44*59bfda1fSAndroid Build Coastguard Worker 	se->dirty = 1;
45*59bfda1fSAndroid Build Coastguard Worker 
46*59bfda1fSAndroid Build Coastguard Worker 	/* read/write SSA */
47*59bfda1fSAndroid Build Coastguard Worker 	get_sum_entry(sbi, from, &sum);
48*59bfda1fSAndroid Build Coastguard Worker 	update_sum_entry(sbi, to, &sum);
49*59bfda1fSAndroid Build Coastguard Worker 
50*59bfda1fSAndroid Build Coastguard Worker 	/* if data block, read node and update node block */
51*59bfda1fSAndroid Build Coastguard Worker 	if (IS_DATASEG(type))
52*59bfda1fSAndroid Build Coastguard Worker 		update_data_blkaddr(sbi, le32_to_cpu(sum.nid),
53*59bfda1fSAndroid Build Coastguard Worker 				le16_to_cpu(sum.ofs_in_node), to, NULL);
54*59bfda1fSAndroid Build Coastguard Worker 	else
55*59bfda1fSAndroid Build Coastguard Worker 		update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to);
56*59bfda1fSAndroid Build Coastguard Worker 
57*59bfda1fSAndroid Build Coastguard Worker 	DBG(1, "Migrate %s block %"PRIx64" -> %"PRIx64"\n",
58*59bfda1fSAndroid Build Coastguard Worker 					IS_DATASEG(type) ? "data" : "node",
59*59bfda1fSAndroid Build Coastguard Worker 					from, to);
60*59bfda1fSAndroid Build Coastguard Worker 	free(raw);
61*59bfda1fSAndroid Build Coastguard Worker 	return 0;
62*59bfda1fSAndroid Build Coastguard Worker }
63*59bfda1fSAndroid Build Coastguard Worker 
f2fs_defragment(struct f2fs_sb_info * sbi,u64 from,u64 len,u64 to,int left)64*59bfda1fSAndroid Build Coastguard Worker int f2fs_defragment(struct f2fs_sb_info *sbi, u64 from, u64 len, u64 to, int left)
65*59bfda1fSAndroid Build Coastguard Worker {
66*59bfda1fSAndroid Build Coastguard Worker 	struct seg_entry *se;
67*59bfda1fSAndroid Build Coastguard Worker 	u64 idx, offset;
68*59bfda1fSAndroid Build Coastguard Worker 
69*59bfda1fSAndroid Build Coastguard Worker 	/* flush NAT/SIT journal entries */
70*59bfda1fSAndroid Build Coastguard Worker 	flush_journal_entries(sbi);
71*59bfda1fSAndroid Build Coastguard Worker 
72*59bfda1fSAndroid Build Coastguard Worker 	for (idx = from; idx < from + len; idx++) {
73*59bfda1fSAndroid Build Coastguard Worker 		u64 target = to;
74*59bfda1fSAndroid Build Coastguard Worker 
75*59bfda1fSAndroid Build Coastguard Worker 		se = get_seg_entry(sbi, GET_SEGNO(sbi, idx));
76*59bfda1fSAndroid Build Coastguard Worker 		offset = OFFSET_IN_SEG(sbi, idx);
77*59bfda1fSAndroid Build Coastguard Worker 
78*59bfda1fSAndroid Build Coastguard Worker 		if (!f2fs_test_bit(offset, (const char *)se->cur_valid_map))
79*59bfda1fSAndroid Build Coastguard Worker 			continue;
80*59bfda1fSAndroid Build Coastguard Worker 
81*59bfda1fSAndroid Build Coastguard Worker 		if (find_next_free_block(sbi, &target, left, se->type, false)) {
82*59bfda1fSAndroid Build Coastguard Worker 			MSG(0, "Not enough space to migrate blocks");
83*59bfda1fSAndroid Build Coastguard Worker 			return -1;
84*59bfda1fSAndroid Build Coastguard Worker 		}
85*59bfda1fSAndroid Build Coastguard Worker 
86*59bfda1fSAndroid Build Coastguard Worker 		if (migrate_block(sbi, idx, target)) {
87*59bfda1fSAndroid Build Coastguard Worker 			ASSERT_MSG("Found inconsistency: please run FSCK");
88*59bfda1fSAndroid Build Coastguard Worker 			return -1;
89*59bfda1fSAndroid Build Coastguard Worker 		}
90*59bfda1fSAndroid Build Coastguard Worker 	}
91*59bfda1fSAndroid Build Coastguard Worker 
92*59bfda1fSAndroid Build Coastguard Worker 	/* update curseg info; can update sit->types */
93*59bfda1fSAndroid Build Coastguard Worker 	move_curseg_info(sbi, to, left);
94*59bfda1fSAndroid Build Coastguard Worker 	zero_journal_entries(sbi);
95*59bfda1fSAndroid Build Coastguard Worker 	write_curseg_info(sbi);
96*59bfda1fSAndroid Build Coastguard Worker 
97*59bfda1fSAndroid Build Coastguard Worker 	/* flush dirty sit entries */
98*59bfda1fSAndroid Build Coastguard Worker 	flush_sit_entries(sbi);
99*59bfda1fSAndroid Build Coastguard Worker 
100*59bfda1fSAndroid Build Coastguard Worker 	write_checkpoint(sbi);
101*59bfda1fSAndroid Build Coastguard Worker 
102*59bfda1fSAndroid Build Coastguard Worker 	return 0;
103*59bfda1fSAndroid Build Coastguard Worker }
104