102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#define _LARGEFILE64_SOURCE
202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#define LOG_TAG "f2fs_sparseblock"
402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include <cutils/log.h>
7125e060bacf25da4043515a9da8ca6da581b759dElliott Hughes#include <errno.h>
802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include <fcntl.h>
902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include <f2fs_fs.h>
1002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include <linux/types.h>
118678c6fc0a7c2f29f1843cc3d0be23cc5908fa85Elliott Hughes#include <malloc.h>
128678c6fc0a7c2f29f1843cc3d0be23cc5908fa85Elliott Hughes#include <string.h>
1302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include <sys/stat.h>
1402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#include "f2fs_sparseblock.h"
1502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
1602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
1702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#define D_DISP_u32(ptr, member)           \
1802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg  do {                \
1902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("%-30s" "\t\t[0x%#08x : %u]\n",    \
2002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg      #member, le32_to_cpu((ptr)->member), le32_to_cpu((ptr)->member) );  \
2102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg  } while (0);
2202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
2302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg#define D_DISP_u64(ptr, member)           \
2402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg  do {                \
2502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("%-30s" "\t\t[0x%#016llx : %llu]\n",    \
2602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg      #member, le64_to_cpu((ptr)->member), le64_to_cpu((ptr)->member) );  \
2702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg  } while (0);
2802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
29b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg#define segno_in_journal(sum, i)    (sum->sit_j.entries[i].segno)
30b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg
31b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg#define sit_in_journal(sum, i)      (sum->sit_j.entries[i].se)
32b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg
3302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic void dbg_print_raw_sb_info(struct f2fs_super_block *sb)
3402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
3502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n");
3602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
3702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("| Super block                                            |\n");
3802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
3902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
4002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, magic);
4102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, major_ver);
4202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, minor_ver);
4302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, log_sectorsize);
4402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, log_sectors_per_block);
4502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
4602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, log_blocksize);
4702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, log_blocks_per_seg);
4802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segs_per_sec);
4902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, secs_per_zone);
5002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, checksum_offset);
5102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u64(sb, block_count);
5202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
5302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, section_count);
5402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count);
5502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count_ckpt);
5602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count_sit);
5702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count_nat);
5802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
5902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count_ssa);
6002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment_count_main);
6102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, segment0_blkaddr);
6202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
6302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, cp_blkaddr);
6402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, sit_blkaddr);
6502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, nat_blkaddr);
6602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, ssa_blkaddr);
6702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, main_blkaddr);
6802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
6902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, root_ino);
7002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, node_ino);
7102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, meta_ino);
7202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(sb, cp_payload);
7302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n");
7402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
7502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic void dbg_print_raw_ckpt_struct(struct f2fs_checkpoint *cp)
7602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
7702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n");
7802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
7902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("| Checkpoint                                             |\n");
8002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
8102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
8202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u64(cp, checkpoint_ver);
8302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u64(cp, user_block_count);
8402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u64(cp, valid_block_count);
8502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, rsvd_segment_count);
8602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, overprov_segment_count);
8702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, free_segment_count);
8802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
8902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_HOT_NODE]);
9002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_WARM_NODE]);
9102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_COLD_NODE]);
9202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_segno[0]);
9302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_segno[1]);
9402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_segno[2]);
9502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
9602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_blkoff[0]);
9702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_blkoff[1]);
9802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_node_blkoff[2]);
9902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
10002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
10102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_HOT_DATA]);
10202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_WARM_DATA]);
10302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, alloc_type[CURSEG_COLD_DATA]);
10402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_segno[0]);
10502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_segno[1]);
10602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_segno[2]);
10702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
10802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_blkoff[0]);
10902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_blkoff[1]);
11002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cur_data_blkoff[2]);
11102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
11202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, ckpt_flags);
11302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cp_pack_total_block_count);
11402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, cp_pack_start_sum);
11502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, valid_node_count);
11602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, valid_inode_count);
11702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, next_free_nid);
11802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, sit_ver_bitmap_bytesize);
11902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, nat_ver_bitmap_bytesize);
12002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, checksum_offset);
12102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u64(cp, elapsed_time);
12202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
12302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    D_DISP_u32(cp, sit_nat_version_bitmap[0]);
12402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n\n");
12502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
12602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
12702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic void dbg_print_info_struct(struct f2fs_info *info)
12802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
12902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n");
13002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
13102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("| F2FS_INFO                                              |\n");
13202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("+--------------------------------------------------------+\n");
13302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("blocks_per_segment: %"PRIu64, info->blocks_per_segment);
13402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("block_size: %d", info->block_size);
13502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("sit_bmp loc: %p", info->sit_bmp);
13602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("sit_bmp_size: %d", info->sit_bmp_size);
13702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("blocks_per_sit: %"PRIu64, info->blocks_per_sit);
13802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("sit_blocks loc: %p", info->sit_blocks);
13902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("sit_sums loc: %p", info->sit_sums);
140b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    SLOGD("sit_sums num: %d", le16_to_cpu(info->sit_sums->n_sits));
141b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    unsigned int i;
142b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    for(i = 0; i < (le16_to_cpu(info->sit_sums->n_sits)); i++) {
143b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg        SLOGD("entry %d in journal entries is for segment %d",i, le32_to_cpu(segno_in_journal(info->sit_sums, i)));
144b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    }
145b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg
14602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("cp_blkaddr: %"PRIu64, info->cp_blkaddr);
14702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("cp_valid_cp_blkaddr: %"PRIu64, info->cp_valid_cp_blkaddr);
14802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("sit_blkaddr: %"PRIu64, info->sit_blkaddr);
14902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("nat_blkaddr: %"PRIu64, info->nat_blkaddr);
15002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("ssa_blkaddr: %"PRIu64, info->ssa_blkaddr);
15102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("main_blkaddr: %"PRIu64, info->main_blkaddr);
15202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("total_user_used: %"PRIu64, info->total_user_used);
15302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("total_blocks: %"PRIu64, info->total_blocks);
15402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGD("\n\n");
15502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
15602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
15702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
15802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg/* read blocks */
15902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic int read_structure(int fd, unsigned long long start, void *buf, ssize_t len)
16002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
16102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    off64_t ret;
16202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
16302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    ret = lseek64(fd, start, SEEK_SET);
16402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret < 0) {
16502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to seek\n");
16602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return ret;
16702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
16802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
16902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    ret = read(fd, buf, len);
17002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret < 0) {
17102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to read\n");
17202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return ret;
17302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
17402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret != len) {
17502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to read all\n");
17602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
17702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
17802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
17902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
18002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
18102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic int read_structure_blk(int fd, unsigned long long start_blk, void *buf, size_t len)
18202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
18302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return read_structure(fd, F2FS_BLKSIZE*start_blk, buf, F2FS_BLKSIZE * len);
18402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
18502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
18602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic int read_f2fs_sb(int fd, struct f2fs_super_block *sb)
18702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
18802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int rc;
18902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    rc = read_structure(fd, F2FS_SUPER_OFFSET, sb, sizeof(*sb));
19002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (le32_to_cpu(sb->magic) != F2FS_SUPER_MAGIC) {
19102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Not a valid F2FS super block. Magic:%#08x != %#08x",
19202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                                  le32_to_cpu(sb->magic), F2FS_SUPER_MAGIC);
19302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
19402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
19502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
19602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
19702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
19802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergunsigned int get_f2fs_filesystem_size_sec(char *dev)
19902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
20002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int fd;
20102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if ((fd = open(dev, O_RDONLY)) < 0) {
20202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Cannot open device to get filesystem size ");
20302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return 0;
20402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
20502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_super_block sb;
20602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if(read_f2fs_sb(fd, &sb))
20702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return 0;
20802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return (unsigned int)(le64_to_cpu(sb.block_count)*F2FS_BLKSIZE/DEFAULT_SECTOR_SIZE);
20902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
21002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
21102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic struct f2fs_checkpoint *validate_checkpoint(block_t cp_addr,
21202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                                                   unsigned long long *version, int fd)
21302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
21402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    unsigned char *cp_block_1, *cp_block_2;
21502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_checkpoint *cp_block, *cp_ret;
21602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u64 cp1_version = 0, cp2_version = 0;
21702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
21802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp_block_1 = malloc(F2FS_BLKSIZE);
21902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!cp_block_1)
22002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return NULL;
22102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
22202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* Read the 1st cp block in this CP pack */
22302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (read_structure_blk(fd, cp_addr, cp_block_1, 1))
22402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto invalid_cp1;
22502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
22602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* get the version number */
22702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp_block = (struct f2fs_checkpoint *)cp_block_1;
22802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
22902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp1_version = le64_to_cpu(cp_block->checkpoint_ver);
23002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
23102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp_block_2 = malloc(F2FS_BLKSIZE);
23202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!cp_block_2) {
23302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto invalid_cp1;
23402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
23502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* Read the 2nd cp block in this CP pack */
23602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1;
23702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (read_structure_blk(fd, cp_addr, cp_block_2, 1)) {
23802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto invalid_cp2;
23902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
24002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
24102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp_block = (struct f2fs_checkpoint *)cp_block_2;
24202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
24302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp2_version = le64_to_cpu(cp_block->checkpoint_ver);
24402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
24502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (cp2_version == cp1_version) {
24602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        *version = cp2_version;
24702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(cp_block_2);
24802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return (struct f2fs_checkpoint *)cp_block_1;
24902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
25002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
25102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* There must be something wrong with this checkpoint */
25202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberginvalid_cp2:
25302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(cp_block_2);
25402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberginvalid_cp1:
25502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(cp_block_1);
25602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return NULL;
25702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
25802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
25902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergint get_valid_checkpoint_info(int fd, struct f2fs_super_block *sb, struct f2fs_checkpoint **cp,  struct f2fs_info *info)
26002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
26102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_checkpoint *cp_block;
26202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
26302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_checkpoint *cp1, *cp2, *cur_cp;
26402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int cur_cp_no;
2656e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    unsigned long blk_size;
26602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    unsigned long long cp1_version = 0, cp2_version = 0;
26702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    unsigned long long cp1_start_blk_no;
26802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    unsigned long long cp2_start_blk_no;
26902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u32 bmp_size;
27002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
2716e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    blk_size = 1U << le32_to_cpu(sb->log_blocksize);
27202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
27302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /*
27402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg     * Find valid cp by reading both packs and finding most recent one.
27502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg     */
27602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp1_start_blk_no = le32_to_cpu(sb->cp_blkaddr);
27702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp1 = validate_checkpoint(cp1_start_blk_no, &cp1_version, fd);
27802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
27902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* The second checkpoint pack should start at the next segment */
28002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp2_start_blk_no = cp1_start_blk_no + (1 << le32_to_cpu(sb->log_blocks_per_seg));
28102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    cp2 = validate_checkpoint(cp2_start_blk_no, &cp2_version, fd);
28202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
28302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (cp1 && cp2) {
28402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        if (ver_after(cp2_version, cp1_version)) {
28502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            cur_cp = cp2;
28602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            info->cp_valid_cp_blkaddr = cp2_start_blk_no;
28702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            free(cp1);
28802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        } else {
28902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            cur_cp = cp1;
29002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            info->cp_valid_cp_blkaddr = cp1_start_blk_no;
29102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            free(cp2);
29202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        }
29302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    } else if (cp1) {
29402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        cur_cp = cp1;
29502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        info->cp_valid_cp_blkaddr = cp1_start_blk_no;
29602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    } else if (cp2) {
29702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        cur_cp = cp2;
29802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        info->cp_valid_cp_blkaddr = cp2_start_blk_no;
29902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    } else {
30002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto fail_no_cp;
30102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
30202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
30302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    *cp = cur_cp;
30402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
30502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
30602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
30702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergfail_no_cp:
30802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    SLOGE("Valid Checkpoint not found!!");
30902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return -EINVAL;
31002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
31102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
31202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic int gather_sit_info(int fd, struct f2fs_info *info)
31302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
31402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u64 num_segments = (info->total_blocks - info->main_blkaddr
31502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            + info->blocks_per_segment - 1) / info->blocks_per_segment;
31602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u64 num_sit_blocks = (num_segments + SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK;
31702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u64 sit_block;
31802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
31902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->sit_blocks = malloc(num_sit_blocks * sizeof(struct f2fs_sit_block));
32002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!info->sit_blocks)
32102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
32202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
32302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    for(sit_block = 0; sit_block<num_sit_blocks; sit_block++) {
32402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        off64_t address = info->sit_blkaddr + sit_block;
32502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
32602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        if (f2fs_test_bit(sit_block, info->sit_bmp))
32702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            address += info->blocks_per_sit;
32802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
32902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGD("Reading cache block starting at block %"PRIu64, address);
33002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        if (read_structure(fd, address * F2FS_BLKSIZE, &info->sit_blocks[sit_block], sizeof(struct f2fs_sit_block))) {
33102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            SLOGE("Could not read sit block at block %"PRIu64, address);
33202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            free(info->sit_blocks);
33302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            return -1;
33402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        }
33502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
33602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
33702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
33802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
339aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenbergstatic inline int is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f)
340aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg{
341aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags);
342aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    return !!(ckpt_flags & f);
343aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg}
344aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
345aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenbergstatic inline u64 sum_blk_addr(struct f2fs_checkpoint *cp, struct f2fs_info *info, int base, int type)
346aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg{
347aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    return info->cp_valid_cp_blkaddr + le32_to_cpu(cp->cp_pack_total_block_count)
348aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg                - (base + 1) + type;
349aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg}
350aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
35102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstatic int get_sit_summary(int fd, struct f2fs_info *info, struct f2fs_checkpoint *cp)
35202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
353aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    char buffer[F2FS_BLKSIZE];
354aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
35502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->sit_sums = calloc(1, sizeof(struct f2fs_summary_block));
35602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!info->sit_sums)
35702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
358aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
359aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    /* CURSEG_COLD_DATA where the journaled SIT entries are. */
360aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    if (is_set_ckpt_flags(cp, CP_COMPACT_SUM_FLAG)) {
361aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        if (read_structure_blk(fd, info->cp_valid_cp_blkaddr + le32_to_cpu(cp->cp_pack_start_sum), buffer, 1))
362aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg            return -1;
363aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        memcpy(&info->sit_sums->n_sits, &buffer[SUM_JOURNAL_SIZE], SUM_JOURNAL_SIZE);
364aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    } else {
365aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        u64 blk_addr;
366aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG))
367aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg            blk_addr = sum_blk_addr(cp, info, NR_CURSEG_TYPE, CURSEG_COLD_DATA);
368aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        else
369aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg            blk_addr = sum_blk_addr(cp, info, NR_CURSEG_DATA_TYPE, CURSEG_COLD_DATA);
370aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
371aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg        if (read_structure_blk(fd, blk_addr, buffer, 1))
372aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg            return -1;
373aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg
374b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg        memcpy(info->sit_sums, buffer, sizeof(struct f2fs_summary_block));
375aff4a27b96454d6868a7a22974f560147a13188fDaniel Rosenberg    }
37602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
37702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
37802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
37902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstruct f2fs_info *generate_f2fs_info(int fd)
38002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
38102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_super_block *sb = NULL;
38202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_checkpoint *cp = NULL;
38302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_info *info;
38402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
38502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info = calloc(1, sizeof(*info));
38602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!info) {
38702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Out of memory!");
38802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return NULL;
38902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
39002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
39102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    sb = malloc(sizeof(*sb));
39202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if(!sb) {
39302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Out of memory!");
39402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(info);
39502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return NULL;
39602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
39702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (read_f2fs_sb(fd, sb)) {
39802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Failed to read superblock");
39902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(info);
40002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(sb);
40102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return NULL;
40202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
40302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    dbg_print_raw_sb_info(sb);
40402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
40502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->cp_blkaddr = le32_to_cpu(sb->cp_blkaddr);
40602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->sit_blkaddr = le32_to_cpu(sb->sit_blkaddr);
40702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->nat_blkaddr = le32_to_cpu(sb->nat_blkaddr);
40802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->ssa_blkaddr = le32_to_cpu(sb->ssa_blkaddr);
40902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->main_blkaddr = le32_to_cpu(sb->main_blkaddr);
41002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->block_size = F2FS_BLKSIZE;
41102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->total_blocks = sb->block_count;
41202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->blocks_per_sit = (le32_to_cpu(sb->segment_count_sit) >> 1) << le32_to_cpu(sb->log_blocks_per_seg);
41302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->blocks_per_segment = 1U << le32_to_cpu(sb->log_blocks_per_seg);
41402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
41502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (get_valid_checkpoint_info(fd, sb, &cp, info))
41602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto error;
41702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    dbg_print_raw_ckpt_struct(cp);
41802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
41902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->total_user_used = le32_to_cpu(cp->valid_block_count);
42002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
42102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u32 bmp_size = le32_to_cpu(cp->sit_ver_bitmap_bytesize);
42202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
42302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    /* get sit validity bitmap */
42402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->sit_bmp = malloc(bmp_size);
42502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if(!info->sit_bmp) {
42602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Out of memory!");
42702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto error;
42802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
42902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
43002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    info->sit_bmp_size = bmp_size;
43102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (read_structure(fd, info->cp_valid_cp_blkaddr * F2FS_BLKSIZE
43202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                   + offsetof(struct f2fs_checkpoint, sit_nat_version_bitmap),
43302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                   info->sit_bmp, bmp_size)) {
43402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Error getting SIT validity bitmap");
43502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto error;
43602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
43702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
43802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (gather_sit_info(fd , info)) {
43902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Error getting SIT information");
44002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto error;
44102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
44202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (get_sit_summary(fd, info, cp)) {
44302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Error getting SIT entries in summary area");
44402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        goto error;
44502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
44602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    dbg_print_info_struct(info);
44702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return info;
44802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergerror:
44902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(sb);
45002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(cp);
45102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free_f2fs_info(info);
45202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return NULL;
45302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
45402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
45502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergvoid free_f2fs_info(struct f2fs_info *info)
45602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
45702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (info) {
45802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(info->sit_blocks);
45902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        info->sit_blocks = NULL;
46002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
46102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(info->sit_bmp);
46202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        info->sit_bmp = NULL;
46302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
46402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        free(info->sit_sums);
46502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        info->sit_sums = NULL;
46602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
46702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(info);
46802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
46902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
47002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergu64 get_num_blocks_used(struct f2fs_info *info)
47102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
47202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return info->main_blkaddr + info->total_user_used;
47302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
47402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
47502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergint f2fs_test_bit(unsigned int nr, const char *p)
47602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
47702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int mask;
47802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *addr = (char *)p;
47902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
48002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    addr += (nr >> 3);
48102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    mask = 1 << (7 - (nr & 0x07));
48202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return (mask & *addr) != 0;
48302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
48402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
48502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergint run_on_used_blocks(u64 startblock, struct f2fs_info *info, int (*func)(u64 pos, void *data), void *data) {
48602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_sit_block sit_block_cache;
487b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    struct f2fs_sit_entry * sit_entry;
488b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg    u64 sit_block_num_cur = 0, segnum = 0, block_offset;
48902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    u64 block;
49002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    unsigned int used, found, started = 0, i;
49102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
4926e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    block = startblock;
4936e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    while (block < info->total_blocks) {
49402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        /* TODO: Save only relevant portions of metadata */
49502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        if (block < info->main_blkaddr) {
49602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            if (func(block, data)) {
49702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                SLOGI("func error");
49802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                return -1;
49902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            }
50002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        } else {
50102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            /* Main Section */
50202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            segnum = (block - info->main_blkaddr)/info->blocks_per_segment;
50302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
50402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            /* check the SIT entries in the journal */
505b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg            found = 0;
506b63632828014d3bdac0d689591532fe78bc81bc7Daniel Rosenberg            for(i = 0; i < le16_to_cpu(info->sit_sums->n_sits); i++) {
50702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                if (le32_to_cpu(segno_in_journal(info->sit_sums, i)) == segnum) {
50802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                    sit_entry = &sit_in_journal(info->sit_sums, i);
50902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                    found = 1;
51002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                    break;
51102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                }
51202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            }
51302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
51402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            /* get SIT entry from SIT section */
51502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            if (!found) {
5166e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg                sit_block_num_cur = segnum / SIT_ENTRY_PER_BLOCK;
51702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                sit_entry = &info->sit_blocks[sit_block_num_cur].entries[segnum % SIT_ENTRY_PER_BLOCK];
51802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            }
51902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
52002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            block_offset = (block - info->main_blkaddr) % info->blocks_per_segment;
52102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
5226e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg            if (block_offset == 0 && GET_SIT_VBLOCKS(sit_entry) == 0) {
5236e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg                block += info->blocks_per_segment;
5246e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg                continue;
5256e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg            }
5266e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg
52702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            used = f2fs_test_bit(block_offset, (char *)sit_entry->valid_map);
52802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg            if(used)
52902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                if (func(block, data))
53002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg                    return -1;
53102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        }
5326e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg
5336e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg        block++;
53402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
53502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
53602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
53702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
53802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergstruct privdata
53902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
54002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int count;
54102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int infd;
54202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int outfd;
54302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char* buf;
54402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *zbuf;
54502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int done;
54602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_info *info;
54702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg};
54802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
54902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
55002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg/*
55102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg * This is a simple test program. It performs a block to block copy of a
55202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg * filesystem, replacing blocks identified as unused with 0's.
55302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg */
55402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
55502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergint copy_used(u64 pos, void *data)
55602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
55702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct privdata *d = data;
55802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *buf;
5596e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    int pdone = (pos * 100) / d->info->total_blocks;
56002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (pdone > d->done) {
56102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        d->done = pdone;
56202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        printf("Done with %d percent\n", d->done);
56302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
56402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
56502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d->count++;
56602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    buf = d->buf;
56702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if(read_structure_blk(d->infd, (unsigned long long)pos, d->buf, 1)) {
56802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        printf("Error reading!!!\n");
56902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
57002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
57102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
57202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    off64_t ret;
5736e2db2265b1c9cdf8a342b6e95f1ef99d1c73456Daniel Rosenberg    ret = lseek64(d->outfd, pos * F2FS_BLKSIZE, SEEK_SET);
57402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret < 0) {
57502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to seek\n");
57602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return ret;
57702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
57802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
57902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    ret = write(d->outfd, d->buf, F2FS_BLKSIZE);
58002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret < 0) {
58102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to write\n");
58202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return ret;
58302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
58402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (ret != F2FS_BLKSIZE) {
58502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("failed to read all\n");
58602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
58702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
58802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
58902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
59002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
59102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenbergint main(int argc, char **argv)
59202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg{
59302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (argc != 3)
59402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        printf("Usage: %s fs_file_in fs_file_out\n", argv[0]);
59502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *in = argv[1];
59602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *out = argv[2];
59702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int infd, outfd;
59802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
59902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if ((infd = open(in, O_RDONLY)) < 0) {
60002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Cannot open device");
60102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return 0;
60202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
60302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if ((outfd = open(out, O_WRONLY|O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
60402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        SLOGE("Cannot open output");
60502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return 0;
60602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
60702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg
60802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct privdata d;
60902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.infd = infd;
61002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.outfd = outfd;
61102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.count = 0;
61202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    struct f2fs_info *info = generate_f2fs_info(infd);
61302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    if (!info) {
61402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        printf("Failed to generate info!");
61502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg        return -1;
61602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    }
61702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *buf = malloc(F2FS_BLKSIZE);
61802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    char *zbuf = calloc(1, F2FS_BLKSIZE);
61902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.buf = buf;
62002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.zbuf = zbuf;
62102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.done = 0;
62202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    d.info = info;
62302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    int expected_count = get_num_blocks_used(info);
62402e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    run_on_used_blocks(0, info, &copy_used, &d);
62502e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    printf("Copied %d blocks. Expected to copy %d\n", d.count, expected_count);
62602e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    ftruncate64(outfd, info->total_blocks * F2FS_BLKSIZE);
62702e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free_f2fs_info(info);
62802e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(buf);
62902e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    free(zbuf);
63002e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    close(infd);
63102e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    close(outfd);
63202e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg    return 0;
63302e662508d7c6b96df94154b2fdf9c8f2c348690Daniel Rosenberg}
634