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