1*288bf522SAndroid Build Coastguard Worker #define _LARGEFILE64_SOURCE
2*288bf522SAndroid Build Coastguard Worker
3*288bf522SAndroid Build Coastguard Worker #define LOG_TAG "f2fs_sparseblock"
4*288bf522SAndroid Build Coastguard Worker
5*288bf522SAndroid Build Coastguard Worker #include "f2fs_sparseblock.h"
6*288bf522SAndroid Build Coastguard Worker
7*288bf522SAndroid Build Coastguard Worker #include <errno.h>
8*288bf522SAndroid Build Coastguard Worker #include <f2fs_fs.h>
9*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
10*288bf522SAndroid Build Coastguard Worker #include <linux/types.h>
11*288bf522SAndroid Build Coastguard Worker #include <malloc.h>
12*288bf522SAndroid Build Coastguard Worker #include <string.h>
13*288bf522SAndroid Build Coastguard Worker #include <sys/stat.h>
14*288bf522SAndroid Build Coastguard Worker #include <sys/types.h>
15*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #include <log/log.h>
18*288bf522SAndroid Build Coastguard Worker
19*288bf522SAndroid Build Coastguard Worker #define D_DISP_u32(ptr, member) \
20*288bf522SAndroid Build Coastguard Worker do { \
21*288bf522SAndroid Build Coastguard Worker SLOGV("%-30s" \
22*288bf522SAndroid Build Coastguard Worker "\t\t[0x%#08x : %u]\n", \
23*288bf522SAndroid Build Coastguard Worker #member, le32_to_cpu((ptr)->member), le32_to_cpu((ptr)->member)); \
24*288bf522SAndroid Build Coastguard Worker } while (0);
25*288bf522SAndroid Build Coastguard Worker
26*288bf522SAndroid Build Coastguard Worker #define D_DISP_u64(ptr, member) \
27*288bf522SAndroid Build Coastguard Worker do { \
28*288bf522SAndroid Build Coastguard Worker SLOGV("%-30s" \
29*288bf522SAndroid Build Coastguard Worker "\t\t[0x%#016" PRIx64 " : %" PRIu64 "]\n", \
30*288bf522SAndroid Build Coastguard Worker #member, le64_to_cpu((ptr)->member), le64_to_cpu((ptr)->member)); \
31*288bf522SAndroid Build Coastguard Worker } while (0);
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker #define segno_in_journal(jnl, i) ((jnl)->sit_j.entries[i].segno)
34*288bf522SAndroid Build Coastguard Worker
35*288bf522SAndroid Build Coastguard Worker #define sit_in_journal(jnl, i) ((jnl)->sit_j.entries[i].se)
36*288bf522SAndroid Build Coastguard Worker
37*288bf522SAndroid Build Coastguard Worker /* Default to 4K blocks. Will replace with actual blocksize when we read superblock */
38*288bf522SAndroid Build Coastguard Worker struct f2fs_configuration c = {.blksize = 4096, .blksize_bits = 12};
39*288bf522SAndroid Build Coastguard Worker
dbg_print_raw_sb_info(struct f2fs_super_block * sb)40*288bf522SAndroid Build Coastguard Worker static void dbg_print_raw_sb_info(struct f2fs_super_block* sb) {
41*288bf522SAndroid Build Coastguard Worker SLOGV("\n");
42*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
43*288bf522SAndroid Build Coastguard Worker SLOGV("| Super block |\n");
44*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
45*288bf522SAndroid Build Coastguard Worker
46*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, magic);
47*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, major_ver);
48*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, minor_ver);
49*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, log_sectorsize);
50*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, log_sectors_per_block);
51*288bf522SAndroid Build Coastguard Worker
52*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, log_blocksize);
53*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, log_blocks_per_seg);
54*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segs_per_sec);
55*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, secs_per_zone);
56*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, checksum_offset);
57*288bf522SAndroid Build Coastguard Worker D_DISP_u64(sb, block_count);
58*288bf522SAndroid Build Coastguard Worker
59*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, section_count);
60*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count);
61*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count_ckpt);
62*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count_sit);
63*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count_nat);
64*288bf522SAndroid Build Coastguard Worker
65*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count_ssa);
66*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment_count_main);
67*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, segment0_blkaddr);
68*288bf522SAndroid Build Coastguard Worker
69*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, cp_blkaddr);
70*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, sit_blkaddr);
71*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, nat_blkaddr);
72*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, ssa_blkaddr);
73*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, main_blkaddr);
74*288bf522SAndroid Build Coastguard Worker
75*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, root_ino);
76*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, node_ino);
77*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, meta_ino);
78*288bf522SAndroid Build Coastguard Worker D_DISP_u32(sb, cp_payload);
79*288bf522SAndroid Build Coastguard Worker SLOGV("\n");
80*288bf522SAndroid Build Coastguard Worker }
dbg_print_raw_ckpt_struct(struct f2fs_checkpoint * cp)81*288bf522SAndroid Build Coastguard Worker static void dbg_print_raw_ckpt_struct(struct f2fs_checkpoint* cp) {
82*288bf522SAndroid Build Coastguard Worker SLOGV("\n");
83*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
84*288bf522SAndroid Build Coastguard Worker SLOGV("| Checkpoint |\n");
85*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
86*288bf522SAndroid Build Coastguard Worker
87*288bf522SAndroid Build Coastguard Worker D_DISP_u64(cp, checkpoint_ver);
88*288bf522SAndroid Build Coastguard Worker D_DISP_u64(cp, user_block_count);
89*288bf522SAndroid Build Coastguard Worker D_DISP_u64(cp, valid_block_count);
90*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, rsvd_segment_count);
91*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, overprov_segment_count);
92*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, free_segment_count);
93*288bf522SAndroid Build Coastguard Worker
94*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_HOT_NODE]);
95*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_WARM_NODE]);
96*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_COLD_NODE]);
97*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_segno[0]);
98*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_segno[1]);
99*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_segno[2]);
100*288bf522SAndroid Build Coastguard Worker
101*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_blkoff[0]);
102*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_blkoff[1]);
103*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_node_blkoff[2]);
104*288bf522SAndroid Build Coastguard Worker
105*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_HOT_DATA]);
106*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_WARM_DATA]);
107*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, alloc_type[CURSEG_COLD_DATA]);
108*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_segno[0]);
109*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_segno[1]);
110*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_segno[2]);
111*288bf522SAndroid Build Coastguard Worker
112*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_blkoff[0]);
113*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_blkoff[1]);
114*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cur_data_blkoff[2]);
115*288bf522SAndroid Build Coastguard Worker
116*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, ckpt_flags);
117*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cp_pack_total_block_count);
118*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, cp_pack_start_sum);
119*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, valid_node_count);
120*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, valid_inode_count);
121*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, next_free_nid);
122*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, sit_ver_bitmap_bytesize);
123*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, nat_ver_bitmap_bytesize);
124*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, checksum_offset);
125*288bf522SAndroid Build Coastguard Worker D_DISP_u64(cp, elapsed_time);
126*288bf522SAndroid Build Coastguard Worker
127*288bf522SAndroid Build Coastguard Worker D_DISP_u32(cp, sit_nat_version_bitmap[0]);
128*288bf522SAndroid Build Coastguard Worker SLOGV("\n\n");
129*288bf522SAndroid Build Coastguard Worker }
130*288bf522SAndroid Build Coastguard Worker
dbg_print_info_struct(struct f2fs_info * info)131*288bf522SAndroid Build Coastguard Worker static void dbg_print_info_struct(struct f2fs_info* info) {
132*288bf522SAndroid Build Coastguard Worker SLOGV("\n");
133*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
134*288bf522SAndroid Build Coastguard Worker SLOGV("| F2FS_INFO |\n");
135*288bf522SAndroid Build Coastguard Worker SLOGV("+--------------------------------------------------------+\n");
136*288bf522SAndroid Build Coastguard Worker SLOGV("blocks_per_segment: %" PRIu64, info->blocks_per_segment);
137*288bf522SAndroid Build Coastguard Worker SLOGV("block_size: %d", info->block_size);
138*288bf522SAndroid Build Coastguard Worker SLOGV("sit_bmp loc: %p", info->sit_bmp);
139*288bf522SAndroid Build Coastguard Worker SLOGV("sit_bmp_size: %d", info->sit_bmp_size);
140*288bf522SAndroid Build Coastguard Worker SLOGV("blocks_per_sit: %" PRIu64, info->blocks_per_sit);
141*288bf522SAndroid Build Coastguard Worker SLOGV("sit_blocks loc: %p", info->sit_blocks);
142*288bf522SAndroid Build Coastguard Worker SLOGV("sit_sums loc: %p", info->sit_sums);
143*288bf522SAndroid Build Coastguard Worker SLOGV("sit_sums num: %d", le16_to_cpu(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums)->n_sits));
144*288bf522SAndroid Build Coastguard Worker unsigned int i;
145*288bf522SAndroid Build Coastguard Worker for (i = 0; i < (le16_to_cpu(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums)->n_sits)); i++) {
146*288bf522SAndroid Build Coastguard Worker SLOGV("entry %d in journal entries is for segment %d", i,
147*288bf522SAndroid Build Coastguard Worker le32_to_cpu(segno_in_journal(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums), i)));
148*288bf522SAndroid Build Coastguard Worker }
149*288bf522SAndroid Build Coastguard Worker
150*288bf522SAndroid Build Coastguard Worker SLOGV("cp_blkaddr: %" PRIu64, info->cp_blkaddr);
151*288bf522SAndroid Build Coastguard Worker SLOGV("cp_valid_cp_blkaddr: %" PRIu64, info->cp_valid_cp_blkaddr);
152*288bf522SAndroid Build Coastguard Worker SLOGV("sit_blkaddr: %" PRIu64, info->sit_blkaddr);
153*288bf522SAndroid Build Coastguard Worker SLOGV("nat_blkaddr: %" PRIu64, info->nat_blkaddr);
154*288bf522SAndroid Build Coastguard Worker SLOGV("ssa_blkaddr: %" PRIu64, info->ssa_blkaddr);
155*288bf522SAndroid Build Coastguard Worker SLOGV("main_blkaddr: %" PRIu64, info->main_blkaddr);
156*288bf522SAndroid Build Coastguard Worker SLOGV("total_user_used: %" PRIu64, info->total_user_used);
157*288bf522SAndroid Build Coastguard Worker SLOGV("total_blocks: %" PRIu64, info->total_blocks);
158*288bf522SAndroid Build Coastguard Worker SLOGV("\n\n");
159*288bf522SAndroid Build Coastguard Worker }
160*288bf522SAndroid Build Coastguard Worker
161*288bf522SAndroid Build Coastguard Worker /* read blocks */
read_structure(int fd,unsigned long long start,void * buf,ssize_t len)162*288bf522SAndroid Build Coastguard Worker static int read_structure(int fd, unsigned long long start, void* buf, ssize_t len) {
163*288bf522SAndroid Build Coastguard Worker off64_t ret;
164*288bf522SAndroid Build Coastguard Worker
165*288bf522SAndroid Build Coastguard Worker ret = lseek64(fd, start, SEEK_SET);
166*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
167*288bf522SAndroid Build Coastguard Worker SLOGE("failed to seek\n");
168*288bf522SAndroid Build Coastguard Worker return ret;
169*288bf522SAndroid Build Coastguard Worker }
170*288bf522SAndroid Build Coastguard Worker
171*288bf522SAndroid Build Coastguard Worker ret = read(fd, buf, len);
172*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
173*288bf522SAndroid Build Coastguard Worker SLOGE("failed to read\n");
174*288bf522SAndroid Build Coastguard Worker return ret;
175*288bf522SAndroid Build Coastguard Worker }
176*288bf522SAndroid Build Coastguard Worker if (ret != len) {
177*288bf522SAndroid Build Coastguard Worker SLOGE("failed to read all\n");
178*288bf522SAndroid Build Coastguard Worker return -1;
179*288bf522SAndroid Build Coastguard Worker }
180*288bf522SAndroid Build Coastguard Worker return 0;
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker
read_structure_blk(int fd,unsigned long long start_blk,void * buf,size_t len)183*288bf522SAndroid Build Coastguard Worker static int read_structure_blk(int fd, unsigned long long start_blk, void* buf, size_t len) {
184*288bf522SAndroid Build Coastguard Worker return read_structure(fd, F2FS_BLKSIZE * start_blk, buf, F2FS_BLKSIZE * len);
185*288bf522SAndroid Build Coastguard Worker }
186*288bf522SAndroid Build Coastguard Worker
read_f2fs_sb(int fd,struct f2fs_super_block * sb)187*288bf522SAndroid Build Coastguard Worker static int read_f2fs_sb(int fd, struct f2fs_super_block* sb) {
188*288bf522SAndroid Build Coastguard Worker int rc;
189*288bf522SAndroid Build Coastguard Worker rc = read_structure(fd, F2FS_SUPER_OFFSET, sb, sizeof(*sb));
190*288bf522SAndroid Build Coastguard Worker if (le32_to_cpu(sb->magic) != F2FS_SUPER_MAGIC) {
191*288bf522SAndroid Build Coastguard Worker SLOGE("Not a valid F2FS super block. Magic:%#08x != %#08x", le32_to_cpu(sb->magic),
192*288bf522SAndroid Build Coastguard Worker F2FS_SUPER_MAGIC);
193*288bf522SAndroid Build Coastguard Worker return -1;
194*288bf522SAndroid Build Coastguard Worker }
195*288bf522SAndroid Build Coastguard Worker return 0;
196*288bf522SAndroid Build Coastguard Worker }
197*288bf522SAndroid Build Coastguard Worker
get_f2fs_filesystem_size_sec(char * dev)198*288bf522SAndroid Build Coastguard Worker unsigned int get_f2fs_filesystem_size_sec(char* dev) {
199*288bf522SAndroid Build Coastguard Worker int fd;
200*288bf522SAndroid Build Coastguard Worker if ((fd = open(dev, O_RDONLY)) < 0) {
201*288bf522SAndroid Build Coastguard Worker SLOGE("Cannot open device to get filesystem size ");
202*288bf522SAndroid Build Coastguard Worker return 0;
203*288bf522SAndroid Build Coastguard Worker }
204*288bf522SAndroid Build Coastguard Worker struct f2fs_super_block sb;
205*288bf522SAndroid Build Coastguard Worker if (read_f2fs_sb(fd, &sb)) return 0;
206*288bf522SAndroid Build Coastguard Worker return (unsigned int)(le64_to_cpu(sb.block_count) * F2FS_BLKSIZE / DEFAULT_SECTOR_SIZE);
207*288bf522SAndroid Build Coastguard Worker }
208*288bf522SAndroid Build Coastguard Worker
validate_checkpoint(block_t cp_addr,unsigned long long * version,int fd)209*288bf522SAndroid Build Coastguard Worker static struct f2fs_checkpoint* validate_checkpoint(block_t cp_addr, unsigned long long* version,
210*288bf522SAndroid Build Coastguard Worker int fd) {
211*288bf522SAndroid Build Coastguard Worker unsigned char *cp_block_1, *cp_block_2;
212*288bf522SAndroid Build Coastguard Worker struct f2fs_checkpoint* cp_block;
213*288bf522SAndroid Build Coastguard Worker uint64_t cp1_version = 0, cp2_version = 0;
214*288bf522SAndroid Build Coastguard Worker
215*288bf522SAndroid Build Coastguard Worker cp_block_1 = malloc(F2FS_BLKSIZE);
216*288bf522SAndroid Build Coastguard Worker if (!cp_block_1) return NULL;
217*288bf522SAndroid Build Coastguard Worker
218*288bf522SAndroid Build Coastguard Worker /* Read the 1st cp block in this CP pack */
219*288bf522SAndroid Build Coastguard Worker if (read_structure_blk(fd, cp_addr, cp_block_1, 1)) goto invalid_cp1;
220*288bf522SAndroid Build Coastguard Worker
221*288bf522SAndroid Build Coastguard Worker /* get the version number */
222*288bf522SAndroid Build Coastguard Worker cp_block = (struct f2fs_checkpoint*)cp_block_1;
223*288bf522SAndroid Build Coastguard Worker
224*288bf522SAndroid Build Coastguard Worker cp1_version = le64_to_cpu(cp_block->checkpoint_ver);
225*288bf522SAndroid Build Coastguard Worker
226*288bf522SAndroid Build Coastguard Worker cp_block_2 = malloc(F2FS_BLKSIZE);
227*288bf522SAndroid Build Coastguard Worker if (!cp_block_2) {
228*288bf522SAndroid Build Coastguard Worker goto invalid_cp1;
229*288bf522SAndroid Build Coastguard Worker }
230*288bf522SAndroid Build Coastguard Worker /* Read the 2nd cp block in this CP pack */
231*288bf522SAndroid Build Coastguard Worker cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
232*288bf522SAndroid Build Coastguard Worker if (read_structure_blk(fd, cp_addr, cp_block_2, 1)) {
233*288bf522SAndroid Build Coastguard Worker goto invalid_cp2;
234*288bf522SAndroid Build Coastguard Worker }
235*288bf522SAndroid Build Coastguard Worker
236*288bf522SAndroid Build Coastguard Worker cp_block = (struct f2fs_checkpoint*)cp_block_2;
237*288bf522SAndroid Build Coastguard Worker
238*288bf522SAndroid Build Coastguard Worker cp2_version = le64_to_cpu(cp_block->checkpoint_ver);
239*288bf522SAndroid Build Coastguard Worker
240*288bf522SAndroid Build Coastguard Worker if (cp2_version == cp1_version) {
241*288bf522SAndroid Build Coastguard Worker *version = cp2_version;
242*288bf522SAndroid Build Coastguard Worker free(cp_block_2);
243*288bf522SAndroid Build Coastguard Worker return (struct f2fs_checkpoint*)cp_block_1;
244*288bf522SAndroid Build Coastguard Worker }
245*288bf522SAndroid Build Coastguard Worker
246*288bf522SAndroid Build Coastguard Worker /* There must be something wrong with this checkpoint */
247*288bf522SAndroid Build Coastguard Worker invalid_cp2:
248*288bf522SAndroid Build Coastguard Worker free(cp_block_2);
249*288bf522SAndroid Build Coastguard Worker invalid_cp1:
250*288bf522SAndroid Build Coastguard Worker free(cp_block_1);
251*288bf522SAndroid Build Coastguard Worker return NULL;
252*288bf522SAndroid Build Coastguard Worker }
253*288bf522SAndroid Build Coastguard Worker
get_valid_checkpoint_info(int fd,struct f2fs_super_block * sb,struct f2fs_checkpoint ** cp,struct f2fs_info * info)254*288bf522SAndroid Build Coastguard Worker int get_valid_checkpoint_info(int fd, struct f2fs_super_block* sb, struct f2fs_checkpoint** cp,
255*288bf522SAndroid Build Coastguard Worker struct f2fs_info* info) {
256*288bf522SAndroid Build Coastguard Worker struct f2fs_checkpoint *cp1, *cp2, *cur_cp;
257*288bf522SAndroid Build Coastguard Worker unsigned long blk_size;
258*288bf522SAndroid Build Coastguard Worker unsigned long long cp1_version = 0, cp2_version = 0;
259*288bf522SAndroid Build Coastguard Worker unsigned long long cp1_start_blk_no;
260*288bf522SAndroid Build Coastguard Worker unsigned long long cp2_start_blk_no;
261*288bf522SAndroid Build Coastguard Worker
262*288bf522SAndroid Build Coastguard Worker blk_size = 1U << le32_to_cpu(sb->log_blocksize);
263*288bf522SAndroid Build Coastguard Worker
264*288bf522SAndroid Build Coastguard Worker /*
265*288bf522SAndroid Build Coastguard Worker * Find valid cp by reading both packs and finding most recent one.
266*288bf522SAndroid Build Coastguard Worker */
267*288bf522SAndroid Build Coastguard Worker cp1_start_blk_no = le32_to_cpu(sb->cp_blkaddr);
268*288bf522SAndroid Build Coastguard Worker cp1 = validate_checkpoint(cp1_start_blk_no, &cp1_version, fd);
269*288bf522SAndroid Build Coastguard Worker
270*288bf522SAndroid Build Coastguard Worker /* The second checkpoint pack should start at the next segment */
271*288bf522SAndroid Build Coastguard Worker cp2_start_blk_no = cp1_start_blk_no + (1 << le32_to_cpu(sb->log_blocks_per_seg));
272*288bf522SAndroid Build Coastguard Worker cp2 = validate_checkpoint(cp2_start_blk_no, &cp2_version, fd);
273*288bf522SAndroid Build Coastguard Worker
274*288bf522SAndroid Build Coastguard Worker if (cp1 && cp2) {
275*288bf522SAndroid Build Coastguard Worker if (ver_after(cp2_version, cp1_version)) {
276*288bf522SAndroid Build Coastguard Worker cur_cp = cp2;
277*288bf522SAndroid Build Coastguard Worker info->cp_valid_cp_blkaddr = cp2_start_blk_no;
278*288bf522SAndroid Build Coastguard Worker free(cp1);
279*288bf522SAndroid Build Coastguard Worker } else {
280*288bf522SAndroid Build Coastguard Worker cur_cp = cp1;
281*288bf522SAndroid Build Coastguard Worker info->cp_valid_cp_blkaddr = cp1_start_blk_no;
282*288bf522SAndroid Build Coastguard Worker free(cp2);
283*288bf522SAndroid Build Coastguard Worker }
284*288bf522SAndroid Build Coastguard Worker } else if (cp1) {
285*288bf522SAndroid Build Coastguard Worker cur_cp = cp1;
286*288bf522SAndroid Build Coastguard Worker info->cp_valid_cp_blkaddr = cp1_start_blk_no;
287*288bf522SAndroid Build Coastguard Worker } else if (cp2) {
288*288bf522SAndroid Build Coastguard Worker cur_cp = cp2;
289*288bf522SAndroid Build Coastguard Worker info->cp_valid_cp_blkaddr = cp2_start_blk_no;
290*288bf522SAndroid Build Coastguard Worker } else {
291*288bf522SAndroid Build Coastguard Worker goto fail_no_cp;
292*288bf522SAndroid Build Coastguard Worker }
293*288bf522SAndroid Build Coastguard Worker
294*288bf522SAndroid Build Coastguard Worker *cp = cur_cp;
295*288bf522SAndroid Build Coastguard Worker
296*288bf522SAndroid Build Coastguard Worker return 0;
297*288bf522SAndroid Build Coastguard Worker
298*288bf522SAndroid Build Coastguard Worker fail_no_cp:
299*288bf522SAndroid Build Coastguard Worker SLOGE("Valid Checkpoint not found!!");
300*288bf522SAndroid Build Coastguard Worker return -EINVAL;
301*288bf522SAndroid Build Coastguard Worker }
302*288bf522SAndroid Build Coastguard Worker
get_sit_block(struct f2fs_info * info,uint64_t sit_block)303*288bf522SAndroid Build Coastguard Worker static inline struct f2fs_sit_block* get_sit_block(struct f2fs_info* info, uint64_t sit_block) {
304*288bf522SAndroid Build Coastguard Worker return (struct f2fs_sit_block*)((char*)info->sit_blocks + sit_block * F2FS_BLKSIZE);
305*288bf522SAndroid Build Coastguard Worker }
306*288bf522SAndroid Build Coastguard Worker
gather_sit_info(int fd,struct f2fs_info * info)307*288bf522SAndroid Build Coastguard Worker static int gather_sit_info(int fd, struct f2fs_info* info) {
308*288bf522SAndroid Build Coastguard Worker uint64_t num_segments =
309*288bf522SAndroid Build Coastguard Worker (info->total_blocks - info->main_blkaddr + info->blocks_per_segment - 1) /
310*288bf522SAndroid Build Coastguard Worker info->blocks_per_segment;
311*288bf522SAndroid Build Coastguard Worker uint64_t num_sit_blocks = (num_segments + SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK;
312*288bf522SAndroid Build Coastguard Worker uint64_t sit_block;
313*288bf522SAndroid Build Coastguard Worker
314*288bf522SAndroid Build Coastguard Worker info->sit_blocks = malloc(num_sit_blocks * F2FS_BLKSIZE);
315*288bf522SAndroid Build Coastguard Worker if (!info->sit_blocks) return -1;
316*288bf522SAndroid Build Coastguard Worker
317*288bf522SAndroid Build Coastguard Worker for (sit_block = 0; sit_block < num_sit_blocks; sit_block++) {
318*288bf522SAndroid Build Coastguard Worker off64_t address = info->sit_blkaddr + sit_block;
319*288bf522SAndroid Build Coastguard Worker
320*288bf522SAndroid Build Coastguard Worker if (f2fs_test_bit(sit_block, info->sit_bmp)) address += info->blocks_per_sit;
321*288bf522SAndroid Build Coastguard Worker
322*288bf522SAndroid Build Coastguard Worker SLOGV("Reading cache block starting at block %" PRIu64, address);
323*288bf522SAndroid Build Coastguard Worker if (read_structure(fd, address * F2FS_BLKSIZE, get_sit_block(info, sit_block),
324*288bf522SAndroid Build Coastguard Worker F2FS_BLKSIZE)) {
325*288bf522SAndroid Build Coastguard Worker SLOGE("Could not read sit block at block %" PRIu64, address);
326*288bf522SAndroid Build Coastguard Worker free(info->sit_blocks);
327*288bf522SAndroid Build Coastguard Worker info->sit_blocks = NULL;
328*288bf522SAndroid Build Coastguard Worker return -1;
329*288bf522SAndroid Build Coastguard Worker }
330*288bf522SAndroid Build Coastguard Worker }
331*288bf522SAndroid Build Coastguard Worker return 0;
332*288bf522SAndroid Build Coastguard Worker }
333*288bf522SAndroid Build Coastguard Worker
is_set_ckpt_flags(struct f2fs_checkpoint * cp,unsigned int f)334*288bf522SAndroid Build Coastguard Worker static inline int is_set_ckpt_flags(struct f2fs_checkpoint* cp, unsigned int f) {
335*288bf522SAndroid Build Coastguard Worker unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
336*288bf522SAndroid Build Coastguard Worker return !!(ckpt_flags & f);
337*288bf522SAndroid Build Coastguard Worker }
338*288bf522SAndroid Build Coastguard Worker
sum_blk_addr(struct f2fs_checkpoint * cp,struct f2fs_info * info,int base,int type)339*288bf522SAndroid Build Coastguard Worker static inline uint64_t sum_blk_addr(struct f2fs_checkpoint* cp, struct f2fs_info* info, int base,
340*288bf522SAndroid Build Coastguard Worker int type) {
341*288bf522SAndroid Build Coastguard Worker return info->cp_valid_cp_blkaddr + le32_to_cpu(cp->cp_pack_total_block_count) - (base + 1) +
342*288bf522SAndroid Build Coastguard Worker type;
343*288bf522SAndroid Build Coastguard Worker }
344*288bf522SAndroid Build Coastguard Worker
get_sit_summary(int fd,struct f2fs_info * info,struct f2fs_checkpoint * cp)345*288bf522SAndroid Build Coastguard Worker static int get_sit_summary(int fd, struct f2fs_info* info, struct f2fs_checkpoint* cp) {
346*288bf522SAndroid Build Coastguard Worker char buffer[F2FS_BLKSIZE];
347*288bf522SAndroid Build Coastguard Worker
348*288bf522SAndroid Build Coastguard Worker info->sit_sums = calloc(1, F2FS_BLKSIZE);
349*288bf522SAndroid Build Coastguard Worker if (!info->sit_sums) return -1;
350*288bf522SAndroid Build Coastguard Worker
351*288bf522SAndroid Build Coastguard Worker /* CURSEG_COLD_DATA where the journaled SIT entries are. */
352*288bf522SAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_COMPACT_SUM_FLAG)) {
353*288bf522SAndroid Build Coastguard Worker if (read_structure_blk(fd, info->cp_valid_cp_blkaddr + le32_to_cpu(cp->cp_pack_start_sum),
354*288bf522SAndroid Build Coastguard Worker buffer, 1))
355*288bf522SAndroid Build Coastguard Worker return -1;
356*288bf522SAndroid Build Coastguard Worker memcpy(&F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums)->n_sits, &buffer[SUM_JOURNAL_SIZE],
357*288bf522SAndroid Build Coastguard Worker SUM_JOURNAL_SIZE);
358*288bf522SAndroid Build Coastguard Worker } else {
359*288bf522SAndroid Build Coastguard Worker uint64_t blk_addr;
360*288bf522SAndroid Build Coastguard Worker if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG))
361*288bf522SAndroid Build Coastguard Worker blk_addr = sum_blk_addr(cp, info, NR_CURSEG_TYPE, CURSEG_COLD_DATA);
362*288bf522SAndroid Build Coastguard Worker else
363*288bf522SAndroid Build Coastguard Worker blk_addr = sum_blk_addr(cp, info, NR_CURSEG_DATA_TYPE, CURSEG_COLD_DATA);
364*288bf522SAndroid Build Coastguard Worker
365*288bf522SAndroid Build Coastguard Worker if (read_structure_blk(fd, blk_addr, buffer, 1)) return -1;
366*288bf522SAndroid Build Coastguard Worker
367*288bf522SAndroid Build Coastguard Worker memcpy(info->sit_sums, buffer, F2FS_BLKSIZE);
368*288bf522SAndroid Build Coastguard Worker }
369*288bf522SAndroid Build Coastguard Worker return 0;
370*288bf522SAndroid Build Coastguard Worker }
371*288bf522SAndroid Build Coastguard Worker
generate_f2fs_info(int fd)372*288bf522SAndroid Build Coastguard Worker struct f2fs_info* generate_f2fs_info(int fd) {
373*288bf522SAndroid Build Coastguard Worker struct f2fs_super_block* sb = NULL;
374*288bf522SAndroid Build Coastguard Worker struct f2fs_checkpoint* cp = NULL;
375*288bf522SAndroid Build Coastguard Worker struct f2fs_info* info;
376*288bf522SAndroid Build Coastguard Worker
377*288bf522SAndroid Build Coastguard Worker info = calloc(1, sizeof(*info));
378*288bf522SAndroid Build Coastguard Worker if (!info) {
379*288bf522SAndroid Build Coastguard Worker SLOGE("Out of memory!");
380*288bf522SAndroid Build Coastguard Worker return NULL;
381*288bf522SAndroid Build Coastguard Worker }
382*288bf522SAndroid Build Coastguard Worker
383*288bf522SAndroid Build Coastguard Worker sb = malloc(sizeof(*sb));
384*288bf522SAndroid Build Coastguard Worker if (!sb) {
385*288bf522SAndroid Build Coastguard Worker SLOGE("Out of memory!");
386*288bf522SAndroid Build Coastguard Worker free(info);
387*288bf522SAndroid Build Coastguard Worker return NULL;
388*288bf522SAndroid Build Coastguard Worker }
389*288bf522SAndroid Build Coastguard Worker if (read_f2fs_sb(fd, sb)) {
390*288bf522SAndroid Build Coastguard Worker SLOGE("Failed to read superblock");
391*288bf522SAndroid Build Coastguard Worker free(info);
392*288bf522SAndroid Build Coastguard Worker free(sb);
393*288bf522SAndroid Build Coastguard Worker return NULL;
394*288bf522SAndroid Build Coastguard Worker }
395*288bf522SAndroid Build Coastguard Worker c.blksize_bits = get_sb(log_blocksize);
396*288bf522SAndroid Build Coastguard Worker c.blksize = 1 << c.blksize_bits;
397*288bf522SAndroid Build Coastguard Worker dbg_print_raw_sb_info(sb);
398*288bf522SAndroid Build Coastguard Worker
399*288bf522SAndroid Build Coastguard Worker info->cp_blkaddr = le32_to_cpu(sb->cp_blkaddr);
400*288bf522SAndroid Build Coastguard Worker info->sit_blkaddr = le32_to_cpu(sb->sit_blkaddr);
401*288bf522SAndroid Build Coastguard Worker info->nat_blkaddr = le32_to_cpu(sb->nat_blkaddr);
402*288bf522SAndroid Build Coastguard Worker info->ssa_blkaddr = le32_to_cpu(sb->ssa_blkaddr);
403*288bf522SAndroid Build Coastguard Worker info->main_blkaddr = le32_to_cpu(sb->main_blkaddr);
404*288bf522SAndroid Build Coastguard Worker info->block_size = F2FS_BLKSIZE;
405*288bf522SAndroid Build Coastguard Worker info->total_blocks = sb->block_count;
406*288bf522SAndroid Build Coastguard Worker info->blocks_per_sit = (le32_to_cpu(sb->segment_count_sit) >> 1)
407*288bf522SAndroid Build Coastguard Worker << le32_to_cpu(sb->log_blocks_per_seg);
408*288bf522SAndroid Build Coastguard Worker info->blocks_per_segment = 1U << le32_to_cpu(sb->log_blocks_per_seg);
409*288bf522SAndroid Build Coastguard Worker
410*288bf522SAndroid Build Coastguard Worker if (get_valid_checkpoint_info(fd, sb, &cp, info)) goto error;
411*288bf522SAndroid Build Coastguard Worker dbg_print_raw_ckpt_struct(cp);
412*288bf522SAndroid Build Coastguard Worker
413*288bf522SAndroid Build Coastguard Worker info->total_user_used = le32_to_cpu(cp->valid_block_count);
414*288bf522SAndroid Build Coastguard Worker
415*288bf522SAndroid Build Coastguard Worker u32 bmp_size = le32_to_cpu(cp->sit_ver_bitmap_bytesize);
416*288bf522SAndroid Build Coastguard Worker
417*288bf522SAndroid Build Coastguard Worker /* get sit validity bitmap */
418*288bf522SAndroid Build Coastguard Worker info->sit_bmp = malloc(bmp_size);
419*288bf522SAndroid Build Coastguard Worker if (!info->sit_bmp) {
420*288bf522SAndroid Build Coastguard Worker SLOGE("Out of memory!");
421*288bf522SAndroid Build Coastguard Worker goto error;
422*288bf522SAndroid Build Coastguard Worker }
423*288bf522SAndroid Build Coastguard Worker
424*288bf522SAndroid Build Coastguard Worker info->sit_bmp_size = bmp_size;
425*288bf522SAndroid Build Coastguard Worker if (read_structure(fd,
426*288bf522SAndroid Build Coastguard Worker info->cp_valid_cp_blkaddr * F2FS_BLKSIZE +
427*288bf522SAndroid Build Coastguard Worker offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap),
428*288bf522SAndroid Build Coastguard Worker info->sit_bmp, bmp_size)) {
429*288bf522SAndroid Build Coastguard Worker SLOGE("Error getting SIT validity bitmap");
430*288bf522SAndroid Build Coastguard Worker goto error;
431*288bf522SAndroid Build Coastguard Worker }
432*288bf522SAndroid Build Coastguard Worker
433*288bf522SAndroid Build Coastguard Worker if (gather_sit_info(fd, info)) {
434*288bf522SAndroid Build Coastguard Worker SLOGE("Error getting SIT information");
435*288bf522SAndroid Build Coastguard Worker goto error;
436*288bf522SAndroid Build Coastguard Worker }
437*288bf522SAndroid Build Coastguard Worker if (get_sit_summary(fd, info, cp)) {
438*288bf522SAndroid Build Coastguard Worker SLOGE("Error getting SIT entries in summary area");
439*288bf522SAndroid Build Coastguard Worker goto error;
440*288bf522SAndroid Build Coastguard Worker }
441*288bf522SAndroid Build Coastguard Worker dbg_print_info_struct(info);
442*288bf522SAndroid Build Coastguard Worker return info;
443*288bf522SAndroid Build Coastguard Worker error:
444*288bf522SAndroid Build Coastguard Worker free(sb);
445*288bf522SAndroid Build Coastguard Worker free(cp);
446*288bf522SAndroid Build Coastguard Worker free_f2fs_info(info);
447*288bf522SAndroid Build Coastguard Worker return NULL;
448*288bf522SAndroid Build Coastguard Worker }
449*288bf522SAndroid Build Coastguard Worker
free_f2fs_info(struct f2fs_info * info)450*288bf522SAndroid Build Coastguard Worker void free_f2fs_info(struct f2fs_info* info) {
451*288bf522SAndroid Build Coastguard Worker if (info) {
452*288bf522SAndroid Build Coastguard Worker free(info->sit_blocks);
453*288bf522SAndroid Build Coastguard Worker info->sit_blocks = NULL;
454*288bf522SAndroid Build Coastguard Worker
455*288bf522SAndroid Build Coastguard Worker free(info->sit_bmp);
456*288bf522SAndroid Build Coastguard Worker info->sit_bmp = NULL;
457*288bf522SAndroid Build Coastguard Worker
458*288bf522SAndroid Build Coastguard Worker free(info->sit_sums);
459*288bf522SAndroid Build Coastguard Worker info->sit_sums = NULL;
460*288bf522SAndroid Build Coastguard Worker }
461*288bf522SAndroid Build Coastguard Worker free(info);
462*288bf522SAndroid Build Coastguard Worker }
463*288bf522SAndroid Build Coastguard Worker
get_num_blocks_used(struct f2fs_info * info)464*288bf522SAndroid Build Coastguard Worker uint64_t get_num_blocks_used(struct f2fs_info* info) {
465*288bf522SAndroid Build Coastguard Worker return info->main_blkaddr + info->total_user_used;
466*288bf522SAndroid Build Coastguard Worker }
467*288bf522SAndroid Build Coastguard Worker
f2fs_test_bit(unsigned int nr,const char * p)468*288bf522SAndroid Build Coastguard Worker int f2fs_test_bit(unsigned int nr, const char* p) {
469*288bf522SAndroid Build Coastguard Worker int mask;
470*288bf522SAndroid Build Coastguard Worker char* addr = (char*)p;
471*288bf522SAndroid Build Coastguard Worker
472*288bf522SAndroid Build Coastguard Worker addr += (nr >> 3);
473*288bf522SAndroid Build Coastguard Worker mask = 1 << (7 - (nr & 0x07));
474*288bf522SAndroid Build Coastguard Worker return (mask & *addr) != 0;
475*288bf522SAndroid Build Coastguard Worker }
476*288bf522SAndroid Build Coastguard Worker
run_on_used_blocks(uint64_t startblock,struct f2fs_info * info,int (* func)(uint64_t pos,void * data),void * data)477*288bf522SAndroid Build Coastguard Worker int run_on_used_blocks(uint64_t startblock, struct f2fs_info* info,
478*288bf522SAndroid Build Coastguard Worker int (*func)(uint64_t pos, void* data), void* data) {
479*288bf522SAndroid Build Coastguard Worker struct f2fs_sit_entry* sit_entry;
480*288bf522SAndroid Build Coastguard Worker uint64_t sit_block_num_cur = 0, segnum = 0, block_offset;
481*288bf522SAndroid Build Coastguard Worker uint64_t block;
482*288bf522SAndroid Build Coastguard Worker unsigned int used, found, i;
483*288bf522SAndroid Build Coastguard Worker
484*288bf522SAndroid Build Coastguard Worker block = startblock;
485*288bf522SAndroid Build Coastguard Worker while (block < info->total_blocks) {
486*288bf522SAndroid Build Coastguard Worker /* TODO: Save only relevant portions of metadata */
487*288bf522SAndroid Build Coastguard Worker if (block < info->main_blkaddr) {
488*288bf522SAndroid Build Coastguard Worker if (func(block, data)) {
489*288bf522SAndroid Build Coastguard Worker SLOGI("func error");
490*288bf522SAndroid Build Coastguard Worker return -1;
491*288bf522SAndroid Build Coastguard Worker }
492*288bf522SAndroid Build Coastguard Worker } else {
493*288bf522SAndroid Build Coastguard Worker /* Main Section */
494*288bf522SAndroid Build Coastguard Worker segnum = (block - info->main_blkaddr) / info->blocks_per_segment;
495*288bf522SAndroid Build Coastguard Worker
496*288bf522SAndroid Build Coastguard Worker /* check the SIT entries in the journal */
497*288bf522SAndroid Build Coastguard Worker found = 0;
498*288bf522SAndroid Build Coastguard Worker for (i = 0; i < le16_to_cpu(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums)->n_sits); i++) {
499*288bf522SAndroid Build Coastguard Worker if (le32_to_cpu(segno_in_journal(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums), i)) ==
500*288bf522SAndroid Build Coastguard Worker segnum) {
501*288bf522SAndroid Build Coastguard Worker sit_entry = &sit_in_journal(F2FS_SUMMARY_BLOCK_JOURNAL(info->sit_sums), i);
502*288bf522SAndroid Build Coastguard Worker found = 1;
503*288bf522SAndroid Build Coastguard Worker break;
504*288bf522SAndroid Build Coastguard Worker }
505*288bf522SAndroid Build Coastguard Worker }
506*288bf522SAndroid Build Coastguard Worker
507*288bf522SAndroid Build Coastguard Worker /* get SIT entry from SIT section */
508*288bf522SAndroid Build Coastguard Worker if (!found) {
509*288bf522SAndroid Build Coastguard Worker sit_block_num_cur = segnum / SIT_ENTRY_PER_BLOCK;
510*288bf522SAndroid Build Coastguard Worker sit_entry = &get_sit_block(info, sit_block_num_cur)
511*288bf522SAndroid Build Coastguard Worker ->entries[segnum % SIT_ENTRY_PER_BLOCK];
512*288bf522SAndroid Build Coastguard Worker }
513*288bf522SAndroid Build Coastguard Worker
514*288bf522SAndroid Build Coastguard Worker block_offset = (block - info->main_blkaddr) % info->blocks_per_segment;
515*288bf522SAndroid Build Coastguard Worker
516*288bf522SAndroid Build Coastguard Worker if (block_offset == 0 && GET_SIT_VBLOCKS(sit_entry) == 0) {
517*288bf522SAndroid Build Coastguard Worker block += info->blocks_per_segment;
518*288bf522SAndroid Build Coastguard Worker continue;
519*288bf522SAndroid Build Coastguard Worker }
520*288bf522SAndroid Build Coastguard Worker
521*288bf522SAndroid Build Coastguard Worker used = f2fs_test_bit(block_offset, (char*)sit_entry->valid_map);
522*288bf522SAndroid Build Coastguard Worker if (used)
523*288bf522SAndroid Build Coastguard Worker if (func(block, data)) return -1;
524*288bf522SAndroid Build Coastguard Worker }
525*288bf522SAndroid Build Coastguard Worker
526*288bf522SAndroid Build Coastguard Worker block++;
527*288bf522SAndroid Build Coastguard Worker }
528*288bf522SAndroid Build Coastguard Worker return 0;
529*288bf522SAndroid Build Coastguard Worker }
530*288bf522SAndroid Build Coastguard Worker
531*288bf522SAndroid Build Coastguard Worker struct privdata {
532*288bf522SAndroid Build Coastguard Worker int count;
533*288bf522SAndroid Build Coastguard Worker int infd;
534*288bf522SAndroid Build Coastguard Worker int outfd;
535*288bf522SAndroid Build Coastguard Worker char* buf;
536*288bf522SAndroid Build Coastguard Worker char* zbuf;
537*288bf522SAndroid Build Coastguard Worker int done;
538*288bf522SAndroid Build Coastguard Worker struct f2fs_info* info;
539*288bf522SAndroid Build Coastguard Worker };
540*288bf522SAndroid Build Coastguard Worker
541*288bf522SAndroid Build Coastguard Worker /*
542*288bf522SAndroid Build Coastguard Worker * This is a simple test program. It performs a block to block copy of a
543*288bf522SAndroid Build Coastguard Worker * filesystem, replacing blocks identified as unused with 0's.
544*288bf522SAndroid Build Coastguard Worker */
545*288bf522SAndroid Build Coastguard Worker
copy_used(uint64_t pos,void * data)546*288bf522SAndroid Build Coastguard Worker int copy_used(uint64_t pos, void* data) {
547*288bf522SAndroid Build Coastguard Worker struct privdata* d = data;
548*288bf522SAndroid Build Coastguard Worker char* buf;
549*288bf522SAndroid Build Coastguard Worker int pdone = (pos * 100) / d->info->total_blocks;
550*288bf522SAndroid Build Coastguard Worker if (pdone > d->done) {
551*288bf522SAndroid Build Coastguard Worker d->done = pdone;
552*288bf522SAndroid Build Coastguard Worker printf("Done with %d percent\n", d->done);
553*288bf522SAndroid Build Coastguard Worker }
554*288bf522SAndroid Build Coastguard Worker
555*288bf522SAndroid Build Coastguard Worker d->count++;
556*288bf522SAndroid Build Coastguard Worker buf = d->buf;
557*288bf522SAndroid Build Coastguard Worker if (read_structure_blk(d->infd, (unsigned long long)pos, d->buf, 1)) {
558*288bf522SAndroid Build Coastguard Worker printf("Error reading!!!\n");
559*288bf522SAndroid Build Coastguard Worker return -1;
560*288bf522SAndroid Build Coastguard Worker }
561*288bf522SAndroid Build Coastguard Worker
562*288bf522SAndroid Build Coastguard Worker off64_t ret;
563*288bf522SAndroid Build Coastguard Worker ret = lseek64(d->outfd, pos * F2FS_BLKSIZE, SEEK_SET);
564*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
565*288bf522SAndroid Build Coastguard Worker SLOGE("failed to seek\n");
566*288bf522SAndroid Build Coastguard Worker return ret;
567*288bf522SAndroid Build Coastguard Worker }
568*288bf522SAndroid Build Coastguard Worker
569*288bf522SAndroid Build Coastguard Worker ret = write(d->outfd, d->buf, F2FS_BLKSIZE);
570*288bf522SAndroid Build Coastguard Worker if (ret < 0) {
571*288bf522SAndroid Build Coastguard Worker SLOGE("failed to write\n");
572*288bf522SAndroid Build Coastguard Worker return ret;
573*288bf522SAndroid Build Coastguard Worker }
574*288bf522SAndroid Build Coastguard Worker if (ret != F2FS_BLKSIZE) {
575*288bf522SAndroid Build Coastguard Worker SLOGE("failed to read all\n");
576*288bf522SAndroid Build Coastguard Worker return -1;
577*288bf522SAndroid Build Coastguard Worker }
578*288bf522SAndroid Build Coastguard Worker return 0;
579*288bf522SAndroid Build Coastguard Worker }
580*288bf522SAndroid Build Coastguard Worker
main(int argc,char ** argv)581*288bf522SAndroid Build Coastguard Worker int main(int argc, char** argv) {
582*288bf522SAndroid Build Coastguard Worker if (argc != 3) printf("Usage: %s fs_file_in fs_file_out\n", argv[0]);
583*288bf522SAndroid Build Coastguard Worker char* in = argv[1];
584*288bf522SAndroid Build Coastguard Worker char* out = argv[2];
585*288bf522SAndroid Build Coastguard Worker int infd, outfd;
586*288bf522SAndroid Build Coastguard Worker
587*288bf522SAndroid Build Coastguard Worker if ((infd = open(in, O_RDONLY)) < 0) {
588*288bf522SAndroid Build Coastguard Worker SLOGE("Cannot open device");
589*288bf522SAndroid Build Coastguard Worker return 0;
590*288bf522SAndroid Build Coastguard Worker }
591*288bf522SAndroid Build Coastguard Worker if ((outfd = open(out, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
592*288bf522SAndroid Build Coastguard Worker SLOGE("Cannot open output");
593*288bf522SAndroid Build Coastguard Worker return 0;
594*288bf522SAndroid Build Coastguard Worker }
595*288bf522SAndroid Build Coastguard Worker
596*288bf522SAndroid Build Coastguard Worker struct privdata d;
597*288bf522SAndroid Build Coastguard Worker d.infd = infd;
598*288bf522SAndroid Build Coastguard Worker d.outfd = outfd;
599*288bf522SAndroid Build Coastguard Worker d.count = 0;
600*288bf522SAndroid Build Coastguard Worker struct f2fs_info* info = generate_f2fs_info(infd);
601*288bf522SAndroid Build Coastguard Worker if (!info) {
602*288bf522SAndroid Build Coastguard Worker printf("Failed to generate info!");
603*288bf522SAndroid Build Coastguard Worker return -1;
604*288bf522SAndroid Build Coastguard Worker }
605*288bf522SAndroid Build Coastguard Worker char* buf = malloc(F2FS_BLKSIZE);
606*288bf522SAndroid Build Coastguard Worker char* zbuf = calloc(1, F2FS_BLKSIZE);
607*288bf522SAndroid Build Coastguard Worker d.buf = buf;
608*288bf522SAndroid Build Coastguard Worker d.zbuf = zbuf;
609*288bf522SAndroid Build Coastguard Worker d.done = 0;
610*288bf522SAndroid Build Coastguard Worker d.info = info;
611*288bf522SAndroid Build Coastguard Worker int expected_count = get_num_blocks_used(info);
612*288bf522SAndroid Build Coastguard Worker run_on_used_blocks(0, info, ©_used, &d);
613*288bf522SAndroid Build Coastguard Worker printf("Copied %d blocks. Expected to copy %d\n", d.count, expected_count);
614*288bf522SAndroid Build Coastguard Worker ftruncate64(outfd, info->total_blocks * F2FS_BLKSIZE);
615*288bf522SAndroid Build Coastguard Worker free_f2fs_info(info);
616*288bf522SAndroid Build Coastguard Worker free(buf);
617*288bf522SAndroid Build Coastguard Worker free(zbuf);
618*288bf522SAndroid Build Coastguard Worker close(infd);
619*288bf522SAndroid Build Coastguard Worker close(outfd);
620*288bf522SAndroid Build Coastguard Worker return 0;
621*288bf522SAndroid Build Coastguard Worker }
622