12c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim/** 22c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * defrag.c 32c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * 42c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * Copyright (c) 2015 Jaegeuk Kim <jaegeuk@kernel.org> 52c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * 62c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * This program is free software; you can redistribute it and/or modify 72c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * it under the terms of the GNU General Public License version 2 as 82c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim * published by the Free Software Foundation. 92c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim */ 102c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim#include "fsck.h" 112c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 122c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kimstatic int migrate_block(struct f2fs_sb_info *sbi, u64 from, u64 to) 132c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim{ 142c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim void *raw = calloc(BLOCK_SZ, 1); 152c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim struct seg_entry *se; 162c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim struct f2fs_summary sum; 172c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim u64 offset; 182c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim int ret, type; 192c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 202c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ASSERT(raw != NULL); 212c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 222c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* read from */ 232c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ret = dev_read_block(raw, from); 242c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ASSERT(ret >= 0); 252c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 262c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* write to */ 272c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ret = dev_write_block(raw, to); 282c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ASSERT(ret >= 0); 292c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 302c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* update sit bitmap & valid_blocks && se->type */ 312c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se = get_seg_entry(sbi, GET_SEGNO(sbi, from)); 322c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim offset = OFFSET_IN_SEG(sbi, from); 332c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim type = se->type; 342c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se->valid_blocks--; 352c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim f2fs_clear_bit(offset, (char *)se->cur_valid_map); 362c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se->dirty = 1; 372c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 382c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se = get_seg_entry(sbi, GET_SEGNO(sbi, to)); 392c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim offset = OFFSET_IN_SEG(sbi, to); 402c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se->type = type; 412c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se->valid_blocks++; 422c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim f2fs_set_bit(offset, (char *)se->cur_valid_map); 432c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se->dirty = 1; 442c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 452c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* read/write SSA */ 462c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim get_sum_entry(sbi, from, &sum); 472c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim update_sum_entry(sbi, to, &sum); 482c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 492c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* if data block, read node and update node block */ 502c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim if (IS_DATASEG(type)) 512c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim update_data_blkaddr(sbi, le32_to_cpu(sum.nid), 522c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim le16_to_cpu(sum.ofs_in_node), to); 532c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim else 54603f8f9d3628e8b81fea301e5f543a9f0b0d902dJaegeuk Kim update_nat_blkaddr(sbi, 0, le32_to_cpu(sum.nid), to); 552c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 562c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim DBG(0, "Migrate %s block %"PRIx64" -> %"PRIx64"\n", 572c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim IS_DATASEG(type) ? "data" : "node", 582c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim from, to); 592c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim free(raw); 602c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim return 0; 612c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim} 622c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 632c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kimint f2fs_defragment(struct f2fs_sb_info *sbi, u64 from, u64 len, u64 to, int left) 642c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim{ 652c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim struct seg_entry *se; 662c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim u64 idx, offset; 672c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 682c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* flush NAT/SIT journal entries */ 692c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim flush_journal_entries(sbi); 702c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 712c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim for (idx = from; idx < from + len; idx++) { 722c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim u64 target = to; 732c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 742c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim se = get_seg_entry(sbi, GET_SEGNO(sbi, idx)); 752c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim offset = OFFSET_IN_SEG(sbi, idx); 762c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 772c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim if (!f2fs_test_bit(offset, (const char *)se->cur_valid_map)) 782c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim continue; 792c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 802c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim if (find_next_free_block(sbi, &target, left, se->type)) { 812f2ee92b3409440bf7cbd50159840efbbd873bb4Jaegeuk Kim MSG(0, "Not enough space to migrate blocks"); 822f2ee92b3409440bf7cbd50159840efbbd873bb4Jaegeuk Kim return -1; 832c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim } 842c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 852c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim if (migrate_block(sbi, idx, target)) { 862c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim ASSERT_MSG("Found inconsistency: please run FSCK"); 872c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim return -1; 882c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim } 892c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim } 902c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 912c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* update curseg info; can update sit->types */ 922c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim move_curseg_info(sbi, to); 9317acba6d3da4efd60142b513b2017bddf67d49bbJaegeuk Kim zero_journal_entries(sbi); 942c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim write_curseg_info(sbi); 952c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 962c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim /* flush dirty sit entries */ 972c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim flush_sit_entries(sbi); 982c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 992c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim write_checkpoint(sbi); 1002c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim 1012c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim return 0; 1022c1ebe237acb9b1e8093f9aecd0c92b53583877bJaegeuk Kim} 103