15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * defrag.c 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org> 55e5c12b0Sopenharmony_ci * 65e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 75e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 85e5c12b0Sopenharmony_ci * published by the Free Software Foundation. 95e5c12b0Sopenharmony_ci */ 105e5c12b0Sopenharmony_ci#include "fsck.h" 115e5c12b0Sopenharmony_ci 125e5c12b0Sopenharmony_cistatic int migrate_block(struct f2fs_sb_info *sbi, u64 from, u64 to) 135e5c12b0Sopenharmony_ci{ 145e5c12b0Sopenharmony_ci void *raw = calloc(BLOCK_SZ, 1); 155e5c12b0Sopenharmony_ci struct seg_entry *se; 165e5c12b0Sopenharmony_ci struct f2fs_summary sum; 175e5c12b0Sopenharmony_ci u64 offset; 185e5c12b0Sopenharmony_ci int ret, type; 195e5c12b0Sopenharmony_ci 205e5c12b0Sopenharmony_ci ASSERT(raw != NULL); 215e5c12b0Sopenharmony_ci 225e5c12b0Sopenharmony_ci /* read from */ 235e5c12b0Sopenharmony_ci ret = dev_read_block(raw, from); 245e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 255e5c12b0Sopenharmony_ci 265e5c12b0Sopenharmony_ci /* write to */ 275e5c12b0Sopenharmony_ci ret = dev_write_block(raw, to); 285e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 295e5c12b0Sopenharmony_ci 305e5c12b0Sopenharmony_ci /* update sit bitmap & valid_blocks && se->type */ 315e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, GET_SEGNO(sbi, from)); 325e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, from); 335e5c12b0Sopenharmony_ci type = se->type; 345e5c12b0Sopenharmony_ci se->valid_blocks--; 355e5c12b0Sopenharmony_ci f2fs_clear_bit(offset, (char *)se->cur_valid_map); 365e5c12b0Sopenharmony_ci se->dirty = 1; 375e5c12b0Sopenharmony_ci 385e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, GET_SEGNO(sbi, to)); 395e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, to); 405e5c12b0Sopenharmony_ci se->type = type; 415e5c12b0Sopenharmony_ci se->valid_blocks++; 425e5c12b0Sopenharmony_ci f2fs_set_bit(offset, (char *)se->cur_valid_map); 435e5c12b0Sopenharmony_ci se->dirty = 1; 445e5c12b0Sopenharmony_ci 455e5c12b0Sopenharmony_ci /* read/write SSA */ 465e5c12b0Sopenharmony_ci get_sum_entry(sbi, from, &sum); 475e5c12b0Sopenharmony_ci update_sum_entry(sbi, to, &sum); 485e5c12b0Sopenharmony_ci 495e5c12b0Sopenharmony_ci /* if data block, read node and update node block */ 505e5c12b0Sopenharmony_ci if (IS_DATASEG(type)) 515e5c12b0Sopenharmony_ci update_data_blkaddr(sbi, le32_to_cpu(sum.nid), 525e5c12b0Sopenharmony_ci le16_to_cpu(sum.ofs_in_node), to); 535e5c12b0Sopenharmony_ci else 545e5c12b0Sopenharmony_ci update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to); 555e5c12b0Sopenharmony_ci 565e5c12b0Sopenharmony_ci DBG(1, "Migrate %s block %"PRIx64" -> %"PRIx64"\n", 575e5c12b0Sopenharmony_ci IS_DATASEG(type) ? "data" : "node", 585e5c12b0Sopenharmony_ci from, to); 595e5c12b0Sopenharmony_ci free(raw); 605e5c12b0Sopenharmony_ci return 0; 615e5c12b0Sopenharmony_ci} 625e5c12b0Sopenharmony_ci 635e5c12b0Sopenharmony_ciint f2fs_defragment(struct f2fs_sb_info *sbi, u64 from, u64 len, u64 to, int left) 645e5c12b0Sopenharmony_ci{ 655e5c12b0Sopenharmony_ci struct seg_entry *se; 665e5c12b0Sopenharmony_ci u64 idx, offset; 675e5c12b0Sopenharmony_ci 685e5c12b0Sopenharmony_ci /* flush NAT/SIT journal entries */ 695e5c12b0Sopenharmony_ci flush_journal_entries(sbi); 705e5c12b0Sopenharmony_ci 715e5c12b0Sopenharmony_ci for (idx = from; idx < from + len; idx++) { 725e5c12b0Sopenharmony_ci u64 target = to; 735e5c12b0Sopenharmony_ci 745e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, GET_SEGNO(sbi, idx)); 755e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, idx); 765e5c12b0Sopenharmony_ci 775e5c12b0Sopenharmony_ci if (!f2fs_test_bit(offset, (const char *)se->cur_valid_map)) 785e5c12b0Sopenharmony_ci continue; 795e5c12b0Sopenharmony_ci 805e5c12b0Sopenharmony_ci if (find_next_free_block(sbi, &target, left, se->type, false)) { 815e5c12b0Sopenharmony_ci MSG(0, "Not enough space to migrate blocks"); 825e5c12b0Sopenharmony_ci return -1; 835e5c12b0Sopenharmony_ci } 845e5c12b0Sopenharmony_ci 855e5c12b0Sopenharmony_ci if (migrate_block(sbi, idx, target)) { 865e5c12b0Sopenharmony_ci ASSERT_MSG("Found inconsistency: please run FSCK"); 875e5c12b0Sopenharmony_ci return -1; 885e5c12b0Sopenharmony_ci } 895e5c12b0Sopenharmony_ci } 905e5c12b0Sopenharmony_ci 915e5c12b0Sopenharmony_ci /* update curseg info; can update sit->types */ 925e5c12b0Sopenharmony_ci move_curseg_info(sbi, to, left); 935e5c12b0Sopenharmony_ci zero_journal_entries(sbi); 945e5c12b0Sopenharmony_ci write_curseg_info(sbi); 955e5c12b0Sopenharmony_ci 965e5c12b0Sopenharmony_ci /* flush dirty sit entries */ 975e5c12b0Sopenharmony_ci flush_sit_entries(sbi); 985e5c12b0Sopenharmony_ci 995e5c12b0Sopenharmony_ci write_checkpoint(sbi); 1005e5c12b0Sopenharmony_ci 1015e5c12b0Sopenharmony_ci return 0; 1025e5c12b0Sopenharmony_ci} 103