15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * mount.c 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Copyright (c) 2013 Samsung Electronics Co., Ltd. 55e5c12b0Sopenharmony_ci * http://www.samsung.com/ 65e5c12b0Sopenharmony_ci * 75e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 85e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 95e5c12b0Sopenharmony_ci * published by the Free Software Foundation. 105e5c12b0Sopenharmony_ci */ 115e5c12b0Sopenharmony_ci#include "fsck.h" 125e5c12b0Sopenharmony_ci#include "fsck_debug.h" 135e5c12b0Sopenharmony_ci#include "node.h" 145e5c12b0Sopenharmony_ci#include "xattr.h" 155e5c12b0Sopenharmony_ci#include <locale.h> 165e5c12b0Sopenharmony_ci#include <stdbool.h> 175e5c12b0Sopenharmony_ci#include <time.h> 185e5c12b0Sopenharmony_ci#ifdef HAVE_LINUX_POSIX_ACL_H 195e5c12b0Sopenharmony_ci#include <linux/posix_acl.h> 205e5c12b0Sopenharmony_ci#endif 215e5c12b0Sopenharmony_ci#ifdef HAVE_SYS_ACL_H 225e5c12b0Sopenharmony_ci#include <sys/acl.h> 235e5c12b0Sopenharmony_ci#endif 245e5c12b0Sopenharmony_ci 255e5c12b0Sopenharmony_ci#ifndef ACL_UNDEFINED_TAG 265e5c12b0Sopenharmony_ci#define ACL_UNDEFINED_TAG (0x00) 275e5c12b0Sopenharmony_ci#define ACL_USER_OBJ (0x01) 285e5c12b0Sopenharmony_ci#define ACL_USER (0x02) 295e5c12b0Sopenharmony_ci#define ACL_GROUP_OBJ (0x04) 305e5c12b0Sopenharmony_ci#define ACL_GROUP (0x08) 315e5c12b0Sopenharmony_ci#define ACL_MASK (0x10) 325e5c12b0Sopenharmony_ci#define ACL_OTHER (0x20) 335e5c12b0Sopenharmony_ci#endif 345e5c12b0Sopenharmony_ci 355e5c12b0Sopenharmony_ci#ifdef HAVE_LINUX_BLKZONED_H 365e5c12b0Sopenharmony_ci 375e5c12b0Sopenharmony_cistatic int get_device_idx(struct f2fs_sb_info *sbi, uint32_t segno) 385e5c12b0Sopenharmony_ci{ 395e5c12b0Sopenharmony_ci block_t seg_start_blkaddr; 405e5c12b0Sopenharmony_ci int i; 415e5c12b0Sopenharmony_ci 425e5c12b0Sopenharmony_ci seg_start_blkaddr = SM_I(sbi)->main_blkaddr + 435e5c12b0Sopenharmony_ci segno * DEFAULT_BLOCKS_PER_SEGMENT; 445e5c12b0Sopenharmony_ci for (i = 0; i < c.ndevs; i++) 455e5c12b0Sopenharmony_ci if (c.devices[i].start_blkaddr <= seg_start_blkaddr && 465e5c12b0Sopenharmony_ci c.devices[i].end_blkaddr > seg_start_blkaddr) 475e5c12b0Sopenharmony_ci return i; 485e5c12b0Sopenharmony_ci return 0; 495e5c12b0Sopenharmony_ci} 505e5c12b0Sopenharmony_ci 515e5c12b0Sopenharmony_cistatic int get_zone_idx_from_dev(struct f2fs_sb_info *sbi, 525e5c12b0Sopenharmony_ci uint32_t segno, uint32_t dev_idx) 535e5c12b0Sopenharmony_ci{ 545e5c12b0Sopenharmony_ci block_t seg_start_blkaddr = START_BLOCK(sbi, segno); 555e5c12b0Sopenharmony_ci 565e5c12b0Sopenharmony_ci return (seg_start_blkaddr - c.devices[dev_idx].start_blkaddr) >> 575e5c12b0Sopenharmony_ci log_base_2(sbi->segs_per_sec * sbi->blocks_per_seg); 585e5c12b0Sopenharmony_ci} 595e5c12b0Sopenharmony_ci 605e5c12b0Sopenharmony_cibool is_usable_seg(struct f2fs_sb_info *sbi, unsigned int segno) 615e5c12b0Sopenharmony_ci{ 625e5c12b0Sopenharmony_ci unsigned int secno = segno / sbi->segs_per_sec; 635e5c12b0Sopenharmony_ci block_t seg_start = START_BLOCK(sbi, segno); 645e5c12b0Sopenharmony_ci block_t blocks_per_sec = sbi->blocks_per_seg * sbi->segs_per_sec; 655e5c12b0Sopenharmony_ci unsigned int dev_idx = get_device_idx(sbi, segno); 665e5c12b0Sopenharmony_ci unsigned int zone_idx = get_zone_idx_from_dev(sbi, segno, dev_idx); 675e5c12b0Sopenharmony_ci unsigned int sec_off = SM_I(sbi)->main_blkaddr >> 685e5c12b0Sopenharmony_ci log_base_2(blocks_per_sec); 695e5c12b0Sopenharmony_ci 705e5c12b0Sopenharmony_ci if (zone_idx < c.devices[dev_idx].nr_rnd_zones) 715e5c12b0Sopenharmony_ci return true; 725e5c12b0Sopenharmony_ci 735e5c12b0Sopenharmony_ci if (c.devices[dev_idx].zoned_model != F2FS_ZONED_HM) 745e5c12b0Sopenharmony_ci return true; 755e5c12b0Sopenharmony_ci 765e5c12b0Sopenharmony_ci return seg_start < ((sec_off + secno) * blocks_per_sec) + 775e5c12b0Sopenharmony_ci c.devices[dev_idx].zone_cap_blocks[zone_idx]; 785e5c12b0Sopenharmony_ci} 795e5c12b0Sopenharmony_ci 805e5c12b0Sopenharmony_ciunsigned int get_usable_seg_count(struct f2fs_sb_info *sbi) 815e5c12b0Sopenharmony_ci{ 825e5c12b0Sopenharmony_ci unsigned int i, usable_seg_count = 0; 835e5c12b0Sopenharmony_ci 845e5c12b0Sopenharmony_ci for (i = 0; i < MAIN_SEGS(sbi); i++) 855e5c12b0Sopenharmony_ci if (is_usable_seg(sbi, i)) 865e5c12b0Sopenharmony_ci usable_seg_count++; 875e5c12b0Sopenharmony_ci 885e5c12b0Sopenharmony_ci return usable_seg_count; 895e5c12b0Sopenharmony_ci} 905e5c12b0Sopenharmony_ci 915e5c12b0Sopenharmony_ci#else 925e5c12b0Sopenharmony_ci 935e5c12b0Sopenharmony_cibool is_usable_seg(struct f2fs_sb_info *UNUSED(sbi), unsigned int UNUSED(segno)) 945e5c12b0Sopenharmony_ci{ 955e5c12b0Sopenharmony_ci return true; 965e5c12b0Sopenharmony_ci} 975e5c12b0Sopenharmony_ci 985e5c12b0Sopenharmony_ciunsigned int get_usable_seg_count(struct f2fs_sb_info *sbi) 995e5c12b0Sopenharmony_ci{ 1005e5c12b0Sopenharmony_ci return MAIN_SEGS(sbi); 1015e5c12b0Sopenharmony_ci} 1025e5c12b0Sopenharmony_ci 1035e5c12b0Sopenharmony_ci#endif 1045e5c12b0Sopenharmony_ci 1055e5c12b0Sopenharmony_ciu32 get_free_segments(struct f2fs_sb_info *sbi) 1065e5c12b0Sopenharmony_ci{ 1075e5c12b0Sopenharmony_ci u32 i, free_segs = 0; 1085e5c12b0Sopenharmony_ci 1095e5c12b0Sopenharmony_ci for (i = 0; i < MAIN_SEGS(sbi); i++) { 1105e5c12b0Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, i); 1115e5c12b0Sopenharmony_ci 1125e5c12b0Sopenharmony_ci if (se->valid_blocks == 0x0 && !IS_CUR_SEGNO(sbi, i) && 1135e5c12b0Sopenharmony_ci is_usable_seg(sbi, i)) 1145e5c12b0Sopenharmony_ci free_segs++; 1155e5c12b0Sopenharmony_ci } 1165e5c12b0Sopenharmony_ci return free_segs; 1175e5c12b0Sopenharmony_ci} 1185e5c12b0Sopenharmony_ci 1195e5c12b0Sopenharmony_civoid update_free_segments(struct f2fs_sb_info *sbi) 1205e5c12b0Sopenharmony_ci{ 1215e5c12b0Sopenharmony_ci char *progress = "-*|*-"; 1225e5c12b0Sopenharmony_ci static int i = 0; 1235e5c12b0Sopenharmony_ci 1245e5c12b0Sopenharmony_ci if (c.dbg_lv) 1255e5c12b0Sopenharmony_ci return; 1265e5c12b0Sopenharmony_ci 1275e5c12b0Sopenharmony_ci MSG(0, "\r [ %c ] Free segments: 0x%x", progress[i % 5], get_free_segments(sbi)); 1285e5c12b0Sopenharmony_ci fflush(stdout); 1295e5c12b0Sopenharmony_ci i++; 1305e5c12b0Sopenharmony_ci} 1315e5c12b0Sopenharmony_ci 1325e5c12b0Sopenharmony_ci#if defined(HAVE_LINUX_POSIX_ACL_H) || defined(HAVE_SYS_ACL_H) 1335e5c12b0Sopenharmony_cistatic void print_acl(const u8 *value, int size) 1345e5c12b0Sopenharmony_ci{ 1355e5c12b0Sopenharmony_ci const struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value; 1365e5c12b0Sopenharmony_ci const struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); 1375e5c12b0Sopenharmony_ci const u8 *end = value + size; 1385e5c12b0Sopenharmony_ci int i, count; 1395e5c12b0Sopenharmony_ci 1405e5c12b0Sopenharmony_ci if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) { 1415e5c12b0Sopenharmony_ci MSG(0, "Invalid ACL version [0x%x : 0x%x]\n", 1425e5c12b0Sopenharmony_ci le32_to_cpu(hdr->a_version), F2FS_ACL_VERSION); 1435e5c12b0Sopenharmony_ci return; 1445e5c12b0Sopenharmony_ci } 1455e5c12b0Sopenharmony_ci 1465e5c12b0Sopenharmony_ci count = f2fs_acl_count(size); 1475e5c12b0Sopenharmony_ci if (count <= 0) { 1485e5c12b0Sopenharmony_ci MSG(0, "Invalid ACL value size %d\n", size); 1495e5c12b0Sopenharmony_ci return; 1505e5c12b0Sopenharmony_ci } 1515e5c12b0Sopenharmony_ci 1525e5c12b0Sopenharmony_ci for (i = 0; i < count; i++) { 1535e5c12b0Sopenharmony_ci if ((u8 *)entry > end) { 1545e5c12b0Sopenharmony_ci MSG(0, "Invalid ACL entries count %d\n", count); 1555e5c12b0Sopenharmony_ci return; 1565e5c12b0Sopenharmony_ci } 1575e5c12b0Sopenharmony_ci 1585e5c12b0Sopenharmony_ci switch (le16_to_cpu(entry->e_tag)) { 1595e5c12b0Sopenharmony_ci case ACL_USER_OBJ: 1605e5c12b0Sopenharmony_ci case ACL_GROUP_OBJ: 1615e5c12b0Sopenharmony_ci case ACL_MASK: 1625e5c12b0Sopenharmony_ci case ACL_OTHER: 1635e5c12b0Sopenharmony_ci MSG(0, "tag:0x%x perm:0x%x\n", 1645e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_tag), 1655e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_perm)); 1665e5c12b0Sopenharmony_ci entry = (struct f2fs_acl_entry *)((char *)entry + 1675e5c12b0Sopenharmony_ci sizeof(struct f2fs_acl_entry_short)); 1685e5c12b0Sopenharmony_ci break; 1695e5c12b0Sopenharmony_ci case ACL_USER: 1705e5c12b0Sopenharmony_ci MSG(0, "tag:0x%x perm:0x%x uid:%u\n", 1715e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_tag), 1725e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_perm), 1735e5c12b0Sopenharmony_ci le32_to_cpu(entry->e_id)); 1745e5c12b0Sopenharmony_ci entry = (struct f2fs_acl_entry *)((char *)entry + 1755e5c12b0Sopenharmony_ci sizeof(struct f2fs_acl_entry)); 1765e5c12b0Sopenharmony_ci break; 1775e5c12b0Sopenharmony_ci case ACL_GROUP: 1785e5c12b0Sopenharmony_ci MSG(0, "tag:0x%x perm:0x%x gid:%u\n", 1795e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_tag), 1805e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_perm), 1815e5c12b0Sopenharmony_ci le32_to_cpu(entry->e_id)); 1825e5c12b0Sopenharmony_ci entry = (struct f2fs_acl_entry *)((char *)entry + 1835e5c12b0Sopenharmony_ci sizeof(struct f2fs_acl_entry)); 1845e5c12b0Sopenharmony_ci break; 1855e5c12b0Sopenharmony_ci default: 1865e5c12b0Sopenharmony_ci MSG(0, "Unknown ACL tag 0x%x\n", 1875e5c12b0Sopenharmony_ci le16_to_cpu(entry->e_tag)); 1885e5c12b0Sopenharmony_ci return; 1895e5c12b0Sopenharmony_ci } 1905e5c12b0Sopenharmony_ci } 1915e5c12b0Sopenharmony_ci} 1925e5c12b0Sopenharmony_ci#endif /* HAVE_LINUX_POSIX_ACL_H || HAVE_SYS_ACL_H */ 1935e5c12b0Sopenharmony_ci 1945e5c12b0Sopenharmony_cistatic void print_xattr_entry(const struct f2fs_xattr_entry *ent) 1955e5c12b0Sopenharmony_ci{ 1965e5c12b0Sopenharmony_ci const u8 *value = (const u8 *)&ent->e_name[ent->e_name_len]; 1975e5c12b0Sopenharmony_ci const int size = le16_to_cpu(ent->e_value_size); 1985e5c12b0Sopenharmony_ci const struct fscrypt_context *ctx; 1995e5c12b0Sopenharmony_ci int i; 2005e5c12b0Sopenharmony_ci 2015e5c12b0Sopenharmony_ci MSG(0, "\nxattr: e_name_index:%d e_name:", ent->e_name_index); 2025e5c12b0Sopenharmony_ci for (i = 0; i < ent->e_name_len; i++) 2035e5c12b0Sopenharmony_ci MSG(0, "%c", ent->e_name[i]); 2045e5c12b0Sopenharmony_ci MSG(0, " e_name_len:%d e_value_size:%d e_value:\n", 2055e5c12b0Sopenharmony_ci ent->e_name_len, size); 2065e5c12b0Sopenharmony_ci 2075e5c12b0Sopenharmony_ci switch (ent->e_name_index) { 2085e5c12b0Sopenharmony_ci#if defined(HAVE_LINUX_POSIX_ACL_H) || defined(HAVE_SYS_ACL_H) 2095e5c12b0Sopenharmony_ci case F2FS_XATTR_INDEX_POSIX_ACL_ACCESS: 2105e5c12b0Sopenharmony_ci case F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT: 2115e5c12b0Sopenharmony_ci print_acl(value, size); 2125e5c12b0Sopenharmony_ci return; 2135e5c12b0Sopenharmony_ci#endif 2145e5c12b0Sopenharmony_ci case F2FS_XATTR_INDEX_ENCRYPTION: 2155e5c12b0Sopenharmony_ci ctx = (const struct fscrypt_context *)value; 2165e5c12b0Sopenharmony_ci if (size != sizeof(*ctx) || 2175e5c12b0Sopenharmony_ci ctx->format != FS_ENCRYPTION_CONTEXT_FORMAT_V1) 2185e5c12b0Sopenharmony_ci break; 2195e5c12b0Sopenharmony_ci MSG(0, "format: %d\n", ctx->format); 2205e5c12b0Sopenharmony_ci MSG(0, "contents_encryption_mode: 0x%x\n", ctx->contents_encryption_mode); 2215e5c12b0Sopenharmony_ci MSG(0, "filenames_encryption_mode: 0x%x\n", ctx->filenames_encryption_mode); 2225e5c12b0Sopenharmony_ci MSG(0, "flags: 0x%x\n", ctx->flags); 2235e5c12b0Sopenharmony_ci MSG(0, "master_key_descriptor: "); 2245e5c12b0Sopenharmony_ci for (i = 0; i < FS_KEY_DESCRIPTOR_SIZE; i++) 2255e5c12b0Sopenharmony_ci MSG(0, "%02X", ctx->master_key_descriptor[i]); 2265e5c12b0Sopenharmony_ci MSG(0, "\nnonce: "); 2275e5c12b0Sopenharmony_ci for (i = 0; i < FS_KEY_DERIVATION_NONCE_SIZE; i++) 2285e5c12b0Sopenharmony_ci MSG(0, "%02X", ctx->nonce[i]); 2295e5c12b0Sopenharmony_ci MSG(0, "\n"); 2305e5c12b0Sopenharmony_ci return; 2315e5c12b0Sopenharmony_ci } 2325e5c12b0Sopenharmony_ci for (i = 0; i < size; i++) 2335e5c12b0Sopenharmony_ci MSG(0, "%02X", value[i]); 2345e5c12b0Sopenharmony_ci MSG(0, "\n"); 2355e5c12b0Sopenharmony_ci} 2365e5c12b0Sopenharmony_ci 2375e5c12b0Sopenharmony_civoid print_inode_info(struct f2fs_sb_info *sbi, 2385e5c12b0Sopenharmony_ci struct f2fs_node *node, int name) 2395e5c12b0Sopenharmony_ci{ 2405e5c12b0Sopenharmony_ci struct f2fs_inode *inode = &node->i; 2415e5c12b0Sopenharmony_ci void *xattr_addr; 2425e5c12b0Sopenharmony_ci struct f2fs_xattr_entry *ent; 2435e5c12b0Sopenharmony_ci char en[F2FS_PRINT_NAMELEN]; 2445e5c12b0Sopenharmony_ci unsigned int i = 0; 2455e5c12b0Sopenharmony_ci u32 namelen = le32_to_cpu(inode->i_namelen); 2465e5c12b0Sopenharmony_ci int enc_name = file_enc_name(inode); 2475e5c12b0Sopenharmony_ci int ofs = get_extra_isize(node); 2485e5c12b0Sopenharmony_ci 2495e5c12b0Sopenharmony_ci pretty_print_filename(inode->i_name, namelen, en, enc_name); 2505e5c12b0Sopenharmony_ci if (name && en[0]) { 2515e5c12b0Sopenharmony_ci MSG(0, " - File name : %s%s\n", en, 2525e5c12b0Sopenharmony_ci enc_name ? " <encrypted>" : ""); 2535e5c12b0Sopenharmony_ci setlocale(LC_ALL, ""); 2545e5c12b0Sopenharmony_ci MSG(0, " - File size : %'" PRIu64 " (bytes)\n", 2555e5c12b0Sopenharmony_ci le64_to_cpu(inode->i_size)); 2565e5c12b0Sopenharmony_ci return; 2575e5c12b0Sopenharmony_ci } 2585e5c12b0Sopenharmony_ci 2595e5c12b0Sopenharmony_ci DISP_u32(inode, i_mode); 2605e5c12b0Sopenharmony_ci DISP_u32(inode, i_advise); 2615e5c12b0Sopenharmony_ci DISP_u32(inode, i_uid); 2625e5c12b0Sopenharmony_ci DISP_u32(inode, i_gid); 2635e5c12b0Sopenharmony_ci DISP_u32(inode, i_links); 2645e5c12b0Sopenharmony_ci DISP_u64(inode, i_size); 2655e5c12b0Sopenharmony_ci DISP_u64(inode, i_blocks); 2665e5c12b0Sopenharmony_ci 2675e5c12b0Sopenharmony_ci DISP_u64(inode, i_atime); 2685e5c12b0Sopenharmony_ci DISP_u32(inode, i_atime_nsec); 2695e5c12b0Sopenharmony_ci DISP_u64(inode, i_ctime); 2705e5c12b0Sopenharmony_ci DISP_u32(inode, i_ctime_nsec); 2715e5c12b0Sopenharmony_ci DISP_u64(inode, i_mtime); 2725e5c12b0Sopenharmony_ci DISP_u32(inode, i_mtime_nsec); 2735e5c12b0Sopenharmony_ci 2745e5c12b0Sopenharmony_ci DISP_u32(inode, i_generation); 2755e5c12b0Sopenharmony_ci DISP_u32(inode, i_current_depth); 2765e5c12b0Sopenharmony_ci DISP_u32(inode, i_xattr_nid); 2775e5c12b0Sopenharmony_ci DISP_u32(inode, i_flags); 2785e5c12b0Sopenharmony_ci DISP_u32(inode, i_inline); 2795e5c12b0Sopenharmony_ci DISP_u32(inode, i_pino); 2805e5c12b0Sopenharmony_ci DISP_u32(inode, i_dir_level); 2815e5c12b0Sopenharmony_ci 2825e5c12b0Sopenharmony_ci if (en[0]) { 2835e5c12b0Sopenharmony_ci DISP_u32(inode, i_namelen); 2845e5c12b0Sopenharmony_ci printf("%-30s\t\t[%s]\n", "i_name", en); 2855e5c12b0Sopenharmony_ci } 2865e5c12b0Sopenharmony_ci 2875e5c12b0Sopenharmony_ci printf("i_ext: fofs:%x blkaddr:%x len:%x\n", 2885e5c12b0Sopenharmony_ci le32_to_cpu(inode->i_ext.fofs), 2895e5c12b0Sopenharmony_ci le32_to_cpu(inode->i_ext.blk_addr), 2905e5c12b0Sopenharmony_ci le32_to_cpu(inode->i_ext.len)); 2915e5c12b0Sopenharmony_ci 2925e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) { 2935e5c12b0Sopenharmony_ci DISP_u16(inode, i_extra_isize); 2945e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)) 2955e5c12b0Sopenharmony_ci DISP_u16(inode, i_inline_xattr_size); 2965e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) 2975e5c12b0Sopenharmony_ci DISP_u32(inode, i_projid); 2985e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) 2995e5c12b0Sopenharmony_ci DISP_u32(inode, i_inode_checksum); 3005e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) { 3015e5c12b0Sopenharmony_ci DISP_u64(inode, i_crtime); 3025e5c12b0Sopenharmony_ci DISP_u32(inode, i_crtime_nsec); 3035e5c12b0Sopenharmony_ci } 3045e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION)) { 3055e5c12b0Sopenharmony_ci DISP_u64(inode, i_compr_blocks); 3065e5c12b0Sopenharmony_ci DISP_u32(inode, i_compress_algrithm); 3075e5c12b0Sopenharmony_ci DISP_u32(inode, i_log_cluster_size); 3085e5c12b0Sopenharmony_ci DISP_u32(inode, i_padding); 3095e5c12b0Sopenharmony_ci } 3105e5c12b0Sopenharmony_ci } 3115e5c12b0Sopenharmony_ci 3125e5c12b0Sopenharmony_ci for (i = 0; i < ADDRS_PER_INODE(inode); i++) { 3135e5c12b0Sopenharmony_ci block_t blkaddr; 3145e5c12b0Sopenharmony_ci char *flag = ""; 3155e5c12b0Sopenharmony_ci 3165e5c12b0Sopenharmony_ci if (i + ofs >= DEF_ADDRS_PER_INODE) 3175e5c12b0Sopenharmony_ci break; 3185e5c12b0Sopenharmony_ci 3195e5c12b0Sopenharmony_ci blkaddr = le32_to_cpu(inode->i_addr[i + ofs]); 3205e5c12b0Sopenharmony_ci 3215e5c12b0Sopenharmony_ci if (blkaddr == 0x0) 3225e5c12b0Sopenharmony_ci continue; 3235e5c12b0Sopenharmony_ci if (blkaddr == COMPRESS_ADDR) 3245e5c12b0Sopenharmony_ci flag = "cluster flag"; 3255e5c12b0Sopenharmony_ci else if (blkaddr == NEW_ADDR) 3265e5c12b0Sopenharmony_ci flag = "reserved flag"; 3275e5c12b0Sopenharmony_ci printf("i_addr[0x%x] %-16s\t\t[0x%8x : %u]\n", i + ofs, flag, 3285e5c12b0Sopenharmony_ci blkaddr, blkaddr); 3295e5c12b0Sopenharmony_ci } 3305e5c12b0Sopenharmony_ci 3315e5c12b0Sopenharmony_ci DISP_u32(inode, i_nid[0]); /* direct */ 3325e5c12b0Sopenharmony_ci DISP_u32(inode, i_nid[1]); /* direct */ 3335e5c12b0Sopenharmony_ci DISP_u32(inode, i_nid[2]); /* indirect */ 3345e5c12b0Sopenharmony_ci DISP_u32(inode, i_nid[3]); /* indirect */ 3355e5c12b0Sopenharmony_ci DISP_u32(inode, i_nid[4]); /* double indirect */ 3365e5c12b0Sopenharmony_ci 3375e5c12b0Sopenharmony_ci xattr_addr = read_all_xattrs(sbi, node); 3385e5c12b0Sopenharmony_ci if (xattr_addr) { 3395e5c12b0Sopenharmony_ci list_for_each_xattr(ent, xattr_addr) { 3405e5c12b0Sopenharmony_ci print_xattr_entry(ent); 3415e5c12b0Sopenharmony_ci } 3425e5c12b0Sopenharmony_ci free(xattr_addr); 3435e5c12b0Sopenharmony_ci } 3445e5c12b0Sopenharmony_ci 3455e5c12b0Sopenharmony_ci printf("\n"); 3465e5c12b0Sopenharmony_ci} 3475e5c12b0Sopenharmony_ci 3485e5c12b0Sopenharmony_civoid print_node_info(struct f2fs_sb_info *sbi, 3495e5c12b0Sopenharmony_ci struct f2fs_node *node_block, int verbose) 3505e5c12b0Sopenharmony_ci{ 3515e5c12b0Sopenharmony_ci nid_t ino = le32_to_cpu(node_block->footer.ino); 3525e5c12b0Sopenharmony_ci nid_t nid = le32_to_cpu(node_block->footer.nid); 3535e5c12b0Sopenharmony_ci /* Is this inode? */ 3545e5c12b0Sopenharmony_ci if (ino == nid) { 3555e5c12b0Sopenharmony_ci DBG(verbose, "Node ID [0x%x:%u] is inode\n", nid, nid); 3565e5c12b0Sopenharmony_ci print_inode_info(sbi, node_block, verbose); 3575e5c12b0Sopenharmony_ci } else { 3585e5c12b0Sopenharmony_ci int i; 3595e5c12b0Sopenharmony_ci u32 *dump_blk = (u32 *)node_block; 3605e5c12b0Sopenharmony_ci DBG(verbose, 3615e5c12b0Sopenharmony_ci "Node ID [0x%x:%u] is direct node or indirect node.\n", 3625e5c12b0Sopenharmony_ci nid, nid); 3635e5c12b0Sopenharmony_ci for (i = 0; i < DEF_ADDRS_PER_BLOCK; i++) 3645e5c12b0Sopenharmony_ci MSG(verbose, "[%d]\t\t\t[0x%8x : %d]\n", 3655e5c12b0Sopenharmony_ci i, dump_blk[i], dump_blk[i]); 3665e5c12b0Sopenharmony_ci } 3675e5c12b0Sopenharmony_ci} 3685e5c12b0Sopenharmony_ci 3695e5c12b0Sopenharmony_cistatic void DISP_label(uint16_t *name) 3705e5c12b0Sopenharmony_ci{ 3715e5c12b0Sopenharmony_ci char buffer[MAX_VOLUME_NAME]; 3725e5c12b0Sopenharmony_ci 3735e5c12b0Sopenharmony_ci utf16_to_utf8(buffer, name, MAX_VOLUME_NAME, MAX_VOLUME_NAME); 3745e5c12b0Sopenharmony_ci if (c.layout) 3755e5c12b0Sopenharmony_ci printf("%-30s %s\n", "Filesystem volume name:", buffer); 3765e5c12b0Sopenharmony_ci else 3775e5c12b0Sopenharmony_ci printf("%-30s" "\t\t[%s]\n", "volum_name", buffer); 3785e5c12b0Sopenharmony_ci} 3795e5c12b0Sopenharmony_ci 3805e5c12b0Sopenharmony_civoid print_raw_sb_info(struct f2fs_super_block *sb) 3815e5c12b0Sopenharmony_ci{ 3825e5c12b0Sopenharmony_ci if (c.layout) 3835e5c12b0Sopenharmony_ci goto printout; 3845e5c12b0Sopenharmony_ci if (!c.dbg_lv) 3855e5c12b0Sopenharmony_ci return; 3865e5c12b0Sopenharmony_ci 3875e5c12b0Sopenharmony_ci printf("\n"); 3885e5c12b0Sopenharmony_ci printf("+--------------------------------------------------------+\n"); 3895e5c12b0Sopenharmony_ci printf("| Super block |\n"); 3905e5c12b0Sopenharmony_ci printf("+--------------------------------------------------------+\n"); 3915e5c12b0Sopenharmony_ciprintout: 3925e5c12b0Sopenharmony_ci DISP_u32(sb, magic); 3935e5c12b0Sopenharmony_ci DISP_u32(sb, major_ver); 3945e5c12b0Sopenharmony_ci 3955e5c12b0Sopenharmony_ci DISP_label(sb->volume_name); 3965e5c12b0Sopenharmony_ci 3975e5c12b0Sopenharmony_ci DISP_u32(sb, minor_ver); 3985e5c12b0Sopenharmony_ci DISP_u32(sb, log_sectorsize); 3995e5c12b0Sopenharmony_ci DISP_u32(sb, log_sectors_per_block); 4005e5c12b0Sopenharmony_ci 4015e5c12b0Sopenharmony_ci DISP_u32(sb, log_blocksize); 4025e5c12b0Sopenharmony_ci DISP_u32(sb, log_blocks_per_seg); 4035e5c12b0Sopenharmony_ci DISP_u32(sb, segs_per_sec); 4045e5c12b0Sopenharmony_ci DISP_u32(sb, secs_per_zone); 4055e5c12b0Sopenharmony_ci DISP_u32(sb, checksum_offset); 4065e5c12b0Sopenharmony_ci DISP_u64(sb, block_count); 4075e5c12b0Sopenharmony_ci 4085e5c12b0Sopenharmony_ci DISP_u32(sb, section_count); 4095e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count); 4105e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count_ckpt); 4115e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count_sit); 4125e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count_nat); 4135e5c12b0Sopenharmony_ci 4145e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count_ssa); 4155e5c12b0Sopenharmony_ci DISP_u32(sb, segment_count_main); 4165e5c12b0Sopenharmony_ci DISP_u32(sb, segment0_blkaddr); 4175e5c12b0Sopenharmony_ci 4185e5c12b0Sopenharmony_ci DISP_u32(sb, cp_blkaddr); 4195e5c12b0Sopenharmony_ci DISP_u32(sb, sit_blkaddr); 4205e5c12b0Sopenharmony_ci DISP_u32(sb, nat_blkaddr); 4215e5c12b0Sopenharmony_ci DISP_u32(sb, ssa_blkaddr); 4225e5c12b0Sopenharmony_ci DISP_u32(sb, main_blkaddr); 4235e5c12b0Sopenharmony_ci 4245e5c12b0Sopenharmony_ci DISP_u32(sb, root_ino); 4255e5c12b0Sopenharmony_ci DISP_u32(sb, node_ino); 4265e5c12b0Sopenharmony_ci DISP_u32(sb, meta_ino); 4275e5c12b0Sopenharmony_ci DISP_u32(sb, cp_payload); 4285e5c12b0Sopenharmony_ci DISP_u32(sb, crc); 4295e5c12b0Sopenharmony_ci DISP("%-.252s", sb, version); 4305e5c12b0Sopenharmony_ci printf("\n"); 4315e5c12b0Sopenharmony_ci} 4325e5c12b0Sopenharmony_ci 4335e5c12b0Sopenharmony_civoid print_ckpt_info(struct f2fs_sb_info *sbi) 4345e5c12b0Sopenharmony_ci{ 4355e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 4365e5c12b0Sopenharmony_ci 4375e5c12b0Sopenharmony_ci if (c.layout) 4385e5c12b0Sopenharmony_ci goto printout; 4395e5c12b0Sopenharmony_ci if (!c.dbg_lv) 4405e5c12b0Sopenharmony_ci return; 4415e5c12b0Sopenharmony_ci 4425e5c12b0Sopenharmony_ci printf("\n"); 4435e5c12b0Sopenharmony_ci printf("+--------------------------------------------------------+\n"); 4445e5c12b0Sopenharmony_ci printf("| Checkpoint |\n"); 4455e5c12b0Sopenharmony_ci printf("+--------------------------------------------------------+\n"); 4465e5c12b0Sopenharmony_ciprintout: 4475e5c12b0Sopenharmony_ci DISP_u64(cp, checkpoint_ver); 4485e5c12b0Sopenharmony_ci DISP_u64(cp, user_block_count); 4495e5c12b0Sopenharmony_ci DISP_u64(cp, valid_block_count); 4505e5c12b0Sopenharmony_ci DISP_u32(cp, rsvd_segment_count); 4515e5c12b0Sopenharmony_ci DISP_u32(cp, overprov_segment_count); 4525e5c12b0Sopenharmony_ci DISP_u32(cp, free_segment_count); 4535e5c12b0Sopenharmony_ci 4545e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_HOT_NODE]); 4555e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_WARM_NODE]); 4565e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_COLD_NODE]); 4575e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_segno[0]); 4585e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_segno[1]); 4595e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_segno[2]); 4605e5c12b0Sopenharmony_ci 4615e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_blkoff[0]); 4625e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_blkoff[1]); 4635e5c12b0Sopenharmony_ci DISP_u32(cp, cur_node_blkoff[2]); 4645e5c12b0Sopenharmony_ci 4655e5c12b0Sopenharmony_ci 4665e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_HOT_DATA]); 4675e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_WARM_DATA]); 4685e5c12b0Sopenharmony_ci DISP_u32(cp, alloc_type[CURSEG_COLD_DATA]); 4695e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_segno[0]); 4705e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_segno[1]); 4715e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_segno[2]); 4725e5c12b0Sopenharmony_ci 4735e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_blkoff[0]); 4745e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_blkoff[1]); 4755e5c12b0Sopenharmony_ci DISP_u32(cp, cur_data_blkoff[2]); 4765e5c12b0Sopenharmony_ci 4775e5c12b0Sopenharmony_ci DISP_u32(cp, ckpt_flags); 4785e5c12b0Sopenharmony_ci DISP_u32(cp, cp_pack_total_block_count); 4795e5c12b0Sopenharmony_ci DISP_u32(cp, cp_pack_start_sum); 4805e5c12b0Sopenharmony_ci DISP_u32(cp, valid_node_count); 4815e5c12b0Sopenharmony_ci DISP_u32(cp, valid_inode_count); 4825e5c12b0Sopenharmony_ci DISP_u32(cp, next_free_nid); 4835e5c12b0Sopenharmony_ci DISP_u32(cp, sit_ver_bitmap_bytesize); 4845e5c12b0Sopenharmony_ci DISP_u32(cp, nat_ver_bitmap_bytesize); 4855e5c12b0Sopenharmony_ci DISP_u32(cp, checksum_offset); 4865e5c12b0Sopenharmony_ci DISP_u64(cp, elapsed_time); 4875e5c12b0Sopenharmony_ci 4885e5c12b0Sopenharmony_ci DISP_u32(cp, sit_nat_version_bitmap[0]); 4895e5c12b0Sopenharmony_ci printf("\n\n"); 4905e5c12b0Sopenharmony_ci} 4915e5c12b0Sopenharmony_ci 4925e5c12b0Sopenharmony_civoid print_cp_state(u32 flag) 4935e5c12b0Sopenharmony_ci{ 4945e5c12b0Sopenharmony_ci if (c.show_file_map) 4955e5c12b0Sopenharmony_ci return; 4965e5c12b0Sopenharmony_ci 4975e5c12b0Sopenharmony_ci MSG(0, "Info: checkpoint state = %x : ", flag); 4985e5c12b0Sopenharmony_ci if (flag & CP_QUOTA_NEED_FSCK_FLAG) 4995e5c12b0Sopenharmony_ci MSG(0, "%s", " quota_need_fsck"); 5005e5c12b0Sopenharmony_ci if (flag & CP_LARGE_NAT_BITMAP_FLAG) 5015e5c12b0Sopenharmony_ci MSG(0, "%s", " large_nat_bitmap"); 5025e5c12b0Sopenharmony_ci if (flag & CP_NOCRC_RECOVERY_FLAG) 5035e5c12b0Sopenharmony_ci MSG(0, "%s", " allow_nocrc"); 5045e5c12b0Sopenharmony_ci if (flag & CP_TRIMMED_FLAG) 5055e5c12b0Sopenharmony_ci MSG(0, "%s", " trimmed"); 5065e5c12b0Sopenharmony_ci if (flag & CP_NAT_BITS_FLAG) 5075e5c12b0Sopenharmony_ci MSG(0, "%s", " nat_bits"); 5085e5c12b0Sopenharmony_ci if (flag & CP_CRC_RECOVERY_FLAG) 5095e5c12b0Sopenharmony_ci MSG(0, "%s", " crc"); 5105e5c12b0Sopenharmony_ci if (flag & CP_FASTBOOT_FLAG) 5115e5c12b0Sopenharmony_ci MSG(0, "%s", " fastboot"); 5125e5c12b0Sopenharmony_ci if (flag & CP_FSCK_FLAG) 5135e5c12b0Sopenharmony_ci MSG(0, "%s", " fsck"); 5145e5c12b0Sopenharmony_ci if (flag & CP_ERROR_FLAG) 5155e5c12b0Sopenharmony_ci MSG(0, "%s", " error"); 5165e5c12b0Sopenharmony_ci if (flag & CP_COMPACT_SUM_FLAG) 5175e5c12b0Sopenharmony_ci MSG(0, "%s", " compacted_summary"); 5185e5c12b0Sopenharmony_ci if (flag & CP_ORPHAN_PRESENT_FLAG) 5195e5c12b0Sopenharmony_ci MSG(0, "%s", " orphan_inodes"); 5205e5c12b0Sopenharmony_ci if (flag & CP_DISABLED_FLAG) 5215e5c12b0Sopenharmony_ci MSG(0, "%s", " disabled"); 5225e5c12b0Sopenharmony_ci if (flag & CP_RESIZEFS_FLAG) 5235e5c12b0Sopenharmony_ci MSG(0, "%s", " resizefs"); 5245e5c12b0Sopenharmony_ci if (flag & CP_UMOUNT_FLAG) 5255e5c12b0Sopenharmony_ci MSG(0, "%s", " unmount"); 5265e5c12b0Sopenharmony_ci else 5275e5c12b0Sopenharmony_ci MSG(0, "%s", " sudden-power-off"); 5285e5c12b0Sopenharmony_ci MSG(0, "\n"); 5295e5c12b0Sopenharmony_ci} 5305e5c12b0Sopenharmony_ci 5315e5c12b0Sopenharmony_civoid print_sb_state(struct f2fs_super_block *sb) 5325e5c12b0Sopenharmony_ci{ 5335e5c12b0Sopenharmony_ci __le32 f = sb->feature; 5345e5c12b0Sopenharmony_ci int i; 5355e5c12b0Sopenharmony_ci 5365e5c12b0Sopenharmony_ci MSG(0, "Info: superblock features = %x : ", f); 5375e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_ENCRYPT)) { 5385e5c12b0Sopenharmony_ci MSG(0, "%s", " encrypt"); 5395e5c12b0Sopenharmony_ci } 5405e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_VERITY)) { 5415e5c12b0Sopenharmony_ci MSG(0, "%s", " verity"); 5425e5c12b0Sopenharmony_ci } 5435e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_BLKZONED)) { 5445e5c12b0Sopenharmony_ci MSG(0, "%s", " blkzoned"); 5455e5c12b0Sopenharmony_ci } 5465e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) { 5475e5c12b0Sopenharmony_ci MSG(0, "%s", " extra_attr"); 5485e5c12b0Sopenharmony_ci } 5495e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) { 5505e5c12b0Sopenharmony_ci MSG(0, "%s", " project_quota"); 5515e5c12b0Sopenharmony_ci } 5525e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) { 5535e5c12b0Sopenharmony_ci MSG(0, "%s", " inode_checksum"); 5545e5c12b0Sopenharmony_ci } 5555e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)) { 5565e5c12b0Sopenharmony_ci MSG(0, "%s", " flexible_inline_xattr"); 5575e5c12b0Sopenharmony_ci } 5585e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_QUOTA_INO)) { 5595e5c12b0Sopenharmony_ci MSG(0, "%s", " quota_ino"); 5605e5c12b0Sopenharmony_ci } 5615e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) { 5625e5c12b0Sopenharmony_ci MSG(0, "%s", " inode_crtime"); 5635e5c12b0Sopenharmony_ci } 5645e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_LOST_FOUND)) { 5655e5c12b0Sopenharmony_ci MSG(0, "%s", " lost_found"); 5665e5c12b0Sopenharmony_ci } 5675e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_SB_CHKSUM)) { 5685e5c12b0Sopenharmony_ci MSG(0, "%s", " sb_checksum"); 5695e5c12b0Sopenharmony_ci } 5705e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_CASEFOLD)) { 5715e5c12b0Sopenharmony_ci MSG(0, "%s", " casefold"); 5725e5c12b0Sopenharmony_ci } 5735e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_COMPRESSION)) { 5745e5c12b0Sopenharmony_ci MSG(0, "%s", " compression"); 5755e5c12b0Sopenharmony_ci } 5765e5c12b0Sopenharmony_ci if (f & cpu_to_le32(F2FS_FEATURE_RO)) { 5775e5c12b0Sopenharmony_ci MSG(0, "%s", " ro"); 5785e5c12b0Sopenharmony_ci } 5795e5c12b0Sopenharmony_ci MSG(0, "\n"); 5805e5c12b0Sopenharmony_ci MSG(0, "Info: superblock encrypt level = %d, salt = ", 5815e5c12b0Sopenharmony_ci sb->encryption_level); 5825e5c12b0Sopenharmony_ci for (i = 0; i < 16; i++) 5835e5c12b0Sopenharmony_ci MSG(0, "%02x", sb->encrypt_pw_salt[i]); 5845e5c12b0Sopenharmony_ci MSG(0, "\n"); 5855e5c12b0Sopenharmony_ci} 5865e5c12b0Sopenharmony_ci 5875e5c12b0Sopenharmony_cistatic char *stop_reason_str[] = { 5885e5c12b0Sopenharmony_ci [STOP_CP_REASON_SHUTDOWN] = "shutdown", 5895e5c12b0Sopenharmony_ci [STOP_CP_REASON_FAULT_INJECT] = "fault_inject", 5905e5c12b0Sopenharmony_ci [STOP_CP_REASON_META_PAGE] = "meta_page", 5915e5c12b0Sopenharmony_ci [STOP_CP_REASON_WRITE_FAIL] = "write_fail", 5925e5c12b0Sopenharmony_ci [STOP_CP_REASON_CORRUPTED_SUMMARY] = "corrupted_summary", 5935e5c12b0Sopenharmony_ci [STOP_CP_REASON_UPDATE_INODE] = "update_inode", 5945e5c12b0Sopenharmony_ci [STOP_CP_REASON_FLUSH_FAIL] = "flush_fail", 5955e5c12b0Sopenharmony_ci}; 5965e5c12b0Sopenharmony_ci 5975e5c12b0Sopenharmony_civoid print_sb_stop_reason(struct f2fs_super_block *sb) 5985e5c12b0Sopenharmony_ci{ 5995e5c12b0Sopenharmony_ci u8 *reason = sb->s_stop_reason; 6005e5c12b0Sopenharmony_ci int i; 6015e5c12b0Sopenharmony_ci 6025e5c12b0Sopenharmony_ci if (!c.force_stop) 6035e5c12b0Sopenharmony_ci return; 6045e5c12b0Sopenharmony_ci 6055e5c12b0Sopenharmony_ci MSG(0, "Info: checkpoint stop reason: "); 6065e5c12b0Sopenharmony_ci 6075e5c12b0Sopenharmony_ci for (i = 0; i < STOP_CP_REASON_MAX; i++) { 6085e5c12b0Sopenharmony_ci if (reason[i]) 6095e5c12b0Sopenharmony_ci MSG(0, "%s(%d) ", stop_reason_str[i], reason[i]); 6105e5c12b0Sopenharmony_ci } 6115e5c12b0Sopenharmony_ci 6125e5c12b0Sopenharmony_ci MSG(0, "\n"); 6135e5c12b0Sopenharmony_ci} 6145e5c12b0Sopenharmony_ci 6155e5c12b0Sopenharmony_cistatic char *errors_str[] = { 6165e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_CLUSTER] = "corrupted_cluster", 6175e5c12b0Sopenharmony_ci [ERROR_FAIL_DECOMPRESSION] = "fail_decompression", 6185e5c12b0Sopenharmony_ci [ERROR_INVALID_BLKADDR] = "invalid_blkaddr", 6195e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_DIRENT] = "corrupted_dirent", 6205e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_INODE] = "corrupted_inode", 6215e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_SUMMARY] = "inconsistent_summary", 6225e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_FOOTER] = "inconsistent_footer", 6235e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_SUM_TYPE] = "inconsistent_sum_type", 6245e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_JOURNAL] = "corrupted_journal", 6255e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_NODE_COUNT] = "inconsistent_node_count", 6265e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_BLOCK_COUNT] = "inconsistent_block_count", 6275e5c12b0Sopenharmony_ci [ERROR_INVALID_CURSEG] = "invalid_curseg", 6285e5c12b0Sopenharmony_ci [ERROR_INCONSISTENT_SIT] = "inconsistent_sit", 6295e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_VERITY_XATTR] = "corrupted_verity_xattr", 6305e5c12b0Sopenharmony_ci [ERROR_CORRUPTED_XATTR] = "corrupted_xattr", 6315e5c12b0Sopenharmony_ci}; 6325e5c12b0Sopenharmony_ci 6335e5c12b0Sopenharmony_civoid print_sb_errors(struct f2fs_super_block *sb) 6345e5c12b0Sopenharmony_ci{ 6355e5c12b0Sopenharmony_ci u8 *errors = sb->s_errors; 6365e5c12b0Sopenharmony_ci int i; 6375e5c12b0Sopenharmony_ci 6385e5c12b0Sopenharmony_ci if (!c.fs_errors) 6395e5c12b0Sopenharmony_ci return; 6405e5c12b0Sopenharmony_ci 6415e5c12b0Sopenharmony_ci MSG(0, "Info: fs errors: "); 6425e5c12b0Sopenharmony_ci 6435e5c12b0Sopenharmony_ci for (i = 0; i < ERROR_MAX; i++) { 6445e5c12b0Sopenharmony_ci if (test_bit_le(i, errors)) 6455e5c12b0Sopenharmony_ci MSG(0, "%s ", errors_str[i]); 6465e5c12b0Sopenharmony_ci } 6475e5c12b0Sopenharmony_ci 6485e5c12b0Sopenharmony_ci MSG(0, "\n"); 6495e5c12b0Sopenharmony_ci} 6505e5c12b0Sopenharmony_ci 6515e5c12b0Sopenharmony_cibool f2fs_is_valid_blkaddr(struct f2fs_sb_info *sbi, 6525e5c12b0Sopenharmony_ci block_t blkaddr, int type) 6535e5c12b0Sopenharmony_ci{ 6545e5c12b0Sopenharmony_ci switch (type) { 6555e5c12b0Sopenharmony_ci case META_NAT: 6565e5c12b0Sopenharmony_ci break; 6575e5c12b0Sopenharmony_ci case META_SIT: 6585e5c12b0Sopenharmony_ci if (blkaddr >= SIT_BLK_CNT(sbi)) 6595e5c12b0Sopenharmony_ci return 0; 6605e5c12b0Sopenharmony_ci break; 6615e5c12b0Sopenharmony_ci case META_SSA: 6625e5c12b0Sopenharmony_ci if (blkaddr >= MAIN_BLKADDR(sbi) || 6635e5c12b0Sopenharmony_ci blkaddr < SM_I(sbi)->ssa_blkaddr) 6645e5c12b0Sopenharmony_ci return 0; 6655e5c12b0Sopenharmony_ci break; 6665e5c12b0Sopenharmony_ci case META_CP: 6675e5c12b0Sopenharmony_ci if (blkaddr >= SIT_I(sbi)->sit_base_addr || 6685e5c12b0Sopenharmony_ci blkaddr < __start_cp_addr(sbi)) 6695e5c12b0Sopenharmony_ci return 0; 6705e5c12b0Sopenharmony_ci break; 6715e5c12b0Sopenharmony_ci case META_POR: 6725e5c12b0Sopenharmony_ci if (blkaddr >= MAX_BLKADDR(sbi) || 6735e5c12b0Sopenharmony_ci blkaddr < MAIN_BLKADDR(sbi)) 6745e5c12b0Sopenharmony_ci return 0; 6755e5c12b0Sopenharmony_ci break; 6765e5c12b0Sopenharmony_ci default: 6775e5c12b0Sopenharmony_ci ASSERT(0); 6785e5c12b0Sopenharmony_ci } 6795e5c12b0Sopenharmony_ci 6805e5c12b0Sopenharmony_ci return 1; 6815e5c12b0Sopenharmony_ci} 6825e5c12b0Sopenharmony_ci 6835e5c12b0Sopenharmony_cistatic inline block_t current_sit_addr(struct f2fs_sb_info *sbi, 6845e5c12b0Sopenharmony_ci unsigned int start); 6855e5c12b0Sopenharmony_ci 6865e5c12b0Sopenharmony_ci/* 6875e5c12b0Sopenharmony_ci * Readahead CP/NAT/SIT/SSA pages 6885e5c12b0Sopenharmony_ci */ 6895e5c12b0Sopenharmony_ciint f2fs_ra_meta_pages(struct f2fs_sb_info *sbi, block_t start, int nrpages, 6905e5c12b0Sopenharmony_ci int type) 6915e5c12b0Sopenharmony_ci{ 6925e5c12b0Sopenharmony_ci block_t blkno = start; 6935e5c12b0Sopenharmony_ci block_t blkaddr, start_blk = 0, len = 0; 6945e5c12b0Sopenharmony_ci 6955e5c12b0Sopenharmony_ci for (; nrpages-- > 0; blkno++) { 6965e5c12b0Sopenharmony_ci 6975e5c12b0Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkno, type)) 6985e5c12b0Sopenharmony_ci goto out; 6995e5c12b0Sopenharmony_ci 7005e5c12b0Sopenharmony_ci switch (type) { 7015e5c12b0Sopenharmony_ci case META_NAT: 7025e5c12b0Sopenharmony_ci if (blkno >= NAT_BLOCK_OFFSET(NM_I(sbi)->max_nid)) 7035e5c12b0Sopenharmony_ci blkno = 0; 7045e5c12b0Sopenharmony_ci /* get nat block addr */ 7055e5c12b0Sopenharmony_ci blkaddr = current_nat_addr(sbi, 7065e5c12b0Sopenharmony_ci blkno * NAT_ENTRY_PER_BLOCK, NULL); 7075e5c12b0Sopenharmony_ci break; 7085e5c12b0Sopenharmony_ci case META_SIT: 7095e5c12b0Sopenharmony_ci /* get sit block addr */ 7105e5c12b0Sopenharmony_ci blkaddr = current_sit_addr(sbi, 7115e5c12b0Sopenharmony_ci blkno * SIT_ENTRY_PER_BLOCK); 7125e5c12b0Sopenharmony_ci break; 7135e5c12b0Sopenharmony_ci case META_SSA: 7145e5c12b0Sopenharmony_ci case META_CP: 7155e5c12b0Sopenharmony_ci case META_POR: 7165e5c12b0Sopenharmony_ci blkaddr = blkno; 7175e5c12b0Sopenharmony_ci break; 7185e5c12b0Sopenharmony_ci default: 7195e5c12b0Sopenharmony_ci ASSERT(0); 7205e5c12b0Sopenharmony_ci } 7215e5c12b0Sopenharmony_ci 7225e5c12b0Sopenharmony_ci if (!len) { 7235e5c12b0Sopenharmony_ci start_blk = blkaddr; 7245e5c12b0Sopenharmony_ci len = 1; 7255e5c12b0Sopenharmony_ci } else if (start_blk + len == blkaddr) { 7265e5c12b0Sopenharmony_ci len++; 7275e5c12b0Sopenharmony_ci } else { 7285e5c12b0Sopenharmony_ci dev_readahead(start_blk << F2FS_BLKSIZE_BITS, 7295e5c12b0Sopenharmony_ci len << F2FS_BLKSIZE_BITS); 7305e5c12b0Sopenharmony_ci } 7315e5c12b0Sopenharmony_ci } 7325e5c12b0Sopenharmony_ciout: 7335e5c12b0Sopenharmony_ci if (len) 7345e5c12b0Sopenharmony_ci dev_readahead(start_blk << F2FS_BLKSIZE_BITS, 7355e5c12b0Sopenharmony_ci len << F2FS_BLKSIZE_BITS); 7365e5c12b0Sopenharmony_ci return blkno - start; 7375e5c12b0Sopenharmony_ci} 7385e5c12b0Sopenharmony_ci 7395e5c12b0Sopenharmony_civoid update_superblock(struct f2fs_super_block *sb, int sb_mask) 7405e5c12b0Sopenharmony_ci{ 7415e5c12b0Sopenharmony_ci int addr, ret; 7425e5c12b0Sopenharmony_ci uint8_t *buf; 7435e5c12b0Sopenharmony_ci u32 old_crc, new_crc; 7445e5c12b0Sopenharmony_ci 7455e5c12b0Sopenharmony_ci buf = calloc(BLOCK_SZ, 1); 7465e5c12b0Sopenharmony_ci ASSERT(buf); 7475e5c12b0Sopenharmony_ci 7485e5c12b0Sopenharmony_ci if (get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) { 7495e5c12b0Sopenharmony_ci old_crc = get_sb(crc); 7505e5c12b0Sopenharmony_ci new_crc = f2fs_cal_crc32(F2FS_SUPER_MAGIC, sb, 7515e5c12b0Sopenharmony_ci SB_CHKSUM_OFFSET); 7525e5c12b0Sopenharmony_ci set_sb(crc, new_crc); 7535e5c12b0Sopenharmony_ci MSG(1, "Info: SB CRC is updated (0x%x -> 0x%x)\n", 7545e5c12b0Sopenharmony_ci old_crc, new_crc); 7555e5c12b0Sopenharmony_ci } 7565e5c12b0Sopenharmony_ci 7575e5c12b0Sopenharmony_ci memcpy(buf + F2FS_SUPER_OFFSET, sb, sizeof(*sb)); 7585e5c12b0Sopenharmony_ci for (addr = SB0_ADDR; addr < SB_MAX_ADDR; addr++) { 7595e5c12b0Sopenharmony_ci if (SB_MASK(addr) & sb_mask) { 7605e5c12b0Sopenharmony_ci ret = dev_write_block(buf, addr); 7615e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 7625e5c12b0Sopenharmony_ci } 7635e5c12b0Sopenharmony_ci } 7645e5c12b0Sopenharmony_ci 7655e5c12b0Sopenharmony_ci free(buf); 7665e5c12b0Sopenharmony_ci DBG(0, "Info: Done to update superblock\n"); 7675e5c12b0Sopenharmony_ci} 7685e5c12b0Sopenharmony_ci 7695e5c12b0Sopenharmony_cistatic inline int sanity_check_area_boundary(struct f2fs_super_block *sb, 7705e5c12b0Sopenharmony_ci enum SB_ADDR sb_addr) 7715e5c12b0Sopenharmony_ci{ 7725e5c12b0Sopenharmony_ci u32 segment0_blkaddr = get_sb(segment0_blkaddr); 7735e5c12b0Sopenharmony_ci u32 cp_blkaddr = get_sb(cp_blkaddr); 7745e5c12b0Sopenharmony_ci u32 sit_blkaddr = get_sb(sit_blkaddr); 7755e5c12b0Sopenharmony_ci u32 nat_blkaddr = get_sb(nat_blkaddr); 7765e5c12b0Sopenharmony_ci u32 ssa_blkaddr = get_sb(ssa_blkaddr); 7775e5c12b0Sopenharmony_ci u32 main_blkaddr = get_sb(main_blkaddr); 7785e5c12b0Sopenharmony_ci u32 segment_count_ckpt = get_sb(segment_count_ckpt); 7795e5c12b0Sopenharmony_ci u32 segment_count_sit = get_sb(segment_count_sit); 7805e5c12b0Sopenharmony_ci u32 segment_count_nat = get_sb(segment_count_nat); 7815e5c12b0Sopenharmony_ci u32 segment_count_ssa = get_sb(segment_count_ssa); 7825e5c12b0Sopenharmony_ci u32 segment_count_main = get_sb(segment_count_main); 7835e5c12b0Sopenharmony_ci u32 segment_count = get_sb(segment_count); 7845e5c12b0Sopenharmony_ci u32 log_blocks_per_seg = get_sb(log_blocks_per_seg); 7855e5c12b0Sopenharmony_ci u64 main_end_blkaddr = main_blkaddr + 7865e5c12b0Sopenharmony_ci (segment_count_main << log_blocks_per_seg); 7875e5c12b0Sopenharmony_ci u64 seg_end_blkaddr = segment0_blkaddr + 7885e5c12b0Sopenharmony_ci (segment_count << log_blocks_per_seg); 7895e5c12b0Sopenharmony_ci 7905e5c12b0Sopenharmony_ci if (segment0_blkaddr != cp_blkaddr) { 7915e5c12b0Sopenharmony_ci MSG(0, "\tMismatch segment0(%u) cp_blkaddr(%u)\n", 7925e5c12b0Sopenharmony_ci segment0_blkaddr, cp_blkaddr); 7935e5c12b0Sopenharmony_ci return -1; 7945e5c12b0Sopenharmony_ci } 7955e5c12b0Sopenharmony_ci 7965e5c12b0Sopenharmony_ci if (cp_blkaddr + (segment_count_ckpt << log_blocks_per_seg) != 7975e5c12b0Sopenharmony_ci sit_blkaddr) { 7985e5c12b0Sopenharmony_ci MSG(0, "\tWrong CP boundary, start(%u) end(%u) blocks(%u)\n", 7995e5c12b0Sopenharmony_ci cp_blkaddr, sit_blkaddr, 8005e5c12b0Sopenharmony_ci segment_count_ckpt << log_blocks_per_seg); 8015e5c12b0Sopenharmony_ci return -1; 8025e5c12b0Sopenharmony_ci } 8035e5c12b0Sopenharmony_ci 8045e5c12b0Sopenharmony_ci if (sit_blkaddr + (segment_count_sit << log_blocks_per_seg) != 8055e5c12b0Sopenharmony_ci nat_blkaddr) { 8065e5c12b0Sopenharmony_ci MSG(0, "\tWrong SIT boundary, start(%u) end(%u) blocks(%u)\n", 8075e5c12b0Sopenharmony_ci sit_blkaddr, nat_blkaddr, 8085e5c12b0Sopenharmony_ci segment_count_sit << log_blocks_per_seg); 8095e5c12b0Sopenharmony_ci return -1; 8105e5c12b0Sopenharmony_ci } 8115e5c12b0Sopenharmony_ci 8125e5c12b0Sopenharmony_ci if (nat_blkaddr + (segment_count_nat << log_blocks_per_seg) != 8135e5c12b0Sopenharmony_ci ssa_blkaddr) { 8145e5c12b0Sopenharmony_ci MSG(0, "\tWrong NAT boundary, start(%u) end(%u) blocks(%u)\n", 8155e5c12b0Sopenharmony_ci nat_blkaddr, ssa_blkaddr, 8165e5c12b0Sopenharmony_ci segment_count_nat << log_blocks_per_seg); 8175e5c12b0Sopenharmony_ci return -1; 8185e5c12b0Sopenharmony_ci } 8195e5c12b0Sopenharmony_ci 8205e5c12b0Sopenharmony_ci if (ssa_blkaddr + (segment_count_ssa << log_blocks_per_seg) != 8215e5c12b0Sopenharmony_ci main_blkaddr) { 8225e5c12b0Sopenharmony_ci MSG(0, "\tWrong SSA boundary, start(%u) end(%u) blocks(%u)\n", 8235e5c12b0Sopenharmony_ci ssa_blkaddr, main_blkaddr, 8245e5c12b0Sopenharmony_ci segment_count_ssa << log_blocks_per_seg); 8255e5c12b0Sopenharmony_ci return -1; 8265e5c12b0Sopenharmony_ci } 8275e5c12b0Sopenharmony_ci 8285e5c12b0Sopenharmony_ci if (main_end_blkaddr > seg_end_blkaddr) { 8295e5c12b0Sopenharmony_ci MSG(0, "\tWrong MAIN_AREA, start(%u) end(%u) block(%u)\n", 8305e5c12b0Sopenharmony_ci main_blkaddr, 8315e5c12b0Sopenharmony_ci segment0_blkaddr + 8325e5c12b0Sopenharmony_ci (segment_count << log_blocks_per_seg), 8335e5c12b0Sopenharmony_ci segment_count_main << log_blocks_per_seg); 8345e5c12b0Sopenharmony_ci return -1; 8355e5c12b0Sopenharmony_ci } else if (main_end_blkaddr < seg_end_blkaddr) { 8365e5c12b0Sopenharmony_ci set_sb(segment_count, (main_end_blkaddr - 8375e5c12b0Sopenharmony_ci segment0_blkaddr) >> log_blocks_per_seg); 8385e5c12b0Sopenharmony_ci 8395e5c12b0Sopenharmony_ci update_superblock(sb, SB_MASK(sb_addr)); 8405e5c12b0Sopenharmony_ci MSG(0, "Info: Fix alignment: start(%u) end(%u) block(%u)\n", 8415e5c12b0Sopenharmony_ci main_blkaddr, 8425e5c12b0Sopenharmony_ci segment0_blkaddr + 8435e5c12b0Sopenharmony_ci (segment_count << log_blocks_per_seg), 8445e5c12b0Sopenharmony_ci segment_count_main << log_blocks_per_seg); 8455e5c12b0Sopenharmony_ci } 8465e5c12b0Sopenharmony_ci return 0; 8475e5c12b0Sopenharmony_ci} 8485e5c12b0Sopenharmony_ci 8495e5c12b0Sopenharmony_cistatic int verify_sb_chksum(struct f2fs_super_block *sb) 8505e5c12b0Sopenharmony_ci{ 8515e5c12b0Sopenharmony_ci if (SB_CHKSUM_OFFSET != get_sb(checksum_offset)) { 8525e5c12b0Sopenharmony_ci MSG(0, "\tInvalid SB CRC offset: %u\n", 8535e5c12b0Sopenharmony_ci get_sb(checksum_offset)); 8545e5c12b0Sopenharmony_ci return -1; 8555e5c12b0Sopenharmony_ci } 8565e5c12b0Sopenharmony_ci if (f2fs_crc_valid(get_sb(crc), sb, 8575e5c12b0Sopenharmony_ci get_sb(checksum_offset))) { 8585e5c12b0Sopenharmony_ci MSG(0, "\tInvalid SB CRC: 0x%x\n", get_sb(crc)); 8595e5c12b0Sopenharmony_ci return -1; 8605e5c12b0Sopenharmony_ci } 8615e5c12b0Sopenharmony_ci return 0; 8625e5c12b0Sopenharmony_ci} 8635e5c12b0Sopenharmony_ci 8645e5c12b0Sopenharmony_ciint sanity_check_raw_super(struct f2fs_super_block *sb, enum SB_ADDR sb_addr) 8655e5c12b0Sopenharmony_ci{ 8665e5c12b0Sopenharmony_ci unsigned int blocksize; 8675e5c12b0Sopenharmony_ci unsigned int segment_count, segs_per_sec, secs_per_zone, segs_per_zone; 8685e5c12b0Sopenharmony_ci unsigned int total_sections, blocks_per_seg; 8695e5c12b0Sopenharmony_ci 8705e5c12b0Sopenharmony_ci if (F2FS_SUPER_MAGIC != get_sb(magic)) { 8715e5c12b0Sopenharmony_ci MSG(0, "Magic Mismatch, valid(0x%x) - read(0x%x)\n", 8725e5c12b0Sopenharmony_ci F2FS_SUPER_MAGIC, get_sb(magic)); 8735e5c12b0Sopenharmony_ci return -1; 8745e5c12b0Sopenharmony_ci } 8755e5c12b0Sopenharmony_ci 8765e5c12b0Sopenharmony_ci if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM) && 8775e5c12b0Sopenharmony_ci verify_sb_chksum(sb)) 8785e5c12b0Sopenharmony_ci return -1; 8795e5c12b0Sopenharmony_ci 8805e5c12b0Sopenharmony_ci blocksize = 1 << get_sb(log_blocksize); 8815e5c12b0Sopenharmony_ci if (F2FS_BLKSIZE != blocksize) { 8825e5c12b0Sopenharmony_ci MSG(0, "Invalid blocksize (%u), supports only 4KB\n", 8835e5c12b0Sopenharmony_ci blocksize); 8845e5c12b0Sopenharmony_ci return -1; 8855e5c12b0Sopenharmony_ci } 8865e5c12b0Sopenharmony_ci 8875e5c12b0Sopenharmony_ci /* check log blocks per segment */ 8885e5c12b0Sopenharmony_ci if (get_sb(log_blocks_per_seg) != 9) { 8895e5c12b0Sopenharmony_ci MSG(0, "Invalid log blocks per segment (%u)\n", 8905e5c12b0Sopenharmony_ci get_sb(log_blocks_per_seg)); 8915e5c12b0Sopenharmony_ci return -1; 8925e5c12b0Sopenharmony_ci } 8935e5c12b0Sopenharmony_ci 8945e5c12b0Sopenharmony_ci /* Currently, support 512/1024/2048/4096 bytes sector size */ 8955e5c12b0Sopenharmony_ci if (get_sb(log_sectorsize) > F2FS_MAX_LOG_SECTOR_SIZE || 8965e5c12b0Sopenharmony_ci get_sb(log_sectorsize) < F2FS_MIN_LOG_SECTOR_SIZE) { 8975e5c12b0Sopenharmony_ci MSG(0, "Invalid log sectorsize (%u)\n", get_sb(log_sectorsize)); 8985e5c12b0Sopenharmony_ci return -1; 8995e5c12b0Sopenharmony_ci } 9005e5c12b0Sopenharmony_ci 9015e5c12b0Sopenharmony_ci if (get_sb(log_sectors_per_block) + get_sb(log_sectorsize) != 9025e5c12b0Sopenharmony_ci F2FS_MAX_LOG_SECTOR_SIZE) { 9035e5c12b0Sopenharmony_ci MSG(0, "Invalid log sectors per block(%u) log sectorsize(%u)\n", 9045e5c12b0Sopenharmony_ci get_sb(log_sectors_per_block), 9055e5c12b0Sopenharmony_ci get_sb(log_sectorsize)); 9065e5c12b0Sopenharmony_ci return -1; 9075e5c12b0Sopenharmony_ci } 9085e5c12b0Sopenharmony_ci 9095e5c12b0Sopenharmony_ci segment_count = get_sb(segment_count); 9105e5c12b0Sopenharmony_ci segs_per_sec = get_sb(segs_per_sec); 9115e5c12b0Sopenharmony_ci secs_per_zone = get_sb(secs_per_zone); 9125e5c12b0Sopenharmony_ci total_sections = get_sb(section_count); 9135e5c12b0Sopenharmony_ci segs_per_zone = segs_per_sec * secs_per_zone; 9145e5c12b0Sopenharmony_ci 9155e5c12b0Sopenharmony_ci /* blocks_per_seg should be 512, given the above check */ 9165e5c12b0Sopenharmony_ci blocks_per_seg = 1 << get_sb(log_blocks_per_seg); 9175e5c12b0Sopenharmony_ci 9185e5c12b0Sopenharmony_ci if (segment_count > F2FS_MAX_SEGMENT || 9195e5c12b0Sopenharmony_ci segment_count < F2FS_MIN_SEGMENTS) { 9205e5c12b0Sopenharmony_ci MSG(0, "\tInvalid segment count (%u)\n", segment_count); 9215e5c12b0Sopenharmony_ci return -1; 9225e5c12b0Sopenharmony_ci } 9235e5c12b0Sopenharmony_ci 9245e5c12b0Sopenharmony_ci if (!(get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) && 9255e5c12b0Sopenharmony_ci (total_sections > segment_count || 9265e5c12b0Sopenharmony_ci total_sections < F2FS_MIN_SEGMENTS || 9275e5c12b0Sopenharmony_ci segs_per_sec > segment_count || !segs_per_sec)) { 9285e5c12b0Sopenharmony_ci MSG(0, "\tInvalid segment/section count (%u, %u x %u)\n", 9295e5c12b0Sopenharmony_ci segment_count, total_sections, segs_per_sec); 9305e5c12b0Sopenharmony_ci return 1; 9315e5c12b0Sopenharmony_ci } 9325e5c12b0Sopenharmony_ci 9335e5c12b0Sopenharmony_ci if ((segment_count / segs_per_sec) < total_sections) { 9345e5c12b0Sopenharmony_ci MSG(0, "Small segment_count (%u < %u * %u)\n", 9355e5c12b0Sopenharmony_ci segment_count, segs_per_sec, total_sections); 9365e5c12b0Sopenharmony_ci return 1; 9375e5c12b0Sopenharmony_ci } 9385e5c12b0Sopenharmony_ci 9395e5c12b0Sopenharmony_ci if (segment_count > (get_sb(block_count) >> 9)) { 9405e5c12b0Sopenharmony_ci MSG(0, "Wrong segment_count / block_count (%u > %llu)\n", 9415e5c12b0Sopenharmony_ci segment_count, get_sb(block_count)); 9425e5c12b0Sopenharmony_ci return 1; 9435e5c12b0Sopenharmony_ci } 9445e5c12b0Sopenharmony_ci 9455e5c12b0Sopenharmony_ci if (sb->devs[0].path[0]) { 9465e5c12b0Sopenharmony_ci unsigned int dev_segs = le32_to_cpu(sb->devs[0].total_segments); 9475e5c12b0Sopenharmony_ci int i = 1; 9485e5c12b0Sopenharmony_ci 9495e5c12b0Sopenharmony_ci while (i < MAX_DEVICES && sb->devs[i].path[0]) { 9505e5c12b0Sopenharmony_ci dev_segs += le32_to_cpu(sb->devs[i].total_segments); 9515e5c12b0Sopenharmony_ci i++; 9525e5c12b0Sopenharmony_ci } 9535e5c12b0Sopenharmony_ci if (segment_count != dev_segs / segs_per_zone * segs_per_zone) { 9545e5c12b0Sopenharmony_ci MSG(0, "Segment count (%u) mismatch with total segments from devices (%u)", 9555e5c12b0Sopenharmony_ci segment_count, dev_segs); 9565e5c12b0Sopenharmony_ci return 1; 9575e5c12b0Sopenharmony_ci } 9585e5c12b0Sopenharmony_ci } 9595e5c12b0Sopenharmony_ci 9605e5c12b0Sopenharmony_ci if (secs_per_zone > total_sections || !secs_per_zone) { 9615e5c12b0Sopenharmony_ci MSG(0, "Wrong secs_per_zone / total_sections (%u, %u)\n", 9625e5c12b0Sopenharmony_ci secs_per_zone, total_sections); 9635e5c12b0Sopenharmony_ci return 1; 9645e5c12b0Sopenharmony_ci } 9655e5c12b0Sopenharmony_ci if (get_sb(extension_count) > F2FS_MAX_EXTENSION || 9665e5c12b0Sopenharmony_ci sb->hot_ext_count > F2FS_MAX_EXTENSION || 9675e5c12b0Sopenharmony_ci get_sb(extension_count) + 9685e5c12b0Sopenharmony_ci sb->hot_ext_count > F2FS_MAX_EXTENSION) { 9695e5c12b0Sopenharmony_ci MSG(0, "Corrupted extension count (%u + %u > %u)\n", 9705e5c12b0Sopenharmony_ci get_sb(extension_count), 9715e5c12b0Sopenharmony_ci sb->hot_ext_count, 9725e5c12b0Sopenharmony_ci F2FS_MAX_EXTENSION); 9735e5c12b0Sopenharmony_ci return 1; 9745e5c12b0Sopenharmony_ci } 9755e5c12b0Sopenharmony_ci 9765e5c12b0Sopenharmony_ci if (get_sb(cp_payload) > (blocks_per_seg - F2FS_CP_PACKS)) { 9775e5c12b0Sopenharmony_ci MSG(0, "Insane cp_payload (%u > %u)\n", 9785e5c12b0Sopenharmony_ci get_sb(cp_payload), blocks_per_seg - F2FS_CP_PACKS); 9795e5c12b0Sopenharmony_ci return 1; 9805e5c12b0Sopenharmony_ci } 9815e5c12b0Sopenharmony_ci 9825e5c12b0Sopenharmony_ci /* check reserved ino info */ 9835e5c12b0Sopenharmony_ci if (get_sb(node_ino) != 1 || get_sb(meta_ino) != 2 || 9845e5c12b0Sopenharmony_ci get_sb(root_ino) != 3) { 9855e5c12b0Sopenharmony_ci MSG(0, "Invalid Fs Meta Ino: node(%u) meta(%u) root(%u)\n", 9865e5c12b0Sopenharmony_ci get_sb(node_ino), get_sb(meta_ino), get_sb(root_ino)); 9875e5c12b0Sopenharmony_ci return -1; 9885e5c12b0Sopenharmony_ci } 9895e5c12b0Sopenharmony_ci 9905e5c12b0Sopenharmony_ci /* Check zoned block device feature */ 9915e5c12b0Sopenharmony_ci if (c.devices[0].zoned_model != F2FS_ZONED_NONE && 9925e5c12b0Sopenharmony_ci !(sb->feature & cpu_to_le32(F2FS_FEATURE_BLKZONED))) { 9935e5c12b0Sopenharmony_ci MSG(0, "\tMissing zoned block device feature\n"); 9945e5c12b0Sopenharmony_ci return -1; 9955e5c12b0Sopenharmony_ci } 9965e5c12b0Sopenharmony_ci 9975e5c12b0Sopenharmony_ci if (sanity_check_area_boundary(sb, sb_addr)) 9985e5c12b0Sopenharmony_ci return -1; 9995e5c12b0Sopenharmony_ci return 0; 10005e5c12b0Sopenharmony_ci} 10015e5c12b0Sopenharmony_ci 10025e5c12b0Sopenharmony_cistatic int check_and_set_one_feature(struct f2fs_sb_info *sbi, int feature) 10035e5c12b0Sopenharmony_ci{ 10045e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(feature)) { 10055e5c12b0Sopenharmony_ci if (!(sbi->raw_super->feature & cpu_to_le32(feature))) { 10065e5c12b0Sopenharmony_ci sbi->raw_super->feature |= cpu_to_le32(feature); 10075e5c12b0Sopenharmony_ci return 1; 10085e5c12b0Sopenharmony_ci } 10095e5c12b0Sopenharmony_ci } 10105e5c12b0Sopenharmony_ci return 0; 10115e5c12b0Sopenharmony_ci} 10125e5c12b0Sopenharmony_ci 10135e5c12b0Sopenharmony_cistatic void check_and_set_features(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) 10145e5c12b0Sopenharmony_ci{ 10155e5c12b0Sopenharmony_ci bool need_fix = false; 10165e5c12b0Sopenharmony_ci if (check_and_set_one_feature(sbi, F2FS_FEATURE_EXTRA_ATTR)) { 10175e5c12b0Sopenharmony_ci MSG(0, "Fix set feature: extra_attr\n"); 10185e5c12b0Sopenharmony_ci need_fix = true; 10195e5c12b0Sopenharmony_ci } 10205e5c12b0Sopenharmony_ci 10215e5c12b0Sopenharmony_ci if (check_and_set_one_feature(sbi, F2FS_FEATURE_PRJQUOTA)) { 10225e5c12b0Sopenharmony_ci MSG(0, "Fix set feature: project_quota\n"); 10235e5c12b0Sopenharmony_ci need_fix = true; 10245e5c12b0Sopenharmony_ci } 10255e5c12b0Sopenharmony_ci 10265e5c12b0Sopenharmony_ci if (check_and_set_one_feature(sbi, F2FS_FEATURE_CASEFOLD)) { 10275e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = sbi->raw_super; 10285e5c12b0Sopenharmony_ci set_sb(s_encoding, c.s_encoding); 10295e5c12b0Sopenharmony_ci set_sb(s_encoding_flags, c.s_encoding_flags); 10305e5c12b0Sopenharmony_ci MSG(0, "Fix set feature: casefold, s_encoding: %d, s_encoding_flags: %d\n", 10315e5c12b0Sopenharmony_ci c.s_encoding, c.s_encoding_flags); 10325e5c12b0Sopenharmony_ci need_fix = true; 10335e5c12b0Sopenharmony_ci } 10345e5c12b0Sopenharmony_ci 10355e5c12b0Sopenharmony_ci if (need_fix) { 10365e5c12b0Sopenharmony_ci update_superblock(sbi->raw_super, SB_MASK(sb_addr)); 10375e5c12b0Sopenharmony_ci } 10385e5c12b0Sopenharmony_ci} 10395e5c12b0Sopenharmony_ci 10405e5c12b0Sopenharmony_ci#define CHECK_PERIOD (3600 * 24 * 30) // one month by default 10415e5c12b0Sopenharmony_ci 10425e5c12b0Sopenharmony_ciint validate_super_block(struct f2fs_sb_info *sbi, enum SB_ADDR sb_addr) 10435e5c12b0Sopenharmony_ci{ 10445e5c12b0Sopenharmony_ci char buf[F2FS_BLKSIZE]; 10455e5c12b0Sopenharmony_ci 10465e5c12b0Sopenharmony_ci sbi->raw_super = malloc(sizeof(struct f2fs_super_block)); 10475e5c12b0Sopenharmony_ci if (!sbi->raw_super) 10485e5c12b0Sopenharmony_ci return -ENOMEM; 10495e5c12b0Sopenharmony_ci 10505e5c12b0Sopenharmony_ci if (dev_read_block(buf, sb_addr)) 10515e5c12b0Sopenharmony_ci return -1; 10525e5c12b0Sopenharmony_ci 10535e5c12b0Sopenharmony_ci memcpy(sbi->raw_super, buf + F2FS_SUPER_OFFSET, 10545e5c12b0Sopenharmony_ci sizeof(struct f2fs_super_block)); 10555e5c12b0Sopenharmony_ci 10565e5c12b0Sopenharmony_ci if (!sanity_check_raw_super(sbi->raw_super, sb_addr)) { 10575e5c12b0Sopenharmony_ci check_and_set_features(sbi, sb_addr); 10585e5c12b0Sopenharmony_ci /* get kernel version */ 10595e5c12b0Sopenharmony_ci if (c.kd >= 0) { 10605e5c12b0Sopenharmony_ci dev_read_version(c.version, 0, VERSION_NAME_LEN); 10615e5c12b0Sopenharmony_ci get_kernel_version(c.version); 10625e5c12b0Sopenharmony_ci } else { 10635e5c12b0Sopenharmony_ci get_kernel_uname_version(c.version); 10645e5c12b0Sopenharmony_ci } 10655e5c12b0Sopenharmony_ci 10665e5c12b0Sopenharmony_ci /* build sb version */ 10675e5c12b0Sopenharmony_ci memcpy(c.sb_version, sbi->raw_super->version, VERSION_NAME_LEN); 10685e5c12b0Sopenharmony_ci get_kernel_version(c.sb_version); 10695e5c12b0Sopenharmony_ci memcpy(c.init_version, sbi->raw_super->init_version, 10705e5c12b0Sopenharmony_ci VERSION_NAME_LEN); 10715e5c12b0Sopenharmony_ci get_kernel_version(c.init_version); 10725e5c12b0Sopenharmony_ci 10735e5c12b0Sopenharmony_ci c.force_stop = is_checkpoint_stop(sbi->raw_super, false); 10745e5c12b0Sopenharmony_ci c.abnormal_stop = is_checkpoint_stop(sbi->raw_super, true); 10755e5c12b0Sopenharmony_ci c.fs_errors = is_inconsistent_error(sbi->raw_super); 10765e5c12b0Sopenharmony_ci 10775e5c12b0Sopenharmony_ci MSG(0, "Info: MKFS version\n \"%s\"\n", c.init_version); 10785e5c12b0Sopenharmony_ci MSG(0, "Info: FSCK version\n from \"%s\"\n to \"%s\"\n", 10795e5c12b0Sopenharmony_ci c.sb_version, c.version); 10805e5c12b0Sopenharmony_ci print_sb_state(sbi->raw_super); 10815e5c12b0Sopenharmony_ci print_sb_stop_reason(sbi->raw_super); 10825e5c12b0Sopenharmony_ci print_sb_errors(sbi->raw_super); 10835e5c12b0Sopenharmony_ci return 0; 10845e5c12b0Sopenharmony_ci } 10855e5c12b0Sopenharmony_ci 10865e5c12b0Sopenharmony_ci free(sbi->raw_super); 10875e5c12b0Sopenharmony_ci sbi->raw_super = NULL; 10885e5c12b0Sopenharmony_ci MSG(0, "\tCan't find a valid F2FS superblock at 0x%x\n", sb_addr); 10895e5c12b0Sopenharmony_ci 10905e5c12b0Sopenharmony_ci return -EINVAL; 10915e5c12b0Sopenharmony_ci} 10925e5c12b0Sopenharmony_ci 10935e5c12b0Sopenharmony_ciint init_sb_info(struct f2fs_sb_info *sbi) 10945e5c12b0Sopenharmony_ci{ 10955e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 10965e5c12b0Sopenharmony_ci u64 total_sectors; 10975e5c12b0Sopenharmony_ci int i; 10985e5c12b0Sopenharmony_ci 10995e5c12b0Sopenharmony_ci sbi->log_sectors_per_block = get_sb(log_sectors_per_block); 11005e5c12b0Sopenharmony_ci sbi->log_blocksize = get_sb(log_blocksize); 11015e5c12b0Sopenharmony_ci sbi->blocksize = 1 << sbi->log_blocksize; 11025e5c12b0Sopenharmony_ci sbi->log_blocks_per_seg = get_sb(log_blocks_per_seg); 11035e5c12b0Sopenharmony_ci sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg; 11045e5c12b0Sopenharmony_ci sbi->segs_per_sec = get_sb(segs_per_sec); 11055e5c12b0Sopenharmony_ci sbi->secs_per_zone = get_sb(secs_per_zone); 11065e5c12b0Sopenharmony_ci sbi->total_sections = get_sb(section_count); 11075e5c12b0Sopenharmony_ci sbi->total_node_count = (get_sb(segment_count_nat) / 2) * 11085e5c12b0Sopenharmony_ci sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK; 11095e5c12b0Sopenharmony_ci sbi->root_ino_num = get_sb(root_ino); 11105e5c12b0Sopenharmony_ci sbi->node_ino_num = get_sb(node_ino); 11115e5c12b0Sopenharmony_ci sbi->meta_ino_num = get_sb(meta_ino); 11125e5c12b0Sopenharmony_ci sbi->cur_victim_sec = NULL_SEGNO; 11135e5c12b0Sopenharmony_ci 11145e5c12b0Sopenharmony_ci for (i = 0; i < MAX_DEVICES; i++) { 11155e5c12b0Sopenharmony_ci if (!sb->devs[i].path[0]) 11165e5c12b0Sopenharmony_ci break; 11175e5c12b0Sopenharmony_ci 11185e5c12b0Sopenharmony_ci if (i) { 11195e5c12b0Sopenharmony_ci c.devices[i].path = strdup((char *)sb->devs[i].path); 11205e5c12b0Sopenharmony_ci if (get_device_info(i)) 11215e5c12b0Sopenharmony_ci ASSERT(0); 11225e5c12b0Sopenharmony_ci } else { 11235e5c12b0Sopenharmony_ci ASSERT(!strcmp((char *)sb->devs[i].path, 11245e5c12b0Sopenharmony_ci (char *)c.devices[i].path)); 11255e5c12b0Sopenharmony_ci } 11265e5c12b0Sopenharmony_ci 11275e5c12b0Sopenharmony_ci c.devices[i].total_segments = 11285e5c12b0Sopenharmony_ci le32_to_cpu(sb->devs[i].total_segments); 11295e5c12b0Sopenharmony_ci if (i) 11305e5c12b0Sopenharmony_ci c.devices[i].start_blkaddr = 11315e5c12b0Sopenharmony_ci c.devices[i - 1].end_blkaddr + 1; 11325e5c12b0Sopenharmony_ci c.devices[i].end_blkaddr = c.devices[i].start_blkaddr + 11335e5c12b0Sopenharmony_ci c.devices[i].total_segments * 11345e5c12b0Sopenharmony_ci c.blks_per_seg - 1; 11355e5c12b0Sopenharmony_ci if (i == 0) 11365e5c12b0Sopenharmony_ci c.devices[i].end_blkaddr += get_sb(segment0_blkaddr); 11375e5c12b0Sopenharmony_ci 11385e5c12b0Sopenharmony_ci if (c.zoned_model == F2FS_ZONED_NONE) { 11395e5c12b0Sopenharmony_ci if (c.devices[i].zoned_model == F2FS_ZONED_HM) 11405e5c12b0Sopenharmony_ci c.zoned_model = F2FS_ZONED_HM; 11415e5c12b0Sopenharmony_ci else if (c.devices[i].zoned_model == F2FS_ZONED_HA && 11425e5c12b0Sopenharmony_ci c.zoned_model != F2FS_ZONED_HM) 11435e5c12b0Sopenharmony_ci c.zoned_model = F2FS_ZONED_HA; 11445e5c12b0Sopenharmony_ci } 11455e5c12b0Sopenharmony_ci 11465e5c12b0Sopenharmony_ci c.ndevs = i + 1; 11475e5c12b0Sopenharmony_ci MSG(0, "Info: Device[%d] : %s blkaddr = %"PRIx64"--%"PRIx64"\n", 11485e5c12b0Sopenharmony_ci i, c.devices[i].path, 11495e5c12b0Sopenharmony_ci c.devices[i].start_blkaddr, 11505e5c12b0Sopenharmony_ci c.devices[i].end_blkaddr); 11515e5c12b0Sopenharmony_ci } 11525e5c12b0Sopenharmony_ci 11535e5c12b0Sopenharmony_ci total_sectors = get_sb(block_count) << sbi->log_sectors_per_block; 11545e5c12b0Sopenharmony_ci MSG(0, "Info: Segments per section = %d\n", sbi->segs_per_sec); 11555e5c12b0Sopenharmony_ci MSG(0, "Info: Sections per zone = %d\n", sbi->secs_per_zone); 11565e5c12b0Sopenharmony_ci MSG(0, "Info: total FS sectors = %"PRIu64" (%"PRIu64" MB)\n", 11575e5c12b0Sopenharmony_ci total_sectors, total_sectors >> 11585e5c12b0Sopenharmony_ci (20 - get_sb(log_sectorsize))); 11595e5c12b0Sopenharmony_ci return 0; 11605e5c12b0Sopenharmony_ci} 11615e5c12b0Sopenharmony_ci 11625e5c12b0Sopenharmony_cistatic int verify_checksum_chksum(struct f2fs_checkpoint *cp) 11635e5c12b0Sopenharmony_ci{ 11645e5c12b0Sopenharmony_ci unsigned int chksum_offset = get_cp(checksum_offset); 11655e5c12b0Sopenharmony_ci unsigned int crc, cal_crc; 11665e5c12b0Sopenharmony_ci 11675e5c12b0Sopenharmony_ci if (chksum_offset < CP_MIN_CHKSUM_OFFSET || 11685e5c12b0Sopenharmony_ci chksum_offset > CP_CHKSUM_OFFSET) { 11695e5c12b0Sopenharmony_ci MSG(0, "\tInvalid CP CRC offset: %u\n", chksum_offset); 11705e5c12b0Sopenharmony_ci return -1; 11715e5c12b0Sopenharmony_ci } 11725e5c12b0Sopenharmony_ci 11735e5c12b0Sopenharmony_ci crc = le32_to_cpu(*(__le32 *)((unsigned char *)cp + chksum_offset)); 11745e5c12b0Sopenharmony_ci cal_crc = f2fs_checkpoint_chksum(cp); 11755e5c12b0Sopenharmony_ci if (cal_crc != crc) { 11765e5c12b0Sopenharmony_ci MSG(0, "\tInvalid CP CRC: offset:%u, crc:0x%x, calc:0x%x\n", 11775e5c12b0Sopenharmony_ci chksum_offset, crc, cal_crc); 11785e5c12b0Sopenharmony_ci return -1; 11795e5c12b0Sopenharmony_ci } 11805e5c12b0Sopenharmony_ci return 0; 11815e5c12b0Sopenharmony_ci} 11825e5c12b0Sopenharmony_ci 11835e5c12b0Sopenharmony_cistatic void *get_checkpoint_version(block_t cp_addr) 11845e5c12b0Sopenharmony_ci{ 11855e5c12b0Sopenharmony_ci void *cp_page; 11865e5c12b0Sopenharmony_ci 11875e5c12b0Sopenharmony_ci cp_page = malloc(F2FS_BLKSIZE); 11885e5c12b0Sopenharmony_ci ASSERT(cp_page); 11895e5c12b0Sopenharmony_ci 11905e5c12b0Sopenharmony_ci if (dev_read_block(cp_page, cp_addr) < 0) 11915e5c12b0Sopenharmony_ci ASSERT(0); 11925e5c12b0Sopenharmony_ci 11935e5c12b0Sopenharmony_ci if (verify_checksum_chksum((struct f2fs_checkpoint *)cp_page)) 11945e5c12b0Sopenharmony_ci goto out; 11955e5c12b0Sopenharmony_ci return cp_page; 11965e5c12b0Sopenharmony_ciout: 11975e5c12b0Sopenharmony_ci free(cp_page); 11985e5c12b0Sopenharmony_ci return NULL; 11995e5c12b0Sopenharmony_ci} 12005e5c12b0Sopenharmony_ci 12015e5c12b0Sopenharmony_civoid *validate_checkpoint(struct f2fs_sb_info *sbi, block_t cp_addr, 12025e5c12b0Sopenharmony_ci unsigned long long *version) 12035e5c12b0Sopenharmony_ci{ 12045e5c12b0Sopenharmony_ci void *cp_page_1, *cp_page_2; 12055e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp; 12065e5c12b0Sopenharmony_ci unsigned long long cur_version = 0, pre_version = 0; 12075e5c12b0Sopenharmony_ci 12085e5c12b0Sopenharmony_ci /* Read the 1st cp block in this CP pack */ 12095e5c12b0Sopenharmony_ci cp_page_1 = get_checkpoint_version(cp_addr); 12105e5c12b0Sopenharmony_ci if (!cp_page_1) 12115e5c12b0Sopenharmony_ci return NULL; 12125e5c12b0Sopenharmony_ci 12135e5c12b0Sopenharmony_ci cp = (struct f2fs_checkpoint *)cp_page_1; 12145e5c12b0Sopenharmony_ci if (get_cp(cp_pack_total_block_count) > sbi->blocks_per_seg) 12155e5c12b0Sopenharmony_ci goto invalid_cp1; 12165e5c12b0Sopenharmony_ci 12175e5c12b0Sopenharmony_ci pre_version = get_cp(checkpoint_ver); 12185e5c12b0Sopenharmony_ci 12195e5c12b0Sopenharmony_ci /* Read the 2nd cp block in this CP pack */ 12205e5c12b0Sopenharmony_ci cp_addr += get_cp(cp_pack_total_block_count) - 1; 12215e5c12b0Sopenharmony_ci cp_page_2 = get_checkpoint_version(cp_addr); 12225e5c12b0Sopenharmony_ci if (!cp_page_2) 12235e5c12b0Sopenharmony_ci goto invalid_cp1; 12245e5c12b0Sopenharmony_ci 12255e5c12b0Sopenharmony_ci cp = (struct f2fs_checkpoint *)cp_page_2; 12265e5c12b0Sopenharmony_ci cur_version = get_cp(checkpoint_ver); 12275e5c12b0Sopenharmony_ci 12285e5c12b0Sopenharmony_ci if (cur_version == pre_version) { 12295e5c12b0Sopenharmony_ci *version = cur_version; 12305e5c12b0Sopenharmony_ci free(cp_page_2); 12315e5c12b0Sopenharmony_ci return cp_page_1; 12325e5c12b0Sopenharmony_ci } 12335e5c12b0Sopenharmony_ci 12345e5c12b0Sopenharmony_ci free(cp_page_2); 12355e5c12b0Sopenharmony_ciinvalid_cp1: 12365e5c12b0Sopenharmony_ci free(cp_page_1); 12375e5c12b0Sopenharmony_ci return NULL; 12385e5c12b0Sopenharmony_ci} 12395e5c12b0Sopenharmony_ci 12405e5c12b0Sopenharmony_ciint get_valid_checkpoint(struct f2fs_sb_info *sbi) 12415e5c12b0Sopenharmony_ci{ 12425e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 12435e5c12b0Sopenharmony_ci void *cp1, *cp2, *cur_page; 12445e5c12b0Sopenharmony_ci unsigned long blk_size = sbi->blocksize; 12455e5c12b0Sopenharmony_ci unsigned long long cp1_version = 0, cp2_version = 0, version; 12465e5c12b0Sopenharmony_ci unsigned long long cp_start_blk_no; 12475e5c12b0Sopenharmony_ci unsigned int cp_payload, cp_blks; 12485e5c12b0Sopenharmony_ci int ret; 12495e5c12b0Sopenharmony_ci 12505e5c12b0Sopenharmony_ci cp_payload = get_sb(cp_payload); 12515e5c12b0Sopenharmony_ci if (cp_payload > F2FS_BLK_ALIGN(MAX_CP_PAYLOAD)) 12525e5c12b0Sopenharmony_ci return -EINVAL; 12535e5c12b0Sopenharmony_ci 12545e5c12b0Sopenharmony_ci cp_blks = 1 + cp_payload; 12555e5c12b0Sopenharmony_ci sbi->ckpt = malloc(cp_blks * blk_size); 12565e5c12b0Sopenharmony_ci if (!sbi->ckpt) 12575e5c12b0Sopenharmony_ci return -ENOMEM; 12585e5c12b0Sopenharmony_ci /* 12595e5c12b0Sopenharmony_ci * Finding out valid cp block involves read both 12605e5c12b0Sopenharmony_ci * sets( cp pack1 and cp pack 2) 12615e5c12b0Sopenharmony_ci */ 12625e5c12b0Sopenharmony_ci cp_start_blk_no = get_sb(cp_blkaddr); 12635e5c12b0Sopenharmony_ci cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version); 12645e5c12b0Sopenharmony_ci 12655e5c12b0Sopenharmony_ci /* The second checkpoint pack should start at the next segment */ 12665e5c12b0Sopenharmony_ci cp_start_blk_no += 1 << get_sb(log_blocks_per_seg); 12675e5c12b0Sopenharmony_ci cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version); 12685e5c12b0Sopenharmony_ci 12695e5c12b0Sopenharmony_ci if (cp1 && cp2) { 12705e5c12b0Sopenharmony_ci if (ver_after(cp2_version, cp1_version)) { 12715e5c12b0Sopenharmony_ci cur_page = cp2; 12725e5c12b0Sopenharmony_ci sbi->cur_cp = 2; 12735e5c12b0Sopenharmony_ci version = cp2_version; 12745e5c12b0Sopenharmony_ci } else { 12755e5c12b0Sopenharmony_ci cur_page = cp1; 12765e5c12b0Sopenharmony_ci sbi->cur_cp = 1; 12775e5c12b0Sopenharmony_ci version = cp1_version; 12785e5c12b0Sopenharmony_ci } 12795e5c12b0Sopenharmony_ci } else if (cp1) { 12805e5c12b0Sopenharmony_ci cur_page = cp1; 12815e5c12b0Sopenharmony_ci sbi->cur_cp = 1; 12825e5c12b0Sopenharmony_ci version = cp1_version; 12835e5c12b0Sopenharmony_ci } else if (cp2) { 12845e5c12b0Sopenharmony_ci cur_page = cp2; 12855e5c12b0Sopenharmony_ci sbi->cur_cp = 2; 12865e5c12b0Sopenharmony_ci version = cp2_version; 12875e5c12b0Sopenharmony_ci } else 12885e5c12b0Sopenharmony_ci goto fail_no_cp; 12895e5c12b0Sopenharmony_ci 12905e5c12b0Sopenharmony_ci MSG(0, "Info: CKPT version = %llx\n", version); 12915e5c12b0Sopenharmony_ci 12925e5c12b0Sopenharmony_ci memcpy(sbi->ckpt, cur_page, blk_size); 12935e5c12b0Sopenharmony_ci 12945e5c12b0Sopenharmony_ci if (cp_blks > 1) { 12955e5c12b0Sopenharmony_ci unsigned int i; 12965e5c12b0Sopenharmony_ci unsigned long long cp_blk_no; 12975e5c12b0Sopenharmony_ci 12985e5c12b0Sopenharmony_ci cp_blk_no = get_sb(cp_blkaddr); 12995e5c12b0Sopenharmony_ci if (cur_page == cp2) 13005e5c12b0Sopenharmony_ci cp_blk_no += 1 << get_sb(log_blocks_per_seg); 13015e5c12b0Sopenharmony_ci 13025e5c12b0Sopenharmony_ci /* copy sit bitmap */ 13035e5c12b0Sopenharmony_ci for (i = 1; i < cp_blks; i++) { 13045e5c12b0Sopenharmony_ci unsigned char *ckpt = (unsigned char *)sbi->ckpt; 13055e5c12b0Sopenharmony_ci ret = dev_read_block(cur_page, cp_blk_no + i); 13065e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 13075e5c12b0Sopenharmony_ci memcpy(ckpt + i * blk_size, cur_page, blk_size); 13085e5c12b0Sopenharmony_ci } 13095e5c12b0Sopenharmony_ci } 13105e5c12b0Sopenharmony_ci if (cp1) 13115e5c12b0Sopenharmony_ci free(cp1); 13125e5c12b0Sopenharmony_ci if (cp2) 13135e5c12b0Sopenharmony_ci free(cp2); 13145e5c12b0Sopenharmony_ci return 0; 13155e5c12b0Sopenharmony_ci 13165e5c12b0Sopenharmony_cifail_no_cp: 13175e5c12b0Sopenharmony_ci free(sbi->ckpt); 13185e5c12b0Sopenharmony_ci sbi->ckpt = NULL; 13195e5c12b0Sopenharmony_ci return -EINVAL; 13205e5c12b0Sopenharmony_ci} 13215e5c12b0Sopenharmony_ci 13225e5c12b0Sopenharmony_cibool is_checkpoint_stop(struct f2fs_super_block *sb, bool abnormal) 13235e5c12b0Sopenharmony_ci{ 13245e5c12b0Sopenharmony_ci int i; 13255e5c12b0Sopenharmony_ci 13265e5c12b0Sopenharmony_ci for (i = 0; i < STOP_CP_REASON_MAX; i++) { 13275e5c12b0Sopenharmony_ci if (abnormal && i == STOP_CP_REASON_SHUTDOWN) 13285e5c12b0Sopenharmony_ci continue; 13295e5c12b0Sopenharmony_ci if (sb->s_stop_reason[i]) 13305e5c12b0Sopenharmony_ci return true; 13315e5c12b0Sopenharmony_ci } 13325e5c12b0Sopenharmony_ci 13335e5c12b0Sopenharmony_ci return false; 13345e5c12b0Sopenharmony_ci} 13355e5c12b0Sopenharmony_ci 13365e5c12b0Sopenharmony_cibool is_inconsistent_error(struct f2fs_super_block *sb) 13375e5c12b0Sopenharmony_ci{ 13385e5c12b0Sopenharmony_ci int i; 13395e5c12b0Sopenharmony_ci 13405e5c12b0Sopenharmony_ci for (i = 0; i < MAX_F2FS_ERRORS; i++) { 13415e5c12b0Sopenharmony_ci if (sb->s_errors[i]) 13425e5c12b0Sopenharmony_ci return true; 13435e5c12b0Sopenharmony_ci } 13445e5c12b0Sopenharmony_ci 13455e5c12b0Sopenharmony_ci return false; 13465e5c12b0Sopenharmony_ci} 13475e5c12b0Sopenharmony_ci 13485e5c12b0Sopenharmony_ci/* 13495e5c12b0Sopenharmony_ci * For a return value of 1, caller should further check for c.fix_on state 13505e5c12b0Sopenharmony_ci * and take appropriate action. 13515e5c12b0Sopenharmony_ci */ 13525e5c12b0Sopenharmony_cistatic int f2fs_should_proceed(struct f2fs_super_block *sb, u32 flag) 13535e5c12b0Sopenharmony_ci{ 13545e5c12b0Sopenharmony_ci if (!c.fix_on && (c.auto_fix || c.preen_mode)) { 13555e5c12b0Sopenharmony_ci if (flag & CP_FSCK_FLAG || 13565e5c12b0Sopenharmony_ci flag & CP_QUOTA_NEED_FSCK_FLAG || 13575e5c12b0Sopenharmony_ci c.abnormal_stop || c.fs_errors || 13585e5c12b0Sopenharmony_ci (exist_qf_ino(sb) && (flag & CP_ERROR_FLAG))) { 13595e5c12b0Sopenharmony_ci c.fix_on = 1; 13605e5c12b0Sopenharmony_ci } else if (!c.preen_mode) { 13615e5c12b0Sopenharmony_ci print_cp_state(flag); 13625e5c12b0Sopenharmony_ci return 0; 13635e5c12b0Sopenharmony_ci } 13645e5c12b0Sopenharmony_ci } 13655e5c12b0Sopenharmony_ci return 1; 13665e5c12b0Sopenharmony_ci} 13675e5c12b0Sopenharmony_ci 13685e5c12b0Sopenharmony_ciint sanity_check_ckpt(struct f2fs_sb_info *sbi) 13695e5c12b0Sopenharmony_ci{ 13705e5c12b0Sopenharmony_ci unsigned int total, fsmeta; 13715e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 13725e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 13735e5c12b0Sopenharmony_ci unsigned int flag = get_cp(ckpt_flags); 13745e5c12b0Sopenharmony_ci unsigned int ovp_segments, reserved_segments; 13755e5c12b0Sopenharmony_ci unsigned int main_segs, blocks_per_seg; 13765e5c12b0Sopenharmony_ci unsigned int sit_segs, nat_segs; 13775e5c12b0Sopenharmony_ci unsigned int sit_bitmap_size, nat_bitmap_size; 13785e5c12b0Sopenharmony_ci unsigned int log_blocks_per_seg; 13795e5c12b0Sopenharmony_ci unsigned int segment_count_main; 13805e5c12b0Sopenharmony_ci unsigned int cp_pack_start_sum, cp_payload; 13815e5c12b0Sopenharmony_ci block_t user_block_count; 13825e5c12b0Sopenharmony_ci int i; 13835e5c12b0Sopenharmony_ci 13845e5c12b0Sopenharmony_ci total = get_sb(segment_count); 13855e5c12b0Sopenharmony_ci fsmeta = get_sb(segment_count_ckpt); 13865e5c12b0Sopenharmony_ci sit_segs = get_sb(segment_count_sit); 13875e5c12b0Sopenharmony_ci fsmeta += sit_segs; 13885e5c12b0Sopenharmony_ci nat_segs = get_sb(segment_count_nat); 13895e5c12b0Sopenharmony_ci fsmeta += nat_segs; 13905e5c12b0Sopenharmony_ci fsmeta += get_cp(rsvd_segment_count); 13915e5c12b0Sopenharmony_ci fsmeta += get_sb(segment_count_ssa); 13925e5c12b0Sopenharmony_ci 13935e5c12b0Sopenharmony_ci if (fsmeta >= total) 13945e5c12b0Sopenharmony_ci return 1; 13955e5c12b0Sopenharmony_ci 13965e5c12b0Sopenharmony_ci ovp_segments = get_cp(overprov_segment_count); 13975e5c12b0Sopenharmony_ci reserved_segments = get_cp(rsvd_segment_count); 13985e5c12b0Sopenharmony_ci 13995e5c12b0Sopenharmony_ci if (!(get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) && 14005e5c12b0Sopenharmony_ci (fsmeta < F2FS_MIN_SEGMENT || ovp_segments == 0 || 14015e5c12b0Sopenharmony_ci reserved_segments == 0)) { 14025e5c12b0Sopenharmony_ci MSG(0, "\tWrong layout: check mkfs.f2fs version\n"); 14035e5c12b0Sopenharmony_ci return 1; 14045e5c12b0Sopenharmony_ci } 14055e5c12b0Sopenharmony_ci 14065e5c12b0Sopenharmony_ci user_block_count = get_cp(user_block_count); 14075e5c12b0Sopenharmony_ci segment_count_main = get_sb(segment_count_main) + 14085e5c12b0Sopenharmony_ci (cpu_to_le32(F2FS_FEATURE_RO) ? 1 : 0); 14095e5c12b0Sopenharmony_ci log_blocks_per_seg = get_sb(log_blocks_per_seg); 14105e5c12b0Sopenharmony_ci if (!user_block_count || user_block_count >= 14115e5c12b0Sopenharmony_ci segment_count_main << log_blocks_per_seg) { 14125e5c12b0Sopenharmony_ci ASSERT_MSG("\tWrong user_block_count(%u)\n", user_block_count); 14135e5c12b0Sopenharmony_ci 14145e5c12b0Sopenharmony_ci if (!f2fs_should_proceed(sb, flag)) 14155e5c12b0Sopenharmony_ci return 1; 14165e5c12b0Sopenharmony_ci if (!c.fix_on) 14175e5c12b0Sopenharmony_ci return 1; 14185e5c12b0Sopenharmony_ci 14195e5c12b0Sopenharmony_ci if (flag & (CP_FSCK_FLAG | CP_RESIZEFS_FLAG)) { 14205e5c12b0Sopenharmony_ci u32 valid_user_block_cnt; 14215e5c12b0Sopenharmony_ci u32 seg_cnt_main = get_sb(segment_count) - 14225e5c12b0Sopenharmony_ci (get_sb(segment_count_ckpt) + 14235e5c12b0Sopenharmony_ci get_sb(segment_count_sit) + 14245e5c12b0Sopenharmony_ci get_sb(segment_count_nat) + 14255e5c12b0Sopenharmony_ci get_sb(segment_count_ssa)); 14265e5c12b0Sopenharmony_ci 14275e5c12b0Sopenharmony_ci /* validate segment_count_main in sb first */ 14285e5c12b0Sopenharmony_ci if (seg_cnt_main != get_sb(segment_count_main)) { 14295e5c12b0Sopenharmony_ci MSG(0, "Inconsistent segment_cnt_main %u in sb\n", 14305e5c12b0Sopenharmony_ci segment_count_main << log_blocks_per_seg); 14315e5c12b0Sopenharmony_ci return 1; 14325e5c12b0Sopenharmony_ci } 14335e5c12b0Sopenharmony_ci valid_user_block_cnt = ((get_sb(segment_count_main) - 14345e5c12b0Sopenharmony_ci get_cp(overprov_segment_count)) * c.blks_per_seg); 14355e5c12b0Sopenharmony_ci MSG(0, "Info: Fix wrong user_block_count in CP: (%u) -> (%u)\n", 14365e5c12b0Sopenharmony_ci user_block_count, valid_user_block_cnt); 14375e5c12b0Sopenharmony_ci set_cp(user_block_count, valid_user_block_cnt); 14385e5c12b0Sopenharmony_ci c.bug_on = 1; 14395e5c12b0Sopenharmony_ci } 14405e5c12b0Sopenharmony_ci } 14415e5c12b0Sopenharmony_ci 14425e5c12b0Sopenharmony_ci main_segs = get_sb(segment_count_main); 14435e5c12b0Sopenharmony_ci blocks_per_seg = sbi->blocks_per_seg; 14445e5c12b0Sopenharmony_ci 14455e5c12b0Sopenharmony_ci for (i = 0; i < NR_CURSEG_NODE_TYPE; i++) { 14465e5c12b0Sopenharmony_ci if (get_cp(cur_node_segno[i]) >= main_segs || 14475e5c12b0Sopenharmony_ci get_cp(cur_node_blkoff[i]) >= blocks_per_seg) 14485e5c12b0Sopenharmony_ci return 1; 14495e5c12b0Sopenharmony_ci } 14505e5c12b0Sopenharmony_ci for (i = 0; i < NR_CURSEG_DATA_TYPE; i++) { 14515e5c12b0Sopenharmony_ci if (get_cp(cur_data_segno[i]) >= main_segs || 14525e5c12b0Sopenharmony_ci get_cp(cur_data_blkoff[i]) >= blocks_per_seg) 14535e5c12b0Sopenharmony_ci return 1; 14545e5c12b0Sopenharmony_ci } 14555e5c12b0Sopenharmony_ci 14565e5c12b0Sopenharmony_ci sit_bitmap_size = get_cp(sit_ver_bitmap_bytesize); 14575e5c12b0Sopenharmony_ci nat_bitmap_size = get_cp(nat_ver_bitmap_bytesize); 14585e5c12b0Sopenharmony_ci 14595e5c12b0Sopenharmony_ci if (sit_bitmap_size != ((sit_segs / 2) << log_blocks_per_seg) / 8 || 14605e5c12b0Sopenharmony_ci nat_bitmap_size != ((nat_segs / 2) << log_blocks_per_seg) / 8) { 14615e5c12b0Sopenharmony_ci MSG(0, "\tWrong bitmap size: sit(%u), nat(%u)\n", 14625e5c12b0Sopenharmony_ci sit_bitmap_size, nat_bitmap_size); 14635e5c12b0Sopenharmony_ci return 1; 14645e5c12b0Sopenharmony_ci } 14655e5c12b0Sopenharmony_ci 14665e5c12b0Sopenharmony_ci cp_pack_start_sum = __start_sum_addr(sbi); 14675e5c12b0Sopenharmony_ci cp_payload = __cp_payload(sbi); 14685e5c12b0Sopenharmony_ci if (cp_pack_start_sum < cp_payload + 1 || 14695e5c12b0Sopenharmony_ci cp_pack_start_sum > blocks_per_seg - 1 - 14705e5c12b0Sopenharmony_ci NR_CURSEG_TYPE) { 14715e5c12b0Sopenharmony_ci MSG(0, "\tWrong cp_pack_start_sum(%u) or cp_payload(%u)\n", 14725e5c12b0Sopenharmony_ci cp_pack_start_sum, cp_payload); 14735e5c12b0Sopenharmony_ci if ((get_sb(feature) & F2FS_FEATURE_SB_CHKSUM)) 14745e5c12b0Sopenharmony_ci return 1; 14755e5c12b0Sopenharmony_ci set_sb(cp_payload, cp_pack_start_sum - 1); 14765e5c12b0Sopenharmony_ci update_superblock(sb, SB_MASK_ALL); 14775e5c12b0Sopenharmony_ci } 14785e5c12b0Sopenharmony_ci 14795e5c12b0Sopenharmony_ci return 0; 14805e5c12b0Sopenharmony_ci} 14815e5c12b0Sopenharmony_ci 14825e5c12b0Sopenharmony_cipgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start, int *pack) 14835e5c12b0Sopenharmony_ci{ 14845e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 14855e5c12b0Sopenharmony_ci pgoff_t block_off; 14865e5c12b0Sopenharmony_ci pgoff_t block_addr; 14875e5c12b0Sopenharmony_ci int seg_off; 14885e5c12b0Sopenharmony_ci 14895e5c12b0Sopenharmony_ci block_off = NAT_BLOCK_OFFSET(start); 14905e5c12b0Sopenharmony_ci seg_off = block_off >> sbi->log_blocks_per_seg; 14915e5c12b0Sopenharmony_ci 14925e5c12b0Sopenharmony_ci block_addr = (pgoff_t)(nm_i->nat_blkaddr + 14935e5c12b0Sopenharmony_ci (seg_off << sbi->log_blocks_per_seg << 1) + 14945e5c12b0Sopenharmony_ci (block_off & ((1 << sbi->log_blocks_per_seg) -1))); 14955e5c12b0Sopenharmony_ci if (pack) 14965e5c12b0Sopenharmony_ci *pack = 1; 14975e5c12b0Sopenharmony_ci 14985e5c12b0Sopenharmony_ci if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) { 14995e5c12b0Sopenharmony_ci block_addr += sbi->blocks_per_seg; 15005e5c12b0Sopenharmony_ci if (pack) 15015e5c12b0Sopenharmony_ci *pack = 2; 15025e5c12b0Sopenharmony_ci } 15035e5c12b0Sopenharmony_ci 15045e5c12b0Sopenharmony_ci return block_addr; 15055e5c12b0Sopenharmony_ci} 15065e5c12b0Sopenharmony_ci 15075e5c12b0Sopenharmony_ci/* will not init nid_bitmap from nat */ 15085e5c12b0Sopenharmony_cistatic int f2fs_early_init_nid_bitmap(struct f2fs_sb_info *sbi) 15095e5c12b0Sopenharmony_ci{ 15105e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 15115e5c12b0Sopenharmony_ci int nid_bitmap_size = (nm_i->max_nid + BITS_PER_BYTE - 1) / BITS_PER_BYTE; 15125e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 15135e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum = curseg->sum_blk; 15145e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &sum->journal; 15155e5c12b0Sopenharmony_ci nid_t nid; 15165e5c12b0Sopenharmony_ci int i; 15175e5c12b0Sopenharmony_ci 15185e5c12b0Sopenharmony_ci if (!(c.func == SLOAD || c.func == FSCK)) 15195e5c12b0Sopenharmony_ci return 0; 15205e5c12b0Sopenharmony_ci 15215e5c12b0Sopenharmony_ci nm_i->nid_bitmap = (char *)calloc(nid_bitmap_size, 1); 15225e5c12b0Sopenharmony_ci if (!nm_i->nid_bitmap) 15235e5c12b0Sopenharmony_ci return -ENOMEM; 15245e5c12b0Sopenharmony_ci 15255e5c12b0Sopenharmony_ci /* arbitrarily set 0 bit */ 15265e5c12b0Sopenharmony_ci f2fs_set_bit(0, nm_i->nid_bitmap); 15275e5c12b0Sopenharmony_ci 15285e5c12b0Sopenharmony_ci if (nats_in_cursum(journal) > NAT_JOURNAL_ENTRIES) { 15295e5c12b0Sopenharmony_ci MSG(0, "\tError: f2fs_init_nid_bitmap truncate n_nats(%u) to " 15305e5c12b0Sopenharmony_ci "NAT_JOURNAL_ENTRIES(%zu)\n", 15315e5c12b0Sopenharmony_ci nats_in_cursum(journal), NAT_JOURNAL_ENTRIES); 15325e5c12b0Sopenharmony_ci journal->n_nats = cpu_to_le16(NAT_JOURNAL_ENTRIES); 15335e5c12b0Sopenharmony_ci c.fix_on = 1; 15345e5c12b0Sopenharmony_ci } 15355e5c12b0Sopenharmony_ci 15365e5c12b0Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 15375e5c12b0Sopenharmony_ci block_t addr; 15385e5c12b0Sopenharmony_ci 15395e5c12b0Sopenharmony_ci addr = le32_to_cpu(nat_in_journal(journal, i).block_addr); 15405e5c12b0Sopenharmony_ci if (!IS_VALID_BLK_ADDR(sbi, addr)) { 15415e5c12b0Sopenharmony_ci MSG(0, "\tError: f2fs_init_nid_bitmap: addr(%u) is invalid!!!\n", addr); 15425e5c12b0Sopenharmony_ci journal->n_nats = cpu_to_le16(i); 15435e5c12b0Sopenharmony_ci c.fix_on = 1; 15445e5c12b0Sopenharmony_ci continue; 15455e5c12b0Sopenharmony_ci } 15465e5c12b0Sopenharmony_ci 15475e5c12b0Sopenharmony_ci nid = le32_to_cpu(nid_in_journal(journal, i)); 15485e5c12b0Sopenharmony_ci if (!IS_VALID_NID(sbi, nid)) { 15495e5c12b0Sopenharmony_ci MSG(0, "\tError: f2fs_init_nid_bitmap: nid(%u) is invalid!!!\n", nid); 15505e5c12b0Sopenharmony_ci journal->n_nats = cpu_to_le16(i); 15515e5c12b0Sopenharmony_ci c.fix_on = 1; 15525e5c12b0Sopenharmony_ci continue; 15535e5c12b0Sopenharmony_ci } 15545e5c12b0Sopenharmony_ci if (addr != NULL_ADDR) 15555e5c12b0Sopenharmony_ci f2fs_set_bit(nid, nm_i->nid_bitmap); 15565e5c12b0Sopenharmony_ci } 15575e5c12b0Sopenharmony_ci return 0; 15585e5c12b0Sopenharmony_ci} 15595e5c12b0Sopenharmony_ci 15605e5c12b0Sopenharmony_ci/* will init nid_bitmap from nat */ 15615e5c12b0Sopenharmony_cistatic int f2fs_late_init_nid_bitmap(struct f2fs_sb_info *sbi) 15625e5c12b0Sopenharmony_ci{ 15635e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 15645e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 15655e5c12b0Sopenharmony_ci block_t start_blk; 15665e5c12b0Sopenharmony_ci nid_t nid; 15675e5c12b0Sopenharmony_ci 15685e5c12b0Sopenharmony_ci if (!(c.func == SLOAD || c.func == FSCK)) 15695e5c12b0Sopenharmony_ci return 0; 15705e5c12b0Sopenharmony_ci 15715e5c12b0Sopenharmony_ci nat_block = malloc(F2FS_BLKSIZE); 15725e5c12b0Sopenharmony_ci if (!nat_block) { 15735e5c12b0Sopenharmony_ci free(nm_i->nid_bitmap); 15745e5c12b0Sopenharmony_ci return -ENOMEM; 15755e5c12b0Sopenharmony_ci } 15765e5c12b0Sopenharmony_ci 15775e5c12b0Sopenharmony_ci f2fs_ra_meta_pages(sbi, 0, NAT_BLOCK_OFFSET(nm_i->max_nid), 15785e5c12b0Sopenharmony_ci META_NAT); 15795e5c12b0Sopenharmony_ci for (nid = 0; nid < nm_i->max_nid; nid++) { 15805e5c12b0Sopenharmony_ci if (!(nid % NAT_ENTRY_PER_BLOCK)) { 15815e5c12b0Sopenharmony_ci int ret; 15825e5c12b0Sopenharmony_ci 15835e5c12b0Sopenharmony_ci start_blk = current_nat_addr(sbi, nid, NULL); 15845e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, start_blk); 15855e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 15865e5c12b0Sopenharmony_ci } 15875e5c12b0Sopenharmony_ci 15885e5c12b0Sopenharmony_ci if (nat_block->entries[nid % NAT_ENTRY_PER_BLOCK].block_addr) 15895e5c12b0Sopenharmony_ci f2fs_set_bit(nid, nm_i->nid_bitmap); 15905e5c12b0Sopenharmony_ci } 15915e5c12b0Sopenharmony_ci 15925e5c12b0Sopenharmony_ci free(nat_block); 15935e5c12b0Sopenharmony_ci return 0; 15945e5c12b0Sopenharmony_ci} 15955e5c12b0Sopenharmony_ci 15965e5c12b0Sopenharmony_ciu32 update_nat_bits_flags(struct f2fs_super_block *sb, 15975e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp, u32 flags) 15985e5c12b0Sopenharmony_ci{ 15995e5c12b0Sopenharmony_ci uint32_t nat_bits_bytes, nat_bits_blocks; 16005e5c12b0Sopenharmony_ci 16015e5c12b0Sopenharmony_ci nat_bits_bytes = get_sb(segment_count_nat) << 5; 16025e5c12b0Sopenharmony_ci nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 8 + 16035e5c12b0Sopenharmony_ci F2FS_BLKSIZE - 1); 16045e5c12b0Sopenharmony_ci if (get_cp(cp_pack_total_block_count) <= 16055e5c12b0Sopenharmony_ci (1 << get_sb(log_blocks_per_seg)) - nat_bits_blocks) 16065e5c12b0Sopenharmony_ci flags |= CP_NAT_BITS_FLAG; 16075e5c12b0Sopenharmony_ci else 16085e5c12b0Sopenharmony_ci flags &= (~CP_NAT_BITS_FLAG); 16095e5c12b0Sopenharmony_ci 16105e5c12b0Sopenharmony_ci return flags; 16115e5c12b0Sopenharmony_ci} 16125e5c12b0Sopenharmony_ci 16135e5c12b0Sopenharmony_ci/* should call flush_journal_entries() bfore this */ 16145e5c12b0Sopenharmony_civoid write_nat_bits(struct f2fs_sb_info *sbi, 16155e5c12b0Sopenharmony_ci struct f2fs_super_block *sb, struct f2fs_checkpoint *cp, int set) 16165e5c12b0Sopenharmony_ci{ 16175e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 16185e5c12b0Sopenharmony_ci uint32_t nat_blocks = get_sb(segment_count_nat) << 16195e5c12b0Sopenharmony_ci (get_sb(log_blocks_per_seg) - 1); 16205e5c12b0Sopenharmony_ci uint32_t nat_bits_bytes = nat_blocks >> 3; 16215e5c12b0Sopenharmony_ci uint32_t nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 16225e5c12b0Sopenharmony_ci 8 + F2FS_BLKSIZE - 1); 16235e5c12b0Sopenharmony_ci unsigned char *nat_bits, *full_nat_bits, *empty_nat_bits; 16245e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 16255e5c12b0Sopenharmony_ci uint32_t i, j; 16265e5c12b0Sopenharmony_ci block_t blkaddr; 16275e5c12b0Sopenharmony_ci int ret; 16285e5c12b0Sopenharmony_ci 16295e5c12b0Sopenharmony_ci nat_bits = calloc(F2FS_BLKSIZE, nat_bits_blocks); 16305e5c12b0Sopenharmony_ci ASSERT(nat_bits); 16315e5c12b0Sopenharmony_ci 16325e5c12b0Sopenharmony_ci nat_block = malloc(F2FS_BLKSIZE); 16335e5c12b0Sopenharmony_ci ASSERT(nat_block); 16345e5c12b0Sopenharmony_ci 16355e5c12b0Sopenharmony_ci full_nat_bits = nat_bits + 8; 16365e5c12b0Sopenharmony_ci empty_nat_bits = full_nat_bits + nat_bits_bytes; 16375e5c12b0Sopenharmony_ci 16385e5c12b0Sopenharmony_ci memset(full_nat_bits, 0, nat_bits_bytes); 16395e5c12b0Sopenharmony_ci memset(empty_nat_bits, 0, nat_bits_bytes); 16405e5c12b0Sopenharmony_ci 16415e5c12b0Sopenharmony_ci for (i = 0; i < nat_blocks; i++) { 16425e5c12b0Sopenharmony_ci int seg_off = i >> get_sb(log_blocks_per_seg); 16435e5c12b0Sopenharmony_ci int valid = 0; 16445e5c12b0Sopenharmony_ci 16455e5c12b0Sopenharmony_ci blkaddr = (pgoff_t)(get_sb(nat_blkaddr) + 16465e5c12b0Sopenharmony_ci (seg_off << get_sb(log_blocks_per_seg) << 1) + 16475e5c12b0Sopenharmony_ci (i & ((1 << get_sb(log_blocks_per_seg)) - 1))); 16485e5c12b0Sopenharmony_ci 16495e5c12b0Sopenharmony_ci /* 16505e5c12b0Sopenharmony_ci * Should consider new nat_blocks is larger than old 16515e5c12b0Sopenharmony_ci * nm_i->nat_blocks, since nm_i->nat_bitmap is based on 16525e5c12b0Sopenharmony_ci * old one. 16535e5c12b0Sopenharmony_ci */ 16545e5c12b0Sopenharmony_ci if (i < nm_i->nat_blocks && f2fs_test_bit(i, nm_i->nat_bitmap)) 16555e5c12b0Sopenharmony_ci blkaddr += (1 << get_sb(log_blocks_per_seg)); 16565e5c12b0Sopenharmony_ci 16575e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, blkaddr); 16585e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 16595e5c12b0Sopenharmony_ci 16605e5c12b0Sopenharmony_ci for (j = 0; j < NAT_ENTRY_PER_BLOCK; j++) { 16615e5c12b0Sopenharmony_ci if ((i == 0 && j == 0) || 16625e5c12b0Sopenharmony_ci nat_block->entries[j].block_addr != NULL_ADDR) 16635e5c12b0Sopenharmony_ci valid++; 16645e5c12b0Sopenharmony_ci } 16655e5c12b0Sopenharmony_ci if (valid == 0) 16665e5c12b0Sopenharmony_ci test_and_set_bit_le(i, empty_nat_bits); 16675e5c12b0Sopenharmony_ci else if (valid == NAT_ENTRY_PER_BLOCK) 16685e5c12b0Sopenharmony_ci test_and_set_bit_le(i, full_nat_bits); 16695e5c12b0Sopenharmony_ci } 16705e5c12b0Sopenharmony_ci *(__le64 *)nat_bits = get_cp_crc(cp); 16715e5c12b0Sopenharmony_ci free(nat_block); 16725e5c12b0Sopenharmony_ci 16735e5c12b0Sopenharmony_ci blkaddr = get_sb(segment0_blkaddr) + (set << 16745e5c12b0Sopenharmony_ci get_sb(log_blocks_per_seg)) - nat_bits_blocks; 16755e5c12b0Sopenharmony_ci 16765e5c12b0Sopenharmony_ci DBG(1, "\tWriting NAT bits pages, at offset 0x%08x\n", blkaddr); 16775e5c12b0Sopenharmony_ci 16785e5c12b0Sopenharmony_ci for (i = 0; i < nat_bits_blocks; i++) { 16795e5c12b0Sopenharmony_ci if (dev_write_block(nat_bits + i * F2FS_BLKSIZE, blkaddr + i)) 16805e5c12b0Sopenharmony_ci ASSERT_MSG("\tError: write NAT bits to disk!!!\n"); 16815e5c12b0Sopenharmony_ci } 16825e5c12b0Sopenharmony_ci MSG(0, "Info: Write valid nat_bits in checkpoint\n"); 16835e5c12b0Sopenharmony_ci 16845e5c12b0Sopenharmony_ci free(nat_bits); 16855e5c12b0Sopenharmony_ci} 16865e5c12b0Sopenharmony_ci 16875e5c12b0Sopenharmony_cistatic int check_nat_bits(struct f2fs_sb_info *sbi, 16885e5c12b0Sopenharmony_ci struct f2fs_super_block *sb, struct f2fs_checkpoint *cp) 16895e5c12b0Sopenharmony_ci{ 16905e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 16915e5c12b0Sopenharmony_ci uint32_t nat_blocks = get_sb(segment_count_nat) << 16925e5c12b0Sopenharmony_ci (get_sb(log_blocks_per_seg) - 1); 16935e5c12b0Sopenharmony_ci uint32_t nat_bits_bytes = nat_blocks >> 3; 16945e5c12b0Sopenharmony_ci uint32_t nat_bits_blocks = F2FS_BYTES_TO_BLK((nat_bits_bytes << 1) + 16955e5c12b0Sopenharmony_ci 8 + F2FS_BLKSIZE - 1); 16965e5c12b0Sopenharmony_ci unsigned char *nat_bits, *full_nat_bits, *empty_nat_bits; 16975e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 16985e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 16995e5c12b0Sopenharmony_ci uint32_t i, j; 17005e5c12b0Sopenharmony_ci block_t blkaddr; 17015e5c12b0Sopenharmony_ci int err = 0; 17025e5c12b0Sopenharmony_ci 17035e5c12b0Sopenharmony_ci nat_bits = calloc(F2FS_BLKSIZE, nat_bits_blocks); 17045e5c12b0Sopenharmony_ci ASSERT(nat_bits); 17055e5c12b0Sopenharmony_ci 17065e5c12b0Sopenharmony_ci full_nat_bits = nat_bits + 8; 17075e5c12b0Sopenharmony_ci empty_nat_bits = full_nat_bits + nat_bits_bytes; 17085e5c12b0Sopenharmony_ci 17095e5c12b0Sopenharmony_ci blkaddr = get_sb(segment0_blkaddr) + (sbi->cur_cp << 17105e5c12b0Sopenharmony_ci get_sb(log_blocks_per_seg)) - nat_bits_blocks; 17115e5c12b0Sopenharmony_ci 17125e5c12b0Sopenharmony_ci for (i = 0; i < nat_bits_blocks; i++) { 17135e5c12b0Sopenharmony_ci if (dev_read_block(nat_bits + i * F2FS_BLKSIZE, blkaddr + i)) 17145e5c12b0Sopenharmony_ci ASSERT_MSG("\tError: read NAT bits to disk!!!\n"); 17155e5c12b0Sopenharmony_ci } 17165e5c12b0Sopenharmony_ci 17175e5c12b0Sopenharmony_ci if (*(__le64 *)nat_bits != get_cp_crc(cp) || nats_in_cursum(journal)) { 17185e5c12b0Sopenharmony_ci /* 17195e5c12b0Sopenharmony_ci * if there is a journal, f2fs was not shutdown cleanly. Let's 17205e5c12b0Sopenharmony_ci * flush them with nat_bits. 17215e5c12b0Sopenharmony_ci */ 17225e5c12b0Sopenharmony_ci if (c.fix_on) 17235e5c12b0Sopenharmony_ci err = -1; 17245e5c12b0Sopenharmony_ci /* Otherwise, kernel will disable nat_bits */ 17255e5c12b0Sopenharmony_ci goto out; 17265e5c12b0Sopenharmony_ci } 17275e5c12b0Sopenharmony_ci 17285e5c12b0Sopenharmony_ci for (i = 0; i < nat_blocks; i++) { 17295e5c12b0Sopenharmony_ci uint32_t start_nid = i * NAT_ENTRY_PER_BLOCK; 17305e5c12b0Sopenharmony_ci uint32_t valid = 0; 17315e5c12b0Sopenharmony_ci int empty = test_bit_le(i, empty_nat_bits); 17325e5c12b0Sopenharmony_ci int full = test_bit_le(i, full_nat_bits); 17335e5c12b0Sopenharmony_ci 17345e5c12b0Sopenharmony_ci for (j = 0; j < NAT_ENTRY_PER_BLOCK; j++) { 17355e5c12b0Sopenharmony_ci if (f2fs_test_bit(start_nid + j, nm_i->nid_bitmap)) 17365e5c12b0Sopenharmony_ci valid++; 17375e5c12b0Sopenharmony_ci } 17385e5c12b0Sopenharmony_ci if (valid == 0) { 17395e5c12b0Sopenharmony_ci if (!empty || full) { 17405e5c12b0Sopenharmony_ci err = -1; 17415e5c12b0Sopenharmony_ci goto out; 17425e5c12b0Sopenharmony_ci } 17435e5c12b0Sopenharmony_ci } else if (valid == NAT_ENTRY_PER_BLOCK) { 17445e5c12b0Sopenharmony_ci if (empty || !full) { 17455e5c12b0Sopenharmony_ci err = -1; 17465e5c12b0Sopenharmony_ci goto out; 17475e5c12b0Sopenharmony_ci } 17485e5c12b0Sopenharmony_ci } else { 17495e5c12b0Sopenharmony_ci if (empty || full) { 17505e5c12b0Sopenharmony_ci err = -1; 17515e5c12b0Sopenharmony_ci goto out; 17525e5c12b0Sopenharmony_ci } 17535e5c12b0Sopenharmony_ci } 17545e5c12b0Sopenharmony_ci } 17555e5c12b0Sopenharmony_ciout: 17565e5c12b0Sopenharmony_ci free(nat_bits); 17575e5c12b0Sopenharmony_ci if (!err) { 17585e5c12b0Sopenharmony_ci MSG(0, "Info: Checked valid nat_bits in checkpoint\n"); 17595e5c12b0Sopenharmony_ci } else { 17605e5c12b0Sopenharmony_ci c.bug_nat_bits = 1; 17615e5c12b0Sopenharmony_ci MSG(0, "Info: Corrupted valid nat_bits in checkpoint\n"); 17625e5c12b0Sopenharmony_ci } 17635e5c12b0Sopenharmony_ci return err; 17645e5c12b0Sopenharmony_ci} 17655e5c12b0Sopenharmony_ci 17665e5c12b0Sopenharmony_ciint init_node_manager(struct f2fs_sb_info *sbi) 17675e5c12b0Sopenharmony_ci{ 17685e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 17695e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 17705e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 17715e5c12b0Sopenharmony_ci unsigned char *version_bitmap; 17725e5c12b0Sopenharmony_ci unsigned int nat_segs; 17735e5c12b0Sopenharmony_ci 17745e5c12b0Sopenharmony_ci nm_i->nat_blkaddr = get_sb(nat_blkaddr); 17755e5c12b0Sopenharmony_ci 17765e5c12b0Sopenharmony_ci /* segment_count_nat includes pair segment so divide to 2. */ 17775e5c12b0Sopenharmony_ci nat_segs = get_sb(segment_count_nat) >> 1; 17785e5c12b0Sopenharmony_ci nm_i->nat_blocks = nat_segs << get_sb(log_blocks_per_seg); 17795e5c12b0Sopenharmony_ci nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nm_i->nat_blocks; 17805e5c12b0Sopenharmony_ci nm_i->fcnt = 0; 17815e5c12b0Sopenharmony_ci nm_i->nat_cnt = 0; 17825e5c12b0Sopenharmony_ci nm_i->init_scan_nid = get_cp(next_free_nid); 17835e5c12b0Sopenharmony_ci nm_i->next_scan_nid = get_cp(next_free_nid); 17845e5c12b0Sopenharmony_ci 17855e5c12b0Sopenharmony_ci nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); 17865e5c12b0Sopenharmony_ci 17875e5c12b0Sopenharmony_ci nm_i->nat_bitmap = malloc(nm_i->bitmap_size); 17885e5c12b0Sopenharmony_ci if (!nm_i->nat_bitmap) 17895e5c12b0Sopenharmony_ci return -ENOMEM; 17905e5c12b0Sopenharmony_ci version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); 17915e5c12b0Sopenharmony_ci if (!version_bitmap) 17925e5c12b0Sopenharmony_ci return -EFAULT; 17935e5c12b0Sopenharmony_ci 17945e5c12b0Sopenharmony_ci /* copy version bitmap */ 17955e5c12b0Sopenharmony_ci memcpy(nm_i->nat_bitmap, version_bitmap, nm_i->bitmap_size); 17965e5c12b0Sopenharmony_ci return f2fs_early_init_nid_bitmap(sbi); 17975e5c12b0Sopenharmony_ci} 17985e5c12b0Sopenharmony_ci 17995e5c12b0Sopenharmony_ciint build_node_manager(struct f2fs_sb_info *sbi) 18005e5c12b0Sopenharmony_ci{ 18015e5c12b0Sopenharmony_ci int err; 18025e5c12b0Sopenharmony_ci sbi->nm_info = malloc(sizeof(struct f2fs_nm_info)); 18035e5c12b0Sopenharmony_ci if (!sbi->nm_info) 18045e5c12b0Sopenharmony_ci return -ENOMEM; 18055e5c12b0Sopenharmony_ci 18065e5c12b0Sopenharmony_ci err = init_node_manager(sbi); 18075e5c12b0Sopenharmony_ci if (err) 18085e5c12b0Sopenharmony_ci return err; 18095e5c12b0Sopenharmony_ci 18105e5c12b0Sopenharmony_ci return 0; 18115e5c12b0Sopenharmony_ci} 18125e5c12b0Sopenharmony_ci 18135e5c12b0Sopenharmony_ciint build_sit_info(struct f2fs_sb_info *sbi) 18145e5c12b0Sopenharmony_ci{ 18155e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 18165e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 18175e5c12b0Sopenharmony_ci struct sit_info *sit_i; 18185e5c12b0Sopenharmony_ci unsigned int sit_segs; 18195e5c12b0Sopenharmony_ci int start; 18205e5c12b0Sopenharmony_ci char *src_bitmap, *dst_bitmap; 18215e5c12b0Sopenharmony_ci unsigned char *bitmap; 18225e5c12b0Sopenharmony_ci unsigned int bitmap_size; 18235e5c12b0Sopenharmony_ci 18245e5c12b0Sopenharmony_ci sit_i = malloc(sizeof(struct sit_info)); 18255e5c12b0Sopenharmony_ci if (!sit_i) { 18265e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc failed for build_sit_info!\n"); 18275e5c12b0Sopenharmony_ci return -ENOMEM; 18285e5c12b0Sopenharmony_ci } 18295e5c12b0Sopenharmony_ci 18305e5c12b0Sopenharmony_ci SM_I(sbi)->sit_info = sit_i; 18315e5c12b0Sopenharmony_ci 18325e5c12b0Sopenharmony_ci sit_i->sentries = calloc(MAIN_SEGS(sbi) * sizeof(struct seg_entry), 1); 18335e5c12b0Sopenharmony_ci if (!sit_i->sentries) { 18345e5c12b0Sopenharmony_ci MSG(1, "\tError: Calloc failed for build_sit_info!\n"); 18355e5c12b0Sopenharmony_ci goto free_sit_info; 18365e5c12b0Sopenharmony_ci } 18375e5c12b0Sopenharmony_ci 18385e5c12b0Sopenharmony_ci bitmap_size = MAIN_SEGS(sbi) * SIT_VBLOCK_MAP_SIZE; 18395e5c12b0Sopenharmony_ci 18405e5c12b0Sopenharmony_ci if (need_fsync_data_record(sbi)) 18415e5c12b0Sopenharmony_ci bitmap_size += bitmap_size; 18425e5c12b0Sopenharmony_ci 18435e5c12b0Sopenharmony_ci sit_i->bitmap = calloc(bitmap_size, 1); 18445e5c12b0Sopenharmony_ci if (!sit_i->bitmap) { 18455e5c12b0Sopenharmony_ci MSG(1, "\tError: Calloc failed for build_sit_info!!\n"); 18465e5c12b0Sopenharmony_ci goto free_sentries; 18475e5c12b0Sopenharmony_ci } 18485e5c12b0Sopenharmony_ci 18495e5c12b0Sopenharmony_ci bitmap = sit_i->bitmap; 18505e5c12b0Sopenharmony_ci 18515e5c12b0Sopenharmony_ci for (start = 0; start < MAIN_SEGS(sbi); start++) { 18525e5c12b0Sopenharmony_ci sit_i->sentries[start].cur_valid_map = bitmap; 18535e5c12b0Sopenharmony_ci bitmap += SIT_VBLOCK_MAP_SIZE; 18545e5c12b0Sopenharmony_ci 18555e5c12b0Sopenharmony_ci if (need_fsync_data_record(sbi)) { 18565e5c12b0Sopenharmony_ci sit_i->sentries[start].ckpt_valid_map = bitmap; 18575e5c12b0Sopenharmony_ci bitmap += SIT_VBLOCK_MAP_SIZE; 18585e5c12b0Sopenharmony_ci } 18595e5c12b0Sopenharmony_ci } 18605e5c12b0Sopenharmony_ci 18615e5c12b0Sopenharmony_ci sit_segs = get_sb(segment_count_sit) >> 1; 18625e5c12b0Sopenharmony_ci bitmap_size = __bitmap_size(sbi, SIT_BITMAP); 18635e5c12b0Sopenharmony_ci src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); 18645e5c12b0Sopenharmony_ci 18655e5c12b0Sopenharmony_ci dst_bitmap = malloc(bitmap_size); 18665e5c12b0Sopenharmony_ci if (!dst_bitmap) { 18675e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc failed for build_sit_info!!\n"); 18685e5c12b0Sopenharmony_ci goto free_validity_maps; 18695e5c12b0Sopenharmony_ci } 18705e5c12b0Sopenharmony_ci 18715e5c12b0Sopenharmony_ci memcpy(dst_bitmap, src_bitmap, bitmap_size); 18725e5c12b0Sopenharmony_ci 18735e5c12b0Sopenharmony_ci sit_i->sit_base_addr = get_sb(sit_blkaddr); 18745e5c12b0Sopenharmony_ci sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; 18755e5c12b0Sopenharmony_ci sit_i->written_valid_blocks = get_cp(valid_block_count); 18765e5c12b0Sopenharmony_ci sit_i->sit_bitmap = dst_bitmap; 18775e5c12b0Sopenharmony_ci sit_i->bitmap_size = bitmap_size; 18785e5c12b0Sopenharmony_ci sit_i->dirty_sentries = 0; 18795e5c12b0Sopenharmony_ci sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; 18805e5c12b0Sopenharmony_ci sit_i->elapsed_time = get_cp(elapsed_time); 18815e5c12b0Sopenharmony_ci return 0; 18825e5c12b0Sopenharmony_ci 18835e5c12b0Sopenharmony_cifree_validity_maps: 18845e5c12b0Sopenharmony_ci free(sit_i->bitmap); 18855e5c12b0Sopenharmony_cifree_sentries: 18865e5c12b0Sopenharmony_ci free(sit_i->sentries); 18875e5c12b0Sopenharmony_cifree_sit_info: 18885e5c12b0Sopenharmony_ci free(sit_i); 18895e5c12b0Sopenharmony_ci 18905e5c12b0Sopenharmony_ci return -ENOMEM; 18915e5c12b0Sopenharmony_ci} 18925e5c12b0Sopenharmony_ci 18935e5c12b0Sopenharmony_civoid reset_curseg(struct f2fs_sb_info *sbi, int type) 18945e5c12b0Sopenharmony_ci{ 18955e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, type); 18965e5c12b0Sopenharmony_ci struct summary_footer *sum_footer; 18975e5c12b0Sopenharmony_ci struct seg_entry *se; 18985e5c12b0Sopenharmony_ci 18995e5c12b0Sopenharmony_ci sum_footer = &(curseg->sum_blk->footer); 19005e5c12b0Sopenharmony_ci memset(sum_footer, 0, sizeof(struct summary_footer)); 19015e5c12b0Sopenharmony_ci if (IS_DATASEG(type)) 19025e5c12b0Sopenharmony_ci SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); 19035e5c12b0Sopenharmony_ci if (IS_NODESEG(type)) 19045e5c12b0Sopenharmony_ci SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); 19055e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, curseg->segno); 19065e5c12b0Sopenharmony_ci se->type = type; 19075e5c12b0Sopenharmony_ci se->dirty = 1; 19085e5c12b0Sopenharmony_ci} 19095e5c12b0Sopenharmony_ci 19105e5c12b0Sopenharmony_cistatic void read_compacted_summaries(struct f2fs_sb_info *sbi) 19115e5c12b0Sopenharmony_ci{ 19125e5c12b0Sopenharmony_ci struct curseg_info *curseg; 19135e5c12b0Sopenharmony_ci unsigned int i, j, offset; 19145e5c12b0Sopenharmony_ci block_t start; 19155e5c12b0Sopenharmony_ci char *kaddr; 19165e5c12b0Sopenharmony_ci int ret; 19175e5c12b0Sopenharmony_ci 19185e5c12b0Sopenharmony_ci start = start_sum_block(sbi); 19195e5c12b0Sopenharmony_ci 19205e5c12b0Sopenharmony_ci kaddr = malloc(F2FS_BLKSIZE); 19215e5c12b0Sopenharmony_ci ASSERT(kaddr); 19225e5c12b0Sopenharmony_ci 19235e5c12b0Sopenharmony_ci ret = dev_read_block(kaddr, start++); 19245e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 19255e5c12b0Sopenharmony_ci 19265e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 19275e5c12b0Sopenharmony_ci memcpy(&curseg->sum_blk->journal.n_nats, kaddr, SUM_JOURNAL_SIZE); 19285e5c12b0Sopenharmony_ci 19295e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); 19305e5c12b0Sopenharmony_ci memcpy(&curseg->sum_blk->journal.n_sits, kaddr + SUM_JOURNAL_SIZE, 19315e5c12b0Sopenharmony_ci SUM_JOURNAL_SIZE); 19325e5c12b0Sopenharmony_ci 19335e5c12b0Sopenharmony_ci offset = 2 * SUM_JOURNAL_SIZE; 19345e5c12b0Sopenharmony_ci for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { 19355e5c12b0Sopenharmony_ci unsigned short blk_off; 19365e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, i); 19375e5c12b0Sopenharmony_ci 19385e5c12b0Sopenharmony_ci reset_curseg(sbi, i); 19395e5c12b0Sopenharmony_ci 19405e5c12b0Sopenharmony_ci if (curseg->alloc_type == SSR) 19415e5c12b0Sopenharmony_ci blk_off = sbi->blocks_per_seg; 19425e5c12b0Sopenharmony_ci else 19435e5c12b0Sopenharmony_ci blk_off = curseg->next_blkoff; 19445e5c12b0Sopenharmony_ci 19455e5c12b0Sopenharmony_ci ASSERT(blk_off <= ENTRIES_IN_SUM); 19465e5c12b0Sopenharmony_ci 19475e5c12b0Sopenharmony_ci for (j = 0; j < blk_off; j++) { 19485e5c12b0Sopenharmony_ci struct f2fs_summary *s; 19495e5c12b0Sopenharmony_ci s = (struct f2fs_summary *)(kaddr + offset); 19505e5c12b0Sopenharmony_ci curseg->sum_blk->entries[j] = *s; 19515e5c12b0Sopenharmony_ci offset += SUMMARY_SIZE; 19525e5c12b0Sopenharmony_ci if (offset + SUMMARY_SIZE <= 19535e5c12b0Sopenharmony_ci F2FS_BLKSIZE - SUM_FOOTER_SIZE) 19545e5c12b0Sopenharmony_ci continue; 19555e5c12b0Sopenharmony_ci memset(kaddr, 0, F2FS_BLKSIZE); 19565e5c12b0Sopenharmony_ci ret = dev_read_block(kaddr, start++); 19575e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 19585e5c12b0Sopenharmony_ci offset = 0; 19595e5c12b0Sopenharmony_ci } 19605e5c12b0Sopenharmony_ci } 19615e5c12b0Sopenharmony_ci free(kaddr); 19625e5c12b0Sopenharmony_ci} 19635e5c12b0Sopenharmony_ci 19645e5c12b0Sopenharmony_cistatic void restore_node_summary(struct f2fs_sb_info *sbi, 19655e5c12b0Sopenharmony_ci unsigned int segno, struct f2fs_summary_block *sum_blk) 19665e5c12b0Sopenharmony_ci{ 19675e5c12b0Sopenharmony_ci struct f2fs_node *node_blk; 19685e5c12b0Sopenharmony_ci struct f2fs_summary *sum_entry; 19695e5c12b0Sopenharmony_ci block_t addr; 19705e5c12b0Sopenharmony_ci unsigned int i; 19715e5c12b0Sopenharmony_ci int ret; 19725e5c12b0Sopenharmony_ci 19735e5c12b0Sopenharmony_ci node_blk = malloc(F2FS_BLKSIZE); 19745e5c12b0Sopenharmony_ci ASSERT(node_blk); 19755e5c12b0Sopenharmony_ci 19765e5c12b0Sopenharmony_ci /* scan the node segment */ 19775e5c12b0Sopenharmony_ci addr = START_BLOCK(sbi, segno); 19785e5c12b0Sopenharmony_ci sum_entry = &sum_blk->entries[0]; 19795e5c12b0Sopenharmony_ci 19805e5c12b0Sopenharmony_ci for (i = 0; i < sbi->blocks_per_seg; i++, sum_entry++) { 19815e5c12b0Sopenharmony_ci ret = dev_read_block(node_blk, addr); 19825e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 19835e5c12b0Sopenharmony_ci sum_entry->nid = node_blk->footer.nid; 19845e5c12b0Sopenharmony_ci addr++; 19855e5c12b0Sopenharmony_ci } 19865e5c12b0Sopenharmony_ci free(node_blk); 19875e5c12b0Sopenharmony_ci} 19885e5c12b0Sopenharmony_ci 19895e5c12b0Sopenharmony_cistatic void read_normal_summaries(struct f2fs_sb_info *sbi, int type) 19905e5c12b0Sopenharmony_ci{ 19915e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 19925e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum_blk; 19935e5c12b0Sopenharmony_ci struct curseg_info *curseg; 19945e5c12b0Sopenharmony_ci unsigned int segno = 0; 19955e5c12b0Sopenharmony_ci block_t blk_addr = 0; 19965e5c12b0Sopenharmony_ci int ret; 19975e5c12b0Sopenharmony_ci 19985e5c12b0Sopenharmony_ci if (IS_DATASEG(type)) { 19995e5c12b0Sopenharmony_ci segno = get_cp(cur_data_segno[type]); 20005e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) 20015e5c12b0Sopenharmony_ci blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); 20025e5c12b0Sopenharmony_ci else 20035e5c12b0Sopenharmony_ci blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type); 20045e5c12b0Sopenharmony_ci } else { 20055e5c12b0Sopenharmony_ci segno = get_cp(cur_node_segno[type - CURSEG_HOT_NODE]); 20065e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) 20075e5c12b0Sopenharmony_ci blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, 20085e5c12b0Sopenharmony_ci type - CURSEG_HOT_NODE); 20095e5c12b0Sopenharmony_ci else 20105e5c12b0Sopenharmony_ci blk_addr = GET_SUM_BLKADDR(sbi, segno); 20115e5c12b0Sopenharmony_ci } 20125e5c12b0Sopenharmony_ci 20135e5c12b0Sopenharmony_ci sum_blk = malloc(sizeof(*sum_blk)); 20145e5c12b0Sopenharmony_ci ASSERT(sum_blk); 20155e5c12b0Sopenharmony_ci 20165e5c12b0Sopenharmony_ci ret = dev_read_block(sum_blk, blk_addr); 20175e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 20185e5c12b0Sopenharmony_ci 20195e5c12b0Sopenharmony_ci if (IS_NODESEG(type) && !is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) 20205e5c12b0Sopenharmony_ci restore_node_summary(sbi, segno, sum_blk); 20215e5c12b0Sopenharmony_ci 20225e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, type); 20235e5c12b0Sopenharmony_ci memcpy(curseg->sum_blk, sum_blk, sizeof(*sum_blk)); 20245e5c12b0Sopenharmony_ci reset_curseg(sbi, type); 20255e5c12b0Sopenharmony_ci free(sum_blk); 20265e5c12b0Sopenharmony_ci} 20275e5c12b0Sopenharmony_ci 20285e5c12b0Sopenharmony_civoid update_sum_entry(struct f2fs_sb_info *sbi, block_t blk_addr, 20295e5c12b0Sopenharmony_ci struct f2fs_summary *sum) 20305e5c12b0Sopenharmony_ci{ 20315e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 20325e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum_blk; 20335e5c12b0Sopenharmony_ci u32 segno, offset; 20345e5c12b0Sopenharmony_ci int type, ret; 20355e5c12b0Sopenharmony_ci struct seg_entry *se; 20365e5c12b0Sopenharmony_ci 20375e5c12b0Sopenharmony_ci if (get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) 20385e5c12b0Sopenharmony_ci return; 20395e5c12b0Sopenharmony_ci 20405e5c12b0Sopenharmony_ci segno = GET_SEGNO(sbi, blk_addr); 20415e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, blk_addr); 20425e5c12b0Sopenharmony_ci 20435e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 20445e5c12b0Sopenharmony_ci 20455e5c12b0Sopenharmony_ci sum_blk = get_sum_block(sbi, segno, &type); 20465e5c12b0Sopenharmony_ci memcpy(&sum_blk->entries[offset], sum, sizeof(*sum)); 20475e5c12b0Sopenharmony_ci sum_blk->footer.entry_type = IS_NODESEG(se->type) ? SUM_TYPE_NODE : 20485e5c12b0Sopenharmony_ci SUM_TYPE_DATA; 20495e5c12b0Sopenharmony_ci 20505e5c12b0Sopenharmony_ci /* write SSA all the time */ 20515e5c12b0Sopenharmony_ci ret = dev_write_block(sum_blk, GET_SUM_BLKADDR(sbi, segno)); 20525e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 20535e5c12b0Sopenharmony_ci 20545e5c12b0Sopenharmony_ci if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA || 20555e5c12b0Sopenharmony_ci type == SEG_TYPE_MAX) 20565e5c12b0Sopenharmony_ci free(sum_blk); 20575e5c12b0Sopenharmony_ci} 20585e5c12b0Sopenharmony_ci 20595e5c12b0Sopenharmony_cistatic void restore_curseg_summaries(struct f2fs_sb_info *sbi) 20605e5c12b0Sopenharmony_ci{ 20615e5c12b0Sopenharmony_ci int type = CURSEG_HOT_DATA; 20625e5c12b0Sopenharmony_ci 20635e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) { 20645e5c12b0Sopenharmony_ci read_compacted_summaries(sbi); 20655e5c12b0Sopenharmony_ci type = CURSEG_HOT_NODE; 20665e5c12b0Sopenharmony_ci } 20675e5c12b0Sopenharmony_ci 20685e5c12b0Sopenharmony_ci for (; type <= CURSEG_COLD_NODE; type++) 20695e5c12b0Sopenharmony_ci read_normal_summaries(sbi, type); 20705e5c12b0Sopenharmony_ci} 20715e5c12b0Sopenharmony_ci 20725e5c12b0Sopenharmony_cistatic int build_curseg(struct f2fs_sb_info *sbi) 20735e5c12b0Sopenharmony_ci{ 20745e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 20755e5c12b0Sopenharmony_ci struct curseg_info *array; 20765e5c12b0Sopenharmony_ci unsigned short blk_off; 20775e5c12b0Sopenharmony_ci unsigned int segno; 20785e5c12b0Sopenharmony_ci int i; 20795e5c12b0Sopenharmony_ci 20805e5c12b0Sopenharmony_ci array = malloc(sizeof(*array) * NR_CURSEG_TYPE); 20815e5c12b0Sopenharmony_ci if (!array) { 20825e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc failed for build_curseg!\n"); 20835e5c12b0Sopenharmony_ci return -ENOMEM; 20845e5c12b0Sopenharmony_ci } 20855e5c12b0Sopenharmony_ci 20865e5c12b0Sopenharmony_ci SM_I(sbi)->curseg_array = array; 20875e5c12b0Sopenharmony_ci 20885e5c12b0Sopenharmony_ci for (i = 0; i < NR_CURSEG_TYPE; i++) { 20895e5c12b0Sopenharmony_ci array[i].sum_blk = calloc(sizeof(*(array[i].sum_blk)), 1); 20905e5c12b0Sopenharmony_ci if (!array[i].sum_blk) { 20915e5c12b0Sopenharmony_ci MSG(1, "\tError: Calloc failed for build_curseg!!\n"); 20925e5c12b0Sopenharmony_ci goto seg_cleanup; 20935e5c12b0Sopenharmony_ci } 20945e5c12b0Sopenharmony_ci 20955e5c12b0Sopenharmony_ci if (i <= CURSEG_COLD_DATA) { 20965e5c12b0Sopenharmony_ci blk_off = get_cp(cur_data_blkoff[i]); 20975e5c12b0Sopenharmony_ci segno = get_cp(cur_data_segno[i]); 20985e5c12b0Sopenharmony_ci } 20995e5c12b0Sopenharmony_ci if (i > CURSEG_COLD_DATA) { 21005e5c12b0Sopenharmony_ci blk_off = get_cp(cur_node_blkoff[i - CURSEG_HOT_NODE]); 21015e5c12b0Sopenharmony_ci segno = get_cp(cur_node_segno[i - CURSEG_HOT_NODE]); 21025e5c12b0Sopenharmony_ci } 21035e5c12b0Sopenharmony_ci ASSERT(segno < MAIN_SEGS(sbi)); 21045e5c12b0Sopenharmony_ci ASSERT(blk_off < DEFAULT_BLOCKS_PER_SEGMENT); 21055e5c12b0Sopenharmony_ci 21065e5c12b0Sopenharmony_ci array[i].segno = segno; 21075e5c12b0Sopenharmony_ci array[i].zone = GET_ZONENO_FROM_SEGNO(sbi, segno); 21085e5c12b0Sopenharmony_ci array[i].next_segno = NULL_SEGNO; 21095e5c12b0Sopenharmony_ci array[i].next_blkoff = blk_off; 21105e5c12b0Sopenharmony_ci array[i].alloc_type = cp->alloc_type[i]; 21115e5c12b0Sopenharmony_ci } 21125e5c12b0Sopenharmony_ci restore_curseg_summaries(sbi); 21135e5c12b0Sopenharmony_ci return 0; 21145e5c12b0Sopenharmony_ci 21155e5c12b0Sopenharmony_ciseg_cleanup: 21165e5c12b0Sopenharmony_ci for(--i ; i >=0; --i) 21175e5c12b0Sopenharmony_ci free(array[i].sum_blk); 21185e5c12b0Sopenharmony_ci free(array); 21195e5c12b0Sopenharmony_ci 21205e5c12b0Sopenharmony_ci return -ENOMEM; 21215e5c12b0Sopenharmony_ci} 21225e5c12b0Sopenharmony_ci 21235e5c12b0Sopenharmony_cistatic inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) 21245e5c12b0Sopenharmony_ci{ 21255e5c12b0Sopenharmony_ci unsigned int end_segno = SM_I(sbi)->segment_count - 1; 21265e5c12b0Sopenharmony_ci ASSERT(segno <= end_segno); 21275e5c12b0Sopenharmony_ci} 21285e5c12b0Sopenharmony_ci 21295e5c12b0Sopenharmony_cistatic inline block_t current_sit_addr(struct f2fs_sb_info *sbi, 21305e5c12b0Sopenharmony_ci unsigned int segno) 21315e5c12b0Sopenharmony_ci{ 21325e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 21335e5c12b0Sopenharmony_ci unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); 21345e5c12b0Sopenharmony_ci block_t blk_addr = sit_i->sit_base_addr + offset; 21355e5c12b0Sopenharmony_ci 21365e5c12b0Sopenharmony_ci check_seg_range(sbi, segno); 21375e5c12b0Sopenharmony_ci 21385e5c12b0Sopenharmony_ci /* calculate sit block address */ 21395e5c12b0Sopenharmony_ci if (f2fs_test_bit(offset, sit_i->sit_bitmap)) 21405e5c12b0Sopenharmony_ci blk_addr += sit_i->sit_blocks; 21415e5c12b0Sopenharmony_ci 21425e5c12b0Sopenharmony_ci return blk_addr; 21435e5c12b0Sopenharmony_ci} 21445e5c12b0Sopenharmony_ci 21455e5c12b0Sopenharmony_civoid get_current_sit_page(struct f2fs_sb_info *sbi, 21465e5c12b0Sopenharmony_ci unsigned int segno, struct f2fs_sit_block *sit_blk) 21475e5c12b0Sopenharmony_ci{ 21485e5c12b0Sopenharmony_ci block_t blk_addr = current_sit_addr(sbi, segno); 21495e5c12b0Sopenharmony_ci 21505e5c12b0Sopenharmony_ci ASSERT(dev_read_block(sit_blk, blk_addr) >= 0); 21515e5c12b0Sopenharmony_ci} 21525e5c12b0Sopenharmony_ci 21535e5c12b0Sopenharmony_civoid rewrite_current_sit_page(struct f2fs_sb_info *sbi, 21545e5c12b0Sopenharmony_ci unsigned int segno, struct f2fs_sit_block *sit_blk) 21555e5c12b0Sopenharmony_ci{ 21565e5c12b0Sopenharmony_ci block_t blk_addr = current_sit_addr(sbi, segno); 21575e5c12b0Sopenharmony_ci 21585e5c12b0Sopenharmony_ci ASSERT(dev_write_block(sit_blk, blk_addr) >= 0); 21595e5c12b0Sopenharmony_ci} 21605e5c12b0Sopenharmony_ci 21615e5c12b0Sopenharmony_civoid check_block_count(struct f2fs_sb_info *sbi, 21625e5c12b0Sopenharmony_ci unsigned int segno, struct f2fs_sit_entry *raw_sit) 21635e5c12b0Sopenharmony_ci{ 21645e5c12b0Sopenharmony_ci struct f2fs_sm_info *sm_info = SM_I(sbi); 21655e5c12b0Sopenharmony_ci unsigned int end_segno = sm_info->segment_count - 1; 21665e5c12b0Sopenharmony_ci int valid_blocks = 0; 21675e5c12b0Sopenharmony_ci unsigned int i; 21685e5c12b0Sopenharmony_ci 21695e5c12b0Sopenharmony_ci /* check segment usage */ 21705e5c12b0Sopenharmony_ci if (GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg) 21715e5c12b0Sopenharmony_ci ASSERT_MSG("Invalid SIT vblocks: segno=0x%x, %u", 21725e5c12b0Sopenharmony_ci segno, GET_SIT_VBLOCKS(raw_sit)); 21735e5c12b0Sopenharmony_ci 21745e5c12b0Sopenharmony_ci /* check boundary of a given segment number */ 21755e5c12b0Sopenharmony_ci if (segno > end_segno) 21765e5c12b0Sopenharmony_ci ASSERT_MSG("Invalid SEGNO: 0x%x", segno); 21775e5c12b0Sopenharmony_ci 21785e5c12b0Sopenharmony_ci /* check bitmap with valid block count */ 21795e5c12b0Sopenharmony_ci for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++) 21805e5c12b0Sopenharmony_ci valid_blocks += get_bits_in_byte(raw_sit->valid_map[i]); 21815e5c12b0Sopenharmony_ci 21825e5c12b0Sopenharmony_ci if (GET_SIT_VBLOCKS(raw_sit) != valid_blocks) 21835e5c12b0Sopenharmony_ci ASSERT_MSG("Wrong SIT valid blocks: segno=0x%x, %u vs. %u", 21845e5c12b0Sopenharmony_ci segno, GET_SIT_VBLOCKS(raw_sit), valid_blocks); 21855e5c12b0Sopenharmony_ci 21865e5c12b0Sopenharmony_ci if (GET_SIT_TYPE(raw_sit) >= NO_CHECK_TYPE) 21875e5c12b0Sopenharmony_ci ASSERT_MSG("Wrong SIT type: segno=0x%x, %u", 21885e5c12b0Sopenharmony_ci segno, GET_SIT_TYPE(raw_sit)); 21895e5c12b0Sopenharmony_ci} 21905e5c12b0Sopenharmony_ci 21915e5c12b0Sopenharmony_civoid __seg_info_from_raw_sit(struct seg_entry *se, 21925e5c12b0Sopenharmony_ci struct f2fs_sit_entry *raw_sit) 21935e5c12b0Sopenharmony_ci{ 21945e5c12b0Sopenharmony_ci se->valid_blocks = GET_SIT_VBLOCKS(raw_sit); 21955e5c12b0Sopenharmony_ci memcpy(se->cur_valid_map, raw_sit->valid_map, SIT_VBLOCK_MAP_SIZE); 21965e5c12b0Sopenharmony_ci se->type = GET_SIT_TYPE(raw_sit); 21975e5c12b0Sopenharmony_ci se->orig_type = GET_SIT_TYPE(raw_sit); 21985e5c12b0Sopenharmony_ci se->mtime = le64_to_cpu(raw_sit->mtime); 21995e5c12b0Sopenharmony_ci} 22005e5c12b0Sopenharmony_ci 22015e5c12b0Sopenharmony_civoid seg_info_from_raw_sit(struct f2fs_sb_info *sbi, struct seg_entry *se, 22025e5c12b0Sopenharmony_ci struct f2fs_sit_entry *raw_sit) 22035e5c12b0Sopenharmony_ci{ 22045e5c12b0Sopenharmony_ci __seg_info_from_raw_sit(se, raw_sit); 22055e5c12b0Sopenharmony_ci 22065e5c12b0Sopenharmony_ci if (!need_fsync_data_record(sbi)) 22075e5c12b0Sopenharmony_ci return; 22085e5c12b0Sopenharmony_ci se->ckpt_valid_blocks = se->valid_blocks; 22095e5c12b0Sopenharmony_ci memcpy(se->ckpt_valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); 22105e5c12b0Sopenharmony_ci se->ckpt_type = se->type; 22115e5c12b0Sopenharmony_ci} 22125e5c12b0Sopenharmony_ci 22135e5c12b0Sopenharmony_cistruct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, 22145e5c12b0Sopenharmony_ci unsigned int segno) 22155e5c12b0Sopenharmony_ci{ 22165e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 22175e5c12b0Sopenharmony_ci return &sit_i->sentries[segno]; 22185e5c12b0Sopenharmony_ci} 22195e5c12b0Sopenharmony_ci 22205e5c12b0Sopenharmony_ciunsigned short get_seg_vblocks(struct f2fs_sb_info *sbi, struct seg_entry *se) 22215e5c12b0Sopenharmony_ci{ 22225e5c12b0Sopenharmony_ci if (!need_fsync_data_record(sbi)) 22235e5c12b0Sopenharmony_ci return se->valid_blocks; 22245e5c12b0Sopenharmony_ci else 22255e5c12b0Sopenharmony_ci return se->ckpt_valid_blocks; 22265e5c12b0Sopenharmony_ci} 22275e5c12b0Sopenharmony_ci 22285e5c12b0Sopenharmony_ciunsigned char *get_seg_bitmap(struct f2fs_sb_info *sbi, struct seg_entry *se) 22295e5c12b0Sopenharmony_ci{ 22305e5c12b0Sopenharmony_ci if (!need_fsync_data_record(sbi)) 22315e5c12b0Sopenharmony_ci return se->cur_valid_map; 22325e5c12b0Sopenharmony_ci else 22335e5c12b0Sopenharmony_ci return se->ckpt_valid_map; 22345e5c12b0Sopenharmony_ci} 22355e5c12b0Sopenharmony_ci 22365e5c12b0Sopenharmony_ciunsigned char get_seg_type(struct f2fs_sb_info *sbi, struct seg_entry *se) 22375e5c12b0Sopenharmony_ci{ 22385e5c12b0Sopenharmony_ci if (!need_fsync_data_record(sbi)) 22395e5c12b0Sopenharmony_ci return se->type; 22405e5c12b0Sopenharmony_ci else 22415e5c12b0Sopenharmony_ci return se->ckpt_type; 22425e5c12b0Sopenharmony_ci} 22435e5c12b0Sopenharmony_ci 22445e5c12b0Sopenharmony_cistruct f2fs_summary_block *get_sum_block(struct f2fs_sb_info *sbi, 22455e5c12b0Sopenharmony_ci unsigned int segno, int *ret_type) 22465e5c12b0Sopenharmony_ci{ 22475e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 22485e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum_blk; 22495e5c12b0Sopenharmony_ci struct curseg_info *curseg; 22505e5c12b0Sopenharmony_ci int type, ret; 22515e5c12b0Sopenharmony_ci u64 ssa_blk; 22525e5c12b0Sopenharmony_ci 22535e5c12b0Sopenharmony_ci *ret_type= SEG_TYPE_MAX; 22545e5c12b0Sopenharmony_ci 22555e5c12b0Sopenharmony_ci ssa_blk = GET_SUM_BLKADDR(sbi, segno); 22565e5c12b0Sopenharmony_ci for (type = 0; type < NR_CURSEG_NODE_TYPE; type++) { 22575e5c12b0Sopenharmony_ci if (segno == get_cp(cur_node_segno[type])) { 22585e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, CURSEG_HOT_NODE + type); 22595e5c12b0Sopenharmony_ci if (!IS_SUM_NODE_SEG(curseg->sum_blk->footer)) { 22605e5c12b0Sopenharmony_ci ASSERT_MSG("segno [0x%x] indicates a data " 22615e5c12b0Sopenharmony_ci "segment, but should be node", 22625e5c12b0Sopenharmony_ci segno); 22635e5c12b0Sopenharmony_ci *ret_type = -SEG_TYPE_CUR_NODE; 22645e5c12b0Sopenharmony_ci } else { 22655e5c12b0Sopenharmony_ci *ret_type = SEG_TYPE_CUR_NODE; 22665e5c12b0Sopenharmony_ci } 22675e5c12b0Sopenharmony_ci return curseg->sum_blk; 22685e5c12b0Sopenharmony_ci } 22695e5c12b0Sopenharmony_ci } 22705e5c12b0Sopenharmony_ci 22715e5c12b0Sopenharmony_ci for (type = 0; type < NR_CURSEG_DATA_TYPE; type++) { 22725e5c12b0Sopenharmony_ci if (segno == get_cp(cur_data_segno[type])) { 22735e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, type); 22745e5c12b0Sopenharmony_ci if (IS_SUM_NODE_SEG(curseg->sum_blk->footer)) { 22755e5c12b0Sopenharmony_ci ASSERT_MSG("segno [0x%x] indicates a node " 22765e5c12b0Sopenharmony_ci "segment, but should be data", 22775e5c12b0Sopenharmony_ci segno); 22785e5c12b0Sopenharmony_ci *ret_type = -SEG_TYPE_CUR_DATA; 22795e5c12b0Sopenharmony_ci } else { 22805e5c12b0Sopenharmony_ci *ret_type = SEG_TYPE_CUR_DATA; 22815e5c12b0Sopenharmony_ci } 22825e5c12b0Sopenharmony_ci return curseg->sum_blk; 22835e5c12b0Sopenharmony_ci } 22845e5c12b0Sopenharmony_ci } 22855e5c12b0Sopenharmony_ci 22865e5c12b0Sopenharmony_ci sum_blk = calloc(BLOCK_SZ, 1); 22875e5c12b0Sopenharmony_ci ASSERT(sum_blk); 22885e5c12b0Sopenharmony_ci 22895e5c12b0Sopenharmony_ci ret = dev_read_block(sum_blk, ssa_blk); 22905e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 22915e5c12b0Sopenharmony_ci 22925e5c12b0Sopenharmony_ci if (IS_SUM_NODE_SEG(sum_blk->footer)) 22935e5c12b0Sopenharmony_ci *ret_type = SEG_TYPE_NODE; 22945e5c12b0Sopenharmony_ci else if (IS_SUM_DATA_SEG(sum_blk->footer)) 22955e5c12b0Sopenharmony_ci *ret_type = SEG_TYPE_DATA; 22965e5c12b0Sopenharmony_ci 22975e5c12b0Sopenharmony_ci return sum_blk; 22985e5c12b0Sopenharmony_ci} 22995e5c12b0Sopenharmony_ci 23005e5c12b0Sopenharmony_ciint get_sum_entry(struct f2fs_sb_info *sbi, u32 blk_addr, 23015e5c12b0Sopenharmony_ci struct f2fs_summary *sum_entry) 23025e5c12b0Sopenharmony_ci{ 23035e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum_blk; 23045e5c12b0Sopenharmony_ci u32 segno, offset; 23055e5c12b0Sopenharmony_ci int type; 23065e5c12b0Sopenharmony_ci 23075e5c12b0Sopenharmony_ci segno = GET_SEGNO(sbi, blk_addr); 23085e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, blk_addr); 23095e5c12b0Sopenharmony_ci 23105e5c12b0Sopenharmony_ci sum_blk = get_sum_block(sbi, segno, &type); 23115e5c12b0Sopenharmony_ci memcpy(sum_entry, &(sum_blk->entries[offset]), 23125e5c12b0Sopenharmony_ci sizeof(struct f2fs_summary)); 23135e5c12b0Sopenharmony_ci if (type == SEG_TYPE_NODE || type == SEG_TYPE_DATA || 23145e5c12b0Sopenharmony_ci type == SEG_TYPE_MAX) 23155e5c12b0Sopenharmony_ci free(sum_blk); 23165e5c12b0Sopenharmony_ci return type; 23175e5c12b0Sopenharmony_ci} 23185e5c12b0Sopenharmony_ci 23195e5c12b0Sopenharmony_cistatic void get_nat_entry(struct f2fs_sb_info *sbi, nid_t nid, 23205e5c12b0Sopenharmony_ci struct f2fs_nat_entry *raw_nat) 23215e5c12b0Sopenharmony_ci{ 23225e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 23235e5c12b0Sopenharmony_ci pgoff_t block_addr; 23245e5c12b0Sopenharmony_ci int entry_off; 23255e5c12b0Sopenharmony_ci int ret; 23265e5c12b0Sopenharmony_ci 23275e5c12b0Sopenharmony_ci if (lookup_nat_in_journal(sbi, nid, raw_nat) >= 0) 23285e5c12b0Sopenharmony_ci return; 23295e5c12b0Sopenharmony_ci 23305e5c12b0Sopenharmony_ci nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 23315e5c12b0Sopenharmony_ci ASSERT(nat_block); 23325e5c12b0Sopenharmony_ci 23335e5c12b0Sopenharmony_ci entry_off = nid % NAT_ENTRY_PER_BLOCK; 23345e5c12b0Sopenharmony_ci block_addr = current_nat_addr(sbi, nid, NULL); 23355e5c12b0Sopenharmony_ci 23365e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, block_addr); 23375e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 23385e5c12b0Sopenharmony_ci 23395e5c12b0Sopenharmony_ci memcpy(raw_nat, &nat_block->entries[entry_off], 23405e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 23415e5c12b0Sopenharmony_ci free(nat_block); 23425e5c12b0Sopenharmony_ci} 23435e5c12b0Sopenharmony_ci 23445e5c12b0Sopenharmony_civoid update_data_blkaddr(struct f2fs_sb_info *sbi, nid_t nid, 23455e5c12b0Sopenharmony_ci u16 ofs_in_node, block_t newaddr) 23465e5c12b0Sopenharmony_ci{ 23475e5c12b0Sopenharmony_ci struct f2fs_node *node_blk = NULL; 23485e5c12b0Sopenharmony_ci struct node_info ni; 23495e5c12b0Sopenharmony_ci block_t oldaddr, startaddr, endaddr; 23505e5c12b0Sopenharmony_ci int ret; 23515e5c12b0Sopenharmony_ci 23525e5c12b0Sopenharmony_ci node_blk = (struct f2fs_node *)calloc(BLOCK_SZ, 1); 23535e5c12b0Sopenharmony_ci ASSERT(node_blk); 23545e5c12b0Sopenharmony_ci 23555e5c12b0Sopenharmony_ci get_node_info(sbi, nid, &ni); 23565e5c12b0Sopenharmony_ci 23575e5c12b0Sopenharmony_ci /* read node_block */ 23585e5c12b0Sopenharmony_ci ret = dev_read_block(node_blk, ni.blk_addr); 23595e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 23605e5c12b0Sopenharmony_ci 23615e5c12b0Sopenharmony_ci /* check its block address */ 23625e5c12b0Sopenharmony_ci if (node_blk->footer.nid == node_blk->footer.ino) { 23635e5c12b0Sopenharmony_ci int ofs = get_extra_isize(node_blk); 23645e5c12b0Sopenharmony_ci 23655e5c12b0Sopenharmony_ci oldaddr = le32_to_cpu(node_blk->i.i_addr[ofs + ofs_in_node]); 23665e5c12b0Sopenharmony_ci node_blk->i.i_addr[ofs + ofs_in_node] = cpu_to_le32(newaddr); 23675e5c12b0Sopenharmony_ci ret = write_inode(node_blk, ni.blk_addr); 23685e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 23695e5c12b0Sopenharmony_ci } else { 23705e5c12b0Sopenharmony_ci oldaddr = le32_to_cpu(node_blk->dn.addr[ofs_in_node]); 23715e5c12b0Sopenharmony_ci node_blk->dn.addr[ofs_in_node] = cpu_to_le32(newaddr); 23725e5c12b0Sopenharmony_ci ret = dev_write_block(node_blk, ni.blk_addr); 23735e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 23745e5c12b0Sopenharmony_ci } 23755e5c12b0Sopenharmony_ci 23765e5c12b0Sopenharmony_ci /* check extent cache entry */ 23775e5c12b0Sopenharmony_ci if (node_blk->footer.nid != node_blk->footer.ino) { 23785e5c12b0Sopenharmony_ci get_node_info(sbi, le32_to_cpu(node_blk->footer.ino), &ni); 23795e5c12b0Sopenharmony_ci 23805e5c12b0Sopenharmony_ci /* read inode block */ 23815e5c12b0Sopenharmony_ci ret = dev_read_block(node_blk, ni.blk_addr); 23825e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 23835e5c12b0Sopenharmony_ci } 23845e5c12b0Sopenharmony_ci 23855e5c12b0Sopenharmony_ci startaddr = le32_to_cpu(node_blk->i.i_ext.blk_addr); 23865e5c12b0Sopenharmony_ci endaddr = startaddr + le32_to_cpu(node_blk->i.i_ext.len); 23875e5c12b0Sopenharmony_ci if (oldaddr >= startaddr && oldaddr < endaddr) { 23885e5c12b0Sopenharmony_ci node_blk->i.i_ext.len = 0; 23895e5c12b0Sopenharmony_ci 23905e5c12b0Sopenharmony_ci /* update inode block */ 23915e5c12b0Sopenharmony_ci ASSERT(write_inode(node_blk, ni.blk_addr) >= 0); 23925e5c12b0Sopenharmony_ci } 23935e5c12b0Sopenharmony_ci free(node_blk); 23945e5c12b0Sopenharmony_ci} 23955e5c12b0Sopenharmony_ci 23965e5c12b0Sopenharmony_civoid update_nat_blkaddr(struct f2fs_sb_info *sbi, nid_t ino, 23975e5c12b0Sopenharmony_ci nid_t nid, block_t newaddr) 23985e5c12b0Sopenharmony_ci{ 23995e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 24005e5c12b0Sopenharmony_ci pgoff_t block_addr; 24015e5c12b0Sopenharmony_ci int entry_off; 24025e5c12b0Sopenharmony_ci int ret; 24035e5c12b0Sopenharmony_ci 24045e5c12b0Sopenharmony_ci nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 24055e5c12b0Sopenharmony_ci ASSERT(nat_block); 24065e5c12b0Sopenharmony_ci 24075e5c12b0Sopenharmony_ci entry_off = nid % NAT_ENTRY_PER_BLOCK; 24085e5c12b0Sopenharmony_ci block_addr = current_nat_addr(sbi, nid, NULL); 24095e5c12b0Sopenharmony_ci 24105e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, block_addr); 24115e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 24125e5c12b0Sopenharmony_ci 24135e5c12b0Sopenharmony_ci if (ino) 24145e5c12b0Sopenharmony_ci nat_block->entries[entry_off].ino = cpu_to_le32(ino); 24155e5c12b0Sopenharmony_ci nat_block->entries[entry_off].block_addr = cpu_to_le32(newaddr); 24165e5c12b0Sopenharmony_ci if (c.func == FSCK) 24175e5c12b0Sopenharmony_ci F2FS_FSCK(sbi)->entries[nid] = nat_block->entries[entry_off]; 24185e5c12b0Sopenharmony_ci 24195e5c12b0Sopenharmony_ci ret = dev_write_block(nat_block, block_addr); 24205e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 24215e5c12b0Sopenharmony_ci free(nat_block); 24225e5c12b0Sopenharmony_ci} 24235e5c12b0Sopenharmony_ci 24245e5c12b0Sopenharmony_civoid get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) 24255e5c12b0Sopenharmony_ci{ 24265e5c12b0Sopenharmony_ci struct f2fs_nat_entry raw_nat; 24275e5c12b0Sopenharmony_ci 24285e5c12b0Sopenharmony_ci ni->nid = nid; 24295e5c12b0Sopenharmony_ci if (c.func == FSCK && F2FS_FSCK(sbi)->nr_nat_entries) { 24305e5c12b0Sopenharmony_ci node_info_from_raw_nat(ni, &(F2FS_FSCK(sbi)->entries[nid])); 24315e5c12b0Sopenharmony_ci if (ni->blk_addr) 24325e5c12b0Sopenharmony_ci return; 24335e5c12b0Sopenharmony_ci /* nat entry is not cached, read it */ 24345e5c12b0Sopenharmony_ci } 24355e5c12b0Sopenharmony_ci 24365e5c12b0Sopenharmony_ci get_nat_entry(sbi, nid, &raw_nat); 24375e5c12b0Sopenharmony_ci node_info_from_raw_nat(ni, &raw_nat); 24385e5c12b0Sopenharmony_ci} 24395e5c12b0Sopenharmony_ci 24405e5c12b0Sopenharmony_cistatic int build_sit_entries(struct f2fs_sb_info *sbi) 24415e5c12b0Sopenharmony_ci{ 24425e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 24435e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); 24445e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 24455e5c12b0Sopenharmony_ci struct f2fs_sit_block *sit_blk; 24465e5c12b0Sopenharmony_ci struct seg_entry *se; 24475e5c12b0Sopenharmony_ci struct f2fs_sit_entry sit; 24485e5c12b0Sopenharmony_ci int sit_blk_cnt = SIT_BLK_CNT(sbi); 24495e5c12b0Sopenharmony_ci unsigned int i, segno, end; 24505e5c12b0Sopenharmony_ci unsigned int readed, start_blk = 0; 24515e5c12b0Sopenharmony_ci 24525e5c12b0Sopenharmony_ci sit_blk = calloc(BLOCK_SZ, 1); 24535e5c12b0Sopenharmony_ci if (!sit_blk) { 24545e5c12b0Sopenharmony_ci MSG(1, "\tError: Calloc failed for build_sit_entries!\n"); 24555e5c12b0Sopenharmony_ci return -ENOMEM; 24565e5c12b0Sopenharmony_ci } 24575e5c12b0Sopenharmony_ci 24585e5c12b0Sopenharmony_ci do { 24595e5c12b0Sopenharmony_ci readed = f2fs_ra_meta_pages(sbi, start_blk, MAX_RA_BLOCKS, 24605e5c12b0Sopenharmony_ci META_SIT); 24615e5c12b0Sopenharmony_ci 24625e5c12b0Sopenharmony_ci segno = start_blk * sit_i->sents_per_block; 24635e5c12b0Sopenharmony_ci end = (start_blk + readed) * sit_i->sents_per_block; 24645e5c12b0Sopenharmony_ci 24655e5c12b0Sopenharmony_ci for (; segno < end && segno < MAIN_SEGS(sbi); segno++) { 24665e5c12b0Sopenharmony_ci se = &sit_i->sentries[segno]; 24675e5c12b0Sopenharmony_ci 24685e5c12b0Sopenharmony_ci get_current_sit_page(sbi, segno, sit_blk); 24695e5c12b0Sopenharmony_ci sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; 24705e5c12b0Sopenharmony_ci 24715e5c12b0Sopenharmony_ci check_block_count(sbi, segno, &sit); 24725e5c12b0Sopenharmony_ci seg_info_from_raw_sit(sbi, se, &sit); 24735e5c12b0Sopenharmony_ci } 24745e5c12b0Sopenharmony_ci start_blk += readed; 24755e5c12b0Sopenharmony_ci } while (start_blk < sit_blk_cnt); 24765e5c12b0Sopenharmony_ci 24775e5c12b0Sopenharmony_ci 24785e5c12b0Sopenharmony_ci free(sit_blk); 24795e5c12b0Sopenharmony_ci 24805e5c12b0Sopenharmony_ci if (sits_in_cursum(journal) > SIT_JOURNAL_ENTRIES) { 24815e5c12b0Sopenharmony_ci MSG(0, "\tError: build_sit_entries truncate n_sits(%u) to " 24825e5c12b0Sopenharmony_ci "SIT_JOURNAL_ENTRIES(%zu)\n", 24835e5c12b0Sopenharmony_ci sits_in_cursum(journal), SIT_JOURNAL_ENTRIES); 24845e5c12b0Sopenharmony_ci journal->n_sits = cpu_to_le16(SIT_JOURNAL_ENTRIES); 24855e5c12b0Sopenharmony_ci c.fix_on = 1; 24865e5c12b0Sopenharmony_ci } 24875e5c12b0Sopenharmony_ci 24885e5c12b0Sopenharmony_ci for (i = 0; i < sits_in_cursum(journal); i++) { 24895e5c12b0Sopenharmony_ci segno = le32_to_cpu(segno_in_journal(journal, i)); 24905e5c12b0Sopenharmony_ci 24915e5c12b0Sopenharmony_ci if (segno >= MAIN_SEGS(sbi)) { 24925e5c12b0Sopenharmony_ci MSG(0, "\tError: build_sit_entries: segno(%u) is invalid!!!\n", segno); 24935e5c12b0Sopenharmony_ci journal->n_sits = cpu_to_le16(i); 24945e5c12b0Sopenharmony_ci c.fix_on = 1; 24955e5c12b0Sopenharmony_ci continue; 24965e5c12b0Sopenharmony_ci } 24975e5c12b0Sopenharmony_ci 24985e5c12b0Sopenharmony_ci se = &sit_i->sentries[segno]; 24995e5c12b0Sopenharmony_ci sit = sit_in_journal(journal, i); 25005e5c12b0Sopenharmony_ci 25015e5c12b0Sopenharmony_ci check_block_count(sbi, segno, &sit); 25025e5c12b0Sopenharmony_ci seg_info_from_raw_sit(sbi, se, &sit); 25035e5c12b0Sopenharmony_ci } 25045e5c12b0Sopenharmony_ci return 0; 25055e5c12b0Sopenharmony_ci} 25065e5c12b0Sopenharmony_ci 25075e5c12b0Sopenharmony_cistatic int early_build_segment_manager(struct f2fs_sb_info *sbi) 25085e5c12b0Sopenharmony_ci{ 25095e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 25105e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 25115e5c12b0Sopenharmony_ci struct f2fs_sm_info *sm_info; 25125e5c12b0Sopenharmony_ci 25135e5c12b0Sopenharmony_ci sm_info = malloc(sizeof(struct f2fs_sm_info)); 25145e5c12b0Sopenharmony_ci if (!sm_info) { 25155e5c12b0Sopenharmony_ci MSG(1, "\tError: Malloc failed for build_segment_manager!\n"); 25165e5c12b0Sopenharmony_ci return -ENOMEM; 25175e5c12b0Sopenharmony_ci } 25185e5c12b0Sopenharmony_ci 25195e5c12b0Sopenharmony_ci /* init sm info */ 25205e5c12b0Sopenharmony_ci sbi->sm_info = sm_info; 25215e5c12b0Sopenharmony_ci sm_info->seg0_blkaddr = get_sb(segment0_blkaddr); 25225e5c12b0Sopenharmony_ci sm_info->main_blkaddr = get_sb(main_blkaddr); 25235e5c12b0Sopenharmony_ci sm_info->segment_count = get_sb(segment_count); 25245e5c12b0Sopenharmony_ci sm_info->reserved_segments = get_cp(rsvd_segment_count); 25255e5c12b0Sopenharmony_ci sm_info->ovp_segments = get_cp(overprov_segment_count); 25265e5c12b0Sopenharmony_ci sm_info->main_segments = get_sb(segment_count_main); 25275e5c12b0Sopenharmony_ci sm_info->ssa_blkaddr = get_sb(ssa_blkaddr); 25285e5c12b0Sopenharmony_ci 25295e5c12b0Sopenharmony_ci if (build_sit_info(sbi) || build_curseg(sbi)) { 25305e5c12b0Sopenharmony_ci free(sm_info); 25315e5c12b0Sopenharmony_ci return -ENOMEM; 25325e5c12b0Sopenharmony_ci } 25335e5c12b0Sopenharmony_ci 25345e5c12b0Sopenharmony_ci return 0; 25355e5c12b0Sopenharmony_ci} 25365e5c12b0Sopenharmony_ci 25375e5c12b0Sopenharmony_cistatic int late_build_segment_manager(struct f2fs_sb_info *sbi) 25385e5c12b0Sopenharmony_ci{ 25395e5c12b0Sopenharmony_ci if (sbi->seg_manager_done) 25405e5c12b0Sopenharmony_ci return 1; /* this function was already called */ 25415e5c12b0Sopenharmony_ci 25425e5c12b0Sopenharmony_ci sbi->seg_manager_done = true; 25435e5c12b0Sopenharmony_ci if (build_sit_entries(sbi)) { 25445e5c12b0Sopenharmony_ci free (sbi->sm_info); 25455e5c12b0Sopenharmony_ci return -ENOMEM; 25465e5c12b0Sopenharmony_ci } 25475e5c12b0Sopenharmony_ci 25485e5c12b0Sopenharmony_ci return 0; 25495e5c12b0Sopenharmony_ci} 25505e5c12b0Sopenharmony_ci 25515e5c12b0Sopenharmony_civoid build_sit_area_bitmap(struct f2fs_sb_info *sbi) 25525e5c12b0Sopenharmony_ci{ 25535e5c12b0Sopenharmony_ci struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 25545e5c12b0Sopenharmony_ci struct f2fs_sm_info *sm_i = SM_I(sbi); 25555e5c12b0Sopenharmony_ci unsigned int segno = 0; 25565e5c12b0Sopenharmony_ci char *ptr = NULL; 25575e5c12b0Sopenharmony_ci u32 sum_vblocks = 0; 25585e5c12b0Sopenharmony_ci u32 free_segs = 0; 25595e5c12b0Sopenharmony_ci struct seg_entry *se; 25605e5c12b0Sopenharmony_ci 25615e5c12b0Sopenharmony_ci fsck->sit_area_bitmap_sz = sm_i->main_segments * SIT_VBLOCK_MAP_SIZE; 25625e5c12b0Sopenharmony_ci fsck->sit_area_bitmap = calloc(1, fsck->sit_area_bitmap_sz); 25635e5c12b0Sopenharmony_ci ASSERT(fsck->sit_area_bitmap); 25645e5c12b0Sopenharmony_ci ptr = fsck->sit_area_bitmap; 25655e5c12b0Sopenharmony_ci 25665e5c12b0Sopenharmony_ci ASSERT(fsck->sit_area_bitmap_sz == fsck->main_area_bitmap_sz); 25675e5c12b0Sopenharmony_ci 25685e5c12b0Sopenharmony_ci for (segno = 0; segno < MAIN_SEGS(sbi); segno++) { 25695e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 25705e5c12b0Sopenharmony_ci 25715e5c12b0Sopenharmony_ci memcpy(ptr, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); 25725e5c12b0Sopenharmony_ci ptr += SIT_VBLOCK_MAP_SIZE; 25735e5c12b0Sopenharmony_ci 25745e5c12b0Sopenharmony_ci if (se->valid_blocks == 0x0 && is_usable_seg(sbi, segno)) { 25755e5c12b0Sopenharmony_ci if (le32_to_cpu(sbi->ckpt->cur_node_segno[0]) == segno || 25765e5c12b0Sopenharmony_ci le32_to_cpu(sbi->ckpt->cur_data_segno[0]) == segno || 25775e5c12b0Sopenharmony_ci le32_to_cpu(sbi->ckpt->cur_node_segno[1]) == segno || 25785e5c12b0Sopenharmony_ci le32_to_cpu(sbi->ckpt->cur_data_segno[1]) == segno || 25795e5c12b0Sopenharmony_ci le32_to_cpu(sbi->ckpt->cur_node_segno[2]) == segno || 25805e5c12b0Sopenharmony_ci le32_to_cpu(sbi->ckpt->cur_data_segno[2]) == segno) { 25815e5c12b0Sopenharmony_ci continue; 25825e5c12b0Sopenharmony_ci } else { 25835e5c12b0Sopenharmony_ci free_segs++; 25845e5c12b0Sopenharmony_ci } 25855e5c12b0Sopenharmony_ci } else { 25865e5c12b0Sopenharmony_ci sum_vblocks += se->valid_blocks; 25875e5c12b0Sopenharmony_ci } 25885e5c12b0Sopenharmony_ci } 25895e5c12b0Sopenharmony_ci fsck->chk.sit_valid_blocks = sum_vblocks; 25905e5c12b0Sopenharmony_ci fsck->chk.sit_free_segs = free_segs; 25915e5c12b0Sopenharmony_ci 25925e5c12b0Sopenharmony_ci DBG(1, "Blocks [0x%x : %d] Free Segs [0x%x : %d]\n\n", 25935e5c12b0Sopenharmony_ci sum_vblocks, sum_vblocks, 25945e5c12b0Sopenharmony_ci free_segs, free_segs); 25955e5c12b0Sopenharmony_ci} 25965e5c12b0Sopenharmony_ci 25975e5c12b0Sopenharmony_civoid rewrite_sit_area_bitmap(struct f2fs_sb_info *sbi) 25985e5c12b0Sopenharmony_ci{ 25995e5c12b0Sopenharmony_ci struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 26005e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); 26015e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 26025e5c12b0Sopenharmony_ci struct f2fs_sit_block *sit_blk; 26035e5c12b0Sopenharmony_ci unsigned int segno = 0; 26045e5c12b0Sopenharmony_ci struct f2fs_summary_block *sum = curseg->sum_blk; 26055e5c12b0Sopenharmony_ci char *ptr = NULL; 26065e5c12b0Sopenharmony_ci 26075e5c12b0Sopenharmony_ci sit_blk = calloc(BLOCK_SZ, 1); 26085e5c12b0Sopenharmony_ci ASSERT(sit_blk); 26095e5c12b0Sopenharmony_ci /* remove sit journal */ 26105e5c12b0Sopenharmony_ci sum->journal.n_sits = 0; 26115e5c12b0Sopenharmony_ci 26125e5c12b0Sopenharmony_ci ptr = fsck->main_area_bitmap; 26135e5c12b0Sopenharmony_ci 26145e5c12b0Sopenharmony_ci for (segno = 0; segno < MAIN_SEGS(sbi); segno++) { 26155e5c12b0Sopenharmony_ci struct f2fs_sit_entry *sit; 26165e5c12b0Sopenharmony_ci struct seg_entry *se; 26175e5c12b0Sopenharmony_ci u16 valid_blocks = 0; 26185e5c12b0Sopenharmony_ci u16 type; 26195e5c12b0Sopenharmony_ci int i; 26205e5c12b0Sopenharmony_ci 26215e5c12b0Sopenharmony_ci get_current_sit_page(sbi, segno, sit_blk); 26225e5c12b0Sopenharmony_ci sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; 26235e5c12b0Sopenharmony_ci memcpy(sit->valid_map, ptr, SIT_VBLOCK_MAP_SIZE); 26245e5c12b0Sopenharmony_ci 26255e5c12b0Sopenharmony_ci /* update valid block count */ 26265e5c12b0Sopenharmony_ci for (i = 0; i < SIT_VBLOCK_MAP_SIZE; i++) 26275e5c12b0Sopenharmony_ci valid_blocks += get_bits_in_byte(sit->valid_map[i]); 26285e5c12b0Sopenharmony_ci 26295e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 26305e5c12b0Sopenharmony_ci memcpy(se->cur_valid_map, ptr, SIT_VBLOCK_MAP_SIZE); 26315e5c12b0Sopenharmony_ci se->valid_blocks = valid_blocks; 26325e5c12b0Sopenharmony_ci type = se->type; 26335e5c12b0Sopenharmony_ci if (type >= NO_CHECK_TYPE) { 26345e5c12b0Sopenharmony_ci ASSERT_MSG("Invalid type and valid blocks=%x,%x", 26355e5c12b0Sopenharmony_ci segno, valid_blocks); 26365e5c12b0Sopenharmony_ci type = 0; 26375e5c12b0Sopenharmony_ci } 26385e5c12b0Sopenharmony_ci sit->vblocks = cpu_to_le16((type << SIT_VBLOCKS_SHIFT) | 26395e5c12b0Sopenharmony_ci valid_blocks); 26405e5c12b0Sopenharmony_ci rewrite_current_sit_page(sbi, segno, sit_blk); 26415e5c12b0Sopenharmony_ci 26425e5c12b0Sopenharmony_ci ptr += SIT_VBLOCK_MAP_SIZE; 26435e5c12b0Sopenharmony_ci } 26445e5c12b0Sopenharmony_ci 26455e5c12b0Sopenharmony_ci free(sit_blk); 26465e5c12b0Sopenharmony_ci} 26475e5c12b0Sopenharmony_ci 26485e5c12b0Sopenharmony_cistatic int flush_sit_journal_entries(struct f2fs_sb_info *sbi) 26495e5c12b0Sopenharmony_ci{ 26505e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); 26515e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 26525e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 26535e5c12b0Sopenharmony_ci struct f2fs_sit_block *sit_blk; 26545e5c12b0Sopenharmony_ci unsigned int segno; 26555e5c12b0Sopenharmony_ci int i; 26565e5c12b0Sopenharmony_ci 26575e5c12b0Sopenharmony_ci sit_blk = calloc(BLOCK_SZ, 1); 26585e5c12b0Sopenharmony_ci ASSERT(sit_blk); 26595e5c12b0Sopenharmony_ci for (i = 0; i < sits_in_cursum(journal); i++) { 26605e5c12b0Sopenharmony_ci struct f2fs_sit_entry *sit; 26615e5c12b0Sopenharmony_ci struct seg_entry *se; 26625e5c12b0Sopenharmony_ci 26635e5c12b0Sopenharmony_ci segno = segno_in_journal(journal, i); 26645e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 26655e5c12b0Sopenharmony_ci 26665e5c12b0Sopenharmony_ci get_current_sit_page(sbi, segno, sit_blk); 26675e5c12b0Sopenharmony_ci sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; 26685e5c12b0Sopenharmony_ci 26695e5c12b0Sopenharmony_ci memcpy(sit->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); 26705e5c12b0Sopenharmony_ci sit->vblocks = cpu_to_le16((se->type << SIT_VBLOCKS_SHIFT) | 26715e5c12b0Sopenharmony_ci se->valid_blocks); 26725e5c12b0Sopenharmony_ci sit->mtime = cpu_to_le64(se->mtime); 26735e5c12b0Sopenharmony_ci 26745e5c12b0Sopenharmony_ci rewrite_current_sit_page(sbi, segno, sit_blk); 26755e5c12b0Sopenharmony_ci } 26765e5c12b0Sopenharmony_ci 26775e5c12b0Sopenharmony_ci free(sit_blk); 26785e5c12b0Sopenharmony_ci journal->n_sits = 0; 26795e5c12b0Sopenharmony_ci return i; 26805e5c12b0Sopenharmony_ci} 26815e5c12b0Sopenharmony_ci 26825e5c12b0Sopenharmony_cistatic int flush_nat_journal_entries(struct f2fs_sb_info *sbi) 26835e5c12b0Sopenharmony_ci{ 26845e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 26855e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 26865e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 26875e5c12b0Sopenharmony_ci pgoff_t block_addr; 26885e5c12b0Sopenharmony_ci int entry_off; 26895e5c12b0Sopenharmony_ci nid_t nid; 26905e5c12b0Sopenharmony_ci int ret; 26915e5c12b0Sopenharmony_ci int i = 0; 26925e5c12b0Sopenharmony_ci 26935e5c12b0Sopenharmony_ci nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 26945e5c12b0Sopenharmony_ci ASSERT(nat_block); 26955e5c12b0Sopenharmony_cinext: 26965e5c12b0Sopenharmony_ci if (i >= nats_in_cursum(journal)) { 26975e5c12b0Sopenharmony_ci free(nat_block); 26985e5c12b0Sopenharmony_ci journal->n_nats = 0; 26995e5c12b0Sopenharmony_ci return i; 27005e5c12b0Sopenharmony_ci } 27015e5c12b0Sopenharmony_ci 27025e5c12b0Sopenharmony_ci nid = le32_to_cpu(nid_in_journal(journal, i)); 27035e5c12b0Sopenharmony_ci 27045e5c12b0Sopenharmony_ci entry_off = nid % NAT_ENTRY_PER_BLOCK; 27055e5c12b0Sopenharmony_ci block_addr = current_nat_addr(sbi, nid, NULL); 27065e5c12b0Sopenharmony_ci 27075e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, block_addr); 27085e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 27095e5c12b0Sopenharmony_ci 27105e5c12b0Sopenharmony_ci memcpy(&nat_block->entries[entry_off], &nat_in_journal(journal, i), 27115e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 27125e5c12b0Sopenharmony_ci 27135e5c12b0Sopenharmony_ci ret = dev_write_block(nat_block, block_addr); 27145e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 27155e5c12b0Sopenharmony_ci i++; 27165e5c12b0Sopenharmony_ci goto next; 27175e5c12b0Sopenharmony_ci} 27185e5c12b0Sopenharmony_ci 27195e5c12b0Sopenharmony_civoid flush_journal_entries(struct f2fs_sb_info *sbi) 27205e5c12b0Sopenharmony_ci{ 27215e5c12b0Sopenharmony_ci int n_nats = flush_nat_journal_entries(sbi); 27225e5c12b0Sopenharmony_ci int n_sits = flush_sit_journal_entries(sbi); 27235e5c12b0Sopenharmony_ci 27245e5c12b0Sopenharmony_ci if (n_nats || n_sits) 27255e5c12b0Sopenharmony_ci write_checkpoints(sbi); 27265e5c12b0Sopenharmony_ci} 27275e5c12b0Sopenharmony_ci 27285e5c12b0Sopenharmony_civoid flush_sit_entries(struct f2fs_sb_info *sbi) 27295e5c12b0Sopenharmony_ci{ 27305e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 27315e5c12b0Sopenharmony_ci struct f2fs_sit_block *sit_blk; 27325e5c12b0Sopenharmony_ci unsigned int segno = 0; 27335e5c12b0Sopenharmony_ci 27345e5c12b0Sopenharmony_ci sit_blk = calloc(BLOCK_SZ, 1); 27355e5c12b0Sopenharmony_ci ASSERT(sit_blk); 27365e5c12b0Sopenharmony_ci /* update free segments */ 27375e5c12b0Sopenharmony_ci for (segno = 0; segno < MAIN_SEGS(sbi); segno++) { 27385e5c12b0Sopenharmony_ci struct f2fs_sit_entry *sit; 27395e5c12b0Sopenharmony_ci struct seg_entry *se; 27405e5c12b0Sopenharmony_ci 27415e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 27425e5c12b0Sopenharmony_ci 27435e5c12b0Sopenharmony_ci if (!se->dirty) 27445e5c12b0Sopenharmony_ci continue; 27455e5c12b0Sopenharmony_ci 27465e5c12b0Sopenharmony_ci get_current_sit_page(sbi, segno, sit_blk); 27475e5c12b0Sopenharmony_ci sit = &sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, segno)]; 27485e5c12b0Sopenharmony_ci memcpy(sit->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); 27495e5c12b0Sopenharmony_ci sit->vblocks = cpu_to_le16((se->type << SIT_VBLOCKS_SHIFT) | 27505e5c12b0Sopenharmony_ci se->valid_blocks); 27515e5c12b0Sopenharmony_ci rewrite_current_sit_page(sbi, segno, sit_blk); 27525e5c12b0Sopenharmony_ci } 27535e5c12b0Sopenharmony_ci 27545e5c12b0Sopenharmony_ci free(sit_blk); 27555e5c12b0Sopenharmony_ci} 27565e5c12b0Sopenharmony_ci 27575e5c12b0Sopenharmony_ciint relocate_curseg_offset(struct f2fs_sb_info *sbi, int type) 27585e5c12b0Sopenharmony_ci{ 27595e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, type); 27605e5c12b0Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, curseg->segno); 27615e5c12b0Sopenharmony_ci unsigned int i; 27625e5c12b0Sopenharmony_ci 27635e5c12b0Sopenharmony_ci if (c.zoned_model == F2FS_ZONED_HM) 27645e5c12b0Sopenharmony_ci return -EINVAL; 27655e5c12b0Sopenharmony_ci 27665e5c12b0Sopenharmony_ci for (i = 0; i < sbi->blocks_per_seg; i++) { 27675e5c12b0Sopenharmony_ci if (!f2fs_test_bit(i, (const char *)se->cur_valid_map)) 27685e5c12b0Sopenharmony_ci break; 27695e5c12b0Sopenharmony_ci } 27705e5c12b0Sopenharmony_ci 27715e5c12b0Sopenharmony_ci if (i == sbi->blocks_per_seg) 27725e5c12b0Sopenharmony_ci return -EINVAL; 27735e5c12b0Sopenharmony_ci 27745e5c12b0Sopenharmony_ci DBG(1, "Update curseg[%d].next_blkoff %u -> %u, alloc_type %s -> SSR\n", 27755e5c12b0Sopenharmony_ci type, curseg->next_blkoff, i, 27765e5c12b0Sopenharmony_ci curseg->alloc_type == LFS ? "LFS" : "SSR"); 27775e5c12b0Sopenharmony_ci 27785e5c12b0Sopenharmony_ci curseg->next_blkoff = i; 27795e5c12b0Sopenharmony_ci curseg->alloc_type = SSR; 27805e5c12b0Sopenharmony_ci 27815e5c12b0Sopenharmony_ci return 0; 27825e5c12b0Sopenharmony_ci} 27835e5c12b0Sopenharmony_ci 27845e5c12b0Sopenharmony_civoid set_section_type(struct f2fs_sb_info *sbi, unsigned int segno, int type) 27855e5c12b0Sopenharmony_ci{ 27865e5c12b0Sopenharmony_ci unsigned int i; 27875e5c12b0Sopenharmony_ci 27885e5c12b0Sopenharmony_ci if (sbi->segs_per_sec == 1) 27895e5c12b0Sopenharmony_ci return; 27905e5c12b0Sopenharmony_ci 27915e5c12b0Sopenharmony_ci for (i = 0; i < sbi->segs_per_sec; i++) { 27925e5c12b0Sopenharmony_ci struct seg_entry *se = get_seg_entry(sbi, segno + i); 27935e5c12b0Sopenharmony_ci 27945e5c12b0Sopenharmony_ci se->type = type; 27955e5c12b0Sopenharmony_ci } 27965e5c12b0Sopenharmony_ci} 27975e5c12b0Sopenharmony_ci 27985e5c12b0Sopenharmony_ci#ifdef HAVE_LINUX_BLKZONED_H 27995e5c12b0Sopenharmony_ci 28005e5c12b0Sopenharmony_cistatic bool write_pointer_at_zone_start(struct f2fs_sb_info *sbi, 28015e5c12b0Sopenharmony_ci unsigned int zone_segno) 28025e5c12b0Sopenharmony_ci{ 28035e5c12b0Sopenharmony_ci uint64_t sector; 28045e5c12b0Sopenharmony_ci struct blk_zone blkz; 28055e5c12b0Sopenharmony_ci block_t block = START_BLOCK(sbi, zone_segno); 28065e5c12b0Sopenharmony_ci int log_sectors_per_block = sbi->log_blocksize - SECTOR_SHIFT; 28075e5c12b0Sopenharmony_ci int ret, j; 28085e5c12b0Sopenharmony_ci 28095e5c12b0Sopenharmony_ci if (c.zoned_model != F2FS_ZONED_HM) 28105e5c12b0Sopenharmony_ci return true; 28115e5c12b0Sopenharmony_ci 28125e5c12b0Sopenharmony_ci for (j = 0; j < MAX_DEVICES; j++) { 28135e5c12b0Sopenharmony_ci if (!c.devices[j].path) 28145e5c12b0Sopenharmony_ci break; 28155e5c12b0Sopenharmony_ci if (c.devices[j].start_blkaddr <= block && 28165e5c12b0Sopenharmony_ci block <= c.devices[j].end_blkaddr) 28175e5c12b0Sopenharmony_ci break; 28185e5c12b0Sopenharmony_ci } 28195e5c12b0Sopenharmony_ci 28205e5c12b0Sopenharmony_ci if (j >= MAX_DEVICES) 28215e5c12b0Sopenharmony_ci return false; 28225e5c12b0Sopenharmony_ci 28235e5c12b0Sopenharmony_ci sector = (block - c.devices[j].start_blkaddr) << log_sectors_per_block; 28245e5c12b0Sopenharmony_ci ret = f2fs_report_zone(j, sector, &blkz); 28255e5c12b0Sopenharmony_ci if (ret) 28265e5c12b0Sopenharmony_ci return false; 28275e5c12b0Sopenharmony_ci 28285e5c12b0Sopenharmony_ci if (blk_zone_type(&blkz) != BLK_ZONE_TYPE_SEQWRITE_REQ) 28295e5c12b0Sopenharmony_ci return true; 28305e5c12b0Sopenharmony_ci 28315e5c12b0Sopenharmony_ci return blk_zone_sector(&blkz) == blk_zone_wp_sector(&blkz); 28325e5c12b0Sopenharmony_ci} 28335e5c12b0Sopenharmony_ci 28345e5c12b0Sopenharmony_ci#else 28355e5c12b0Sopenharmony_ci 28365e5c12b0Sopenharmony_cistatic bool write_pointer_at_zone_start(struct f2fs_sb_info *UNUSED(sbi), 28375e5c12b0Sopenharmony_ci unsigned int UNUSED(zone_segno)) 28385e5c12b0Sopenharmony_ci{ 28395e5c12b0Sopenharmony_ci return true; 28405e5c12b0Sopenharmony_ci} 28415e5c12b0Sopenharmony_ci 28425e5c12b0Sopenharmony_ci#endif 28435e5c12b0Sopenharmony_ci 28445e5c12b0Sopenharmony_ciint find_next_free_block(struct f2fs_sb_info *sbi, u64 *to, int left, 28455e5c12b0Sopenharmony_ci int want_type, bool new_sec) 28465e5c12b0Sopenharmony_ci{ 28475e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 28485e5c12b0Sopenharmony_ci struct seg_entry *se; 28495e5c12b0Sopenharmony_ci u32 segno; 28505e5c12b0Sopenharmony_ci u32 offset; 28515e5c12b0Sopenharmony_ci int not_enough = 0; 28525e5c12b0Sopenharmony_ci u64 end_blkaddr = (get_sb(segment_count_main) << 28535e5c12b0Sopenharmony_ci get_sb(log_blocks_per_seg)) + get_sb(main_blkaddr); 28545e5c12b0Sopenharmony_ci 28555e5c12b0Sopenharmony_ci if (*to > 0) 28565e5c12b0Sopenharmony_ci *to -= left; 28575e5c12b0Sopenharmony_ci if (get_free_segments(sbi) <= SM_I(sbi)->reserved_segments + 1) 28585e5c12b0Sopenharmony_ci not_enough = 1; 28595e5c12b0Sopenharmony_ci 28605e5c12b0Sopenharmony_ci while (*to >= SM_I(sbi)->main_blkaddr && *to < end_blkaddr) { 28615e5c12b0Sopenharmony_ci unsigned short vblocks; 28625e5c12b0Sopenharmony_ci unsigned char *bitmap; 28635e5c12b0Sopenharmony_ci unsigned char type; 28645e5c12b0Sopenharmony_ci 28655e5c12b0Sopenharmony_ci segno = GET_SEGNO(sbi, *to); 28665e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, *to); 28675e5c12b0Sopenharmony_ci 28685e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 28695e5c12b0Sopenharmony_ci 28705e5c12b0Sopenharmony_ci vblocks = get_seg_vblocks(sbi, se); 28715e5c12b0Sopenharmony_ci bitmap = get_seg_bitmap(sbi, se); 28725e5c12b0Sopenharmony_ci type = get_seg_type(sbi, se); 28735e5c12b0Sopenharmony_ci 28745e5c12b0Sopenharmony_ci if (vblocks == sbi->blocks_per_seg) { 28755e5c12b0Sopenharmony_cinext_segment: 28765e5c12b0Sopenharmony_ci *to = left ? START_BLOCK(sbi, segno) - 1: 28775e5c12b0Sopenharmony_ci START_BLOCK(sbi, segno + 1); 28785e5c12b0Sopenharmony_ci continue; 28795e5c12b0Sopenharmony_ci } 28805e5c12b0Sopenharmony_ci if (!(get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) && 28815e5c12b0Sopenharmony_ci IS_CUR_SEGNO(sbi, segno)) 28825e5c12b0Sopenharmony_ci goto next_segment; 28835e5c12b0Sopenharmony_ci if (vblocks == 0 && not_enough) 28845e5c12b0Sopenharmony_ci goto next_segment; 28855e5c12b0Sopenharmony_ci 28865e5c12b0Sopenharmony_ci if (vblocks == 0 && !(segno % sbi->segs_per_sec)) { 28875e5c12b0Sopenharmony_ci struct seg_entry *se2; 28885e5c12b0Sopenharmony_ci unsigned int i; 28895e5c12b0Sopenharmony_ci 28905e5c12b0Sopenharmony_ci for (i = 1; i < sbi->segs_per_sec; i++) { 28915e5c12b0Sopenharmony_ci se2 = get_seg_entry(sbi, segno + i); 28925e5c12b0Sopenharmony_ci if (get_seg_vblocks(sbi, se2)) 28935e5c12b0Sopenharmony_ci break; 28945e5c12b0Sopenharmony_ci } 28955e5c12b0Sopenharmony_ci 28965e5c12b0Sopenharmony_ci if (i == sbi->segs_per_sec && 28975e5c12b0Sopenharmony_ci write_pointer_at_zone_start(sbi, segno)) { 28985e5c12b0Sopenharmony_ci set_section_type(sbi, segno, want_type); 28995e5c12b0Sopenharmony_ci return 0; 29005e5c12b0Sopenharmony_ci } 29015e5c12b0Sopenharmony_ci } 29025e5c12b0Sopenharmony_ci 29035e5c12b0Sopenharmony_ci if (type == want_type && !new_sec && 29045e5c12b0Sopenharmony_ci !f2fs_test_bit(offset, (const char *)bitmap)) 29055e5c12b0Sopenharmony_ci return 0; 29065e5c12b0Sopenharmony_ci 29075e5c12b0Sopenharmony_ci *to = left ? *to - 1: *to + 1; 29085e5c12b0Sopenharmony_ci } 29095e5c12b0Sopenharmony_ci return -1; 29105e5c12b0Sopenharmony_ci} 29115e5c12b0Sopenharmony_ci 29125e5c12b0Sopenharmony_cistatic void move_one_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left, 29135e5c12b0Sopenharmony_ci int i) 29145e5c12b0Sopenharmony_ci{ 29155e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 29165e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, i); 29175e5c12b0Sopenharmony_ci struct f2fs_summary_block buf; 29185e5c12b0Sopenharmony_ci u32 old_segno; 29195e5c12b0Sopenharmony_ci u64 ssa_blk, to; 29205e5c12b0Sopenharmony_ci int ret; 29215e5c12b0Sopenharmony_ci 29225e5c12b0Sopenharmony_ci if ((get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO))) { 29235e5c12b0Sopenharmony_ci if (i != CURSEG_HOT_DATA && i != CURSEG_HOT_NODE) 29245e5c12b0Sopenharmony_ci return; 29255e5c12b0Sopenharmony_ci 29265e5c12b0Sopenharmony_ci if (i == CURSEG_HOT_DATA) { 29275e5c12b0Sopenharmony_ci left = 0; 29285e5c12b0Sopenharmony_ci from = SM_I(sbi)->main_blkaddr; 29295e5c12b0Sopenharmony_ci } else { 29305e5c12b0Sopenharmony_ci left = 1; 29315e5c12b0Sopenharmony_ci from = __end_block_addr(sbi); 29325e5c12b0Sopenharmony_ci } 29335e5c12b0Sopenharmony_ci goto bypass_ssa; 29345e5c12b0Sopenharmony_ci } 29355e5c12b0Sopenharmony_ci 29365e5c12b0Sopenharmony_ci /* update original SSA too */ 29375e5c12b0Sopenharmony_ci ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); 29385e5c12b0Sopenharmony_ci ret = dev_write_block(curseg->sum_blk, ssa_blk); 29395e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 29405e5c12b0Sopenharmony_cibypass_ssa: 29415e5c12b0Sopenharmony_ci to = from; 29425e5c12b0Sopenharmony_ci ret = find_next_free_block(sbi, &to, left, i, 29435e5c12b0Sopenharmony_ci c.zoned_model == F2FS_ZONED_HM); 29445e5c12b0Sopenharmony_ci ASSERT(ret == 0); 29455e5c12b0Sopenharmony_ci 29465e5c12b0Sopenharmony_ci old_segno = curseg->segno; 29475e5c12b0Sopenharmony_ci curseg->segno = GET_SEGNO(sbi, to); 29485e5c12b0Sopenharmony_ci curseg->next_blkoff = OFFSET_IN_SEG(sbi, to); 29495e5c12b0Sopenharmony_ci curseg->alloc_type = c.zoned_model == F2FS_ZONED_HM ? LFS : SSR; 29505e5c12b0Sopenharmony_ci 29515e5c12b0Sopenharmony_ci /* update new segno */ 29525e5c12b0Sopenharmony_ci ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); 29535e5c12b0Sopenharmony_ci ret = dev_read_block(&buf, ssa_blk); 29545e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 29555e5c12b0Sopenharmony_ci 29565e5c12b0Sopenharmony_ci memcpy(curseg->sum_blk, &buf, SUM_ENTRIES_SIZE); 29575e5c12b0Sopenharmony_ci 29585e5c12b0Sopenharmony_ci /* update se->types */ 29595e5c12b0Sopenharmony_ci reset_curseg(sbi, i); 29605e5c12b0Sopenharmony_ci 29615e5c12b0Sopenharmony_ci FIX_MSG("Move curseg[%d] %x -> %x after %"PRIx64"\n", 29625e5c12b0Sopenharmony_ci i, old_segno, curseg->segno, from); 29635e5c12b0Sopenharmony_ci} 29645e5c12b0Sopenharmony_ci 29655e5c12b0Sopenharmony_civoid move_curseg_info(struct f2fs_sb_info *sbi, u64 from, int left) 29665e5c12b0Sopenharmony_ci{ 29675e5c12b0Sopenharmony_ci int i; 29685e5c12b0Sopenharmony_ci 29695e5c12b0Sopenharmony_ci /* update summary blocks having nullified journal entries */ 29705e5c12b0Sopenharmony_ci for (i = 0; i < NO_CHECK_TYPE; i++) 29715e5c12b0Sopenharmony_ci move_one_curseg_info(sbi, from, left, i); 29725e5c12b0Sopenharmony_ci} 29735e5c12b0Sopenharmony_ci 29745e5c12b0Sopenharmony_civoid update_curseg_info(struct f2fs_sb_info *sbi, int type) 29755e5c12b0Sopenharmony_ci{ 29765e5c12b0Sopenharmony_ci if (!relocate_curseg_offset(sbi, type)) 29775e5c12b0Sopenharmony_ci return; 29785e5c12b0Sopenharmony_ci move_one_curseg_info(sbi, SM_I(sbi)->main_blkaddr, 0, type); 29795e5c12b0Sopenharmony_ci} 29805e5c12b0Sopenharmony_ci 29815e5c12b0Sopenharmony_civoid zero_journal_entries(struct f2fs_sb_info *sbi) 29825e5c12b0Sopenharmony_ci{ 29835e5c12b0Sopenharmony_ci int i; 29845e5c12b0Sopenharmony_ci 29855e5c12b0Sopenharmony_ci for (i = 0; i < NO_CHECK_TYPE; i++) 29865e5c12b0Sopenharmony_ci CURSEG_I(sbi, i)->sum_blk->journal.n_nats = 0; 29875e5c12b0Sopenharmony_ci} 29885e5c12b0Sopenharmony_ci 29895e5c12b0Sopenharmony_civoid write_curseg_info(struct f2fs_sb_info *sbi) 29905e5c12b0Sopenharmony_ci{ 29915e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 29925e5c12b0Sopenharmony_ci int i; 29935e5c12b0Sopenharmony_ci 29945e5c12b0Sopenharmony_ci for (i = 0; i < NO_CHECK_TYPE; i++) { 29955e5c12b0Sopenharmony_ci cp->alloc_type[i] = CURSEG_I(sbi, i)->alloc_type; 29965e5c12b0Sopenharmony_ci if (i < CURSEG_HOT_NODE) { 29975e5c12b0Sopenharmony_ci set_cp(cur_data_segno[i], CURSEG_I(sbi, i)->segno); 29985e5c12b0Sopenharmony_ci set_cp(cur_data_blkoff[i], 29995e5c12b0Sopenharmony_ci CURSEG_I(sbi, i)->next_blkoff); 30005e5c12b0Sopenharmony_ci } else { 30015e5c12b0Sopenharmony_ci int n = i - CURSEG_HOT_NODE; 30025e5c12b0Sopenharmony_ci 30035e5c12b0Sopenharmony_ci set_cp(cur_node_segno[n], CURSEG_I(sbi, i)->segno); 30045e5c12b0Sopenharmony_ci set_cp(cur_node_blkoff[n], 30055e5c12b0Sopenharmony_ci CURSEG_I(sbi, i)->next_blkoff); 30065e5c12b0Sopenharmony_ci } 30075e5c12b0Sopenharmony_ci } 30085e5c12b0Sopenharmony_ci} 30095e5c12b0Sopenharmony_ci 30105e5c12b0Sopenharmony_ciint lookup_nat_in_journal(struct f2fs_sb_info *sbi, u32 nid, 30115e5c12b0Sopenharmony_ci struct f2fs_nat_entry *raw_nat) 30125e5c12b0Sopenharmony_ci{ 30135e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 30145e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 30155e5c12b0Sopenharmony_ci int i = 0; 30165e5c12b0Sopenharmony_ci 30175e5c12b0Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 30185e5c12b0Sopenharmony_ci if (le32_to_cpu(nid_in_journal(journal, i)) == nid) { 30195e5c12b0Sopenharmony_ci memcpy(raw_nat, &nat_in_journal(journal, i), 30205e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 30215e5c12b0Sopenharmony_ci DBG(3, "==> Found nid [0x%x] in nat cache\n", nid); 30225e5c12b0Sopenharmony_ci return i; 30235e5c12b0Sopenharmony_ci } 30245e5c12b0Sopenharmony_ci } 30255e5c12b0Sopenharmony_ci return -1; 30265e5c12b0Sopenharmony_ci} 30275e5c12b0Sopenharmony_ci 30285e5c12b0Sopenharmony_civoid nullify_nat_entry(struct f2fs_sb_info *sbi, u32 nid) 30295e5c12b0Sopenharmony_ci{ 30305e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 30315e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 30325e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 30335e5c12b0Sopenharmony_ci pgoff_t block_addr; 30345e5c12b0Sopenharmony_ci int entry_off; 30355e5c12b0Sopenharmony_ci int ret; 30365e5c12b0Sopenharmony_ci int i = 0; 30375e5c12b0Sopenharmony_ci 30385e5c12b0Sopenharmony_ci /* check in journal */ 30395e5c12b0Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 30405e5c12b0Sopenharmony_ci if (le32_to_cpu(nid_in_journal(journal, i)) == nid) { 30415e5c12b0Sopenharmony_ci memset(&nat_in_journal(journal, i), 0, 30425e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 30435e5c12b0Sopenharmony_ci FIX_MSG("Remove nid [0x%x] in nat journal", nid); 30445e5c12b0Sopenharmony_ci return; 30455e5c12b0Sopenharmony_ci } 30465e5c12b0Sopenharmony_ci } 30475e5c12b0Sopenharmony_ci nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 30485e5c12b0Sopenharmony_ci ASSERT(nat_block); 30495e5c12b0Sopenharmony_ci 30505e5c12b0Sopenharmony_ci entry_off = nid % NAT_ENTRY_PER_BLOCK; 30515e5c12b0Sopenharmony_ci block_addr = current_nat_addr(sbi, nid, NULL); 30525e5c12b0Sopenharmony_ci 30535e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, block_addr); 30545e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 30555e5c12b0Sopenharmony_ci 30565e5c12b0Sopenharmony_ci if (nid == F2FS_NODE_INO(sbi) || nid == F2FS_META_INO(sbi)) { 30575e5c12b0Sopenharmony_ci FIX_MSG("nid [0x%x] block_addr= 0x%x -> 0x1", nid, 30585e5c12b0Sopenharmony_ci le32_to_cpu(nat_block->entries[entry_off].block_addr)); 30595e5c12b0Sopenharmony_ci nat_block->entries[entry_off].block_addr = cpu_to_le32(0x1); 30605e5c12b0Sopenharmony_ci } else { 30615e5c12b0Sopenharmony_ci memset(&nat_block->entries[entry_off], 0, 30625e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 30635e5c12b0Sopenharmony_ci FIX_MSG("Remove nid [0x%x] in NAT", nid); 30645e5c12b0Sopenharmony_ci } 30655e5c12b0Sopenharmony_ci 30665e5c12b0Sopenharmony_ci ret = dev_write_block(nat_block, block_addr); 30675e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 30685e5c12b0Sopenharmony_ci free(nat_block); 30695e5c12b0Sopenharmony_ci} 30705e5c12b0Sopenharmony_ci 30715e5c12b0Sopenharmony_civoid duplicate_checkpoint(struct f2fs_sb_info *sbi) 30725e5c12b0Sopenharmony_ci{ 30735e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 30745e5c12b0Sopenharmony_ci unsigned long long dst, src; 30755e5c12b0Sopenharmony_ci void *buf; 30765e5c12b0Sopenharmony_ci unsigned int seg_size = 1 << get_sb(log_blocks_per_seg); 30775e5c12b0Sopenharmony_ci int ret; 30785e5c12b0Sopenharmony_ci 30795e5c12b0Sopenharmony_ci if (sbi->cp_backuped) 30805e5c12b0Sopenharmony_ci return; 30815e5c12b0Sopenharmony_ci 30825e5c12b0Sopenharmony_ci buf = malloc(F2FS_BLKSIZE * seg_size); 30835e5c12b0Sopenharmony_ci ASSERT(buf); 30845e5c12b0Sopenharmony_ci 30855e5c12b0Sopenharmony_ci if (sbi->cur_cp == 1) { 30865e5c12b0Sopenharmony_ci src = get_sb(cp_blkaddr); 30875e5c12b0Sopenharmony_ci dst = src + seg_size; 30885e5c12b0Sopenharmony_ci } else { 30895e5c12b0Sopenharmony_ci dst = get_sb(cp_blkaddr); 30905e5c12b0Sopenharmony_ci src = dst + seg_size; 30915e5c12b0Sopenharmony_ci } 30925e5c12b0Sopenharmony_ci 30935e5c12b0Sopenharmony_ci ret = dev_read(buf, src << F2FS_BLKSIZE_BITS, 30945e5c12b0Sopenharmony_ci seg_size << F2FS_BLKSIZE_BITS); 30955e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 30965e5c12b0Sopenharmony_ci 30975e5c12b0Sopenharmony_ci ret = dev_write(buf, dst << F2FS_BLKSIZE_BITS, 30985e5c12b0Sopenharmony_ci seg_size << F2FS_BLKSIZE_BITS); 30995e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31005e5c12b0Sopenharmony_ci 31015e5c12b0Sopenharmony_ci free(buf); 31025e5c12b0Sopenharmony_ci 31035e5c12b0Sopenharmony_ci ret = f2fs_fsync_device(); 31045e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31055e5c12b0Sopenharmony_ci 31065e5c12b0Sopenharmony_ci sbi->cp_backuped = 1; 31075e5c12b0Sopenharmony_ci 31085e5c12b0Sopenharmony_ci MSG(0, "Info: Duplicate valid checkpoint to mirror position " 31095e5c12b0Sopenharmony_ci "%llu -> %llu\n", src, dst); 31105e5c12b0Sopenharmony_ci} 31115e5c12b0Sopenharmony_ci 31125e5c12b0Sopenharmony_civoid write_checkpoint(struct f2fs_sb_info *sbi) 31135e5c12b0Sopenharmony_ci{ 31145e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 31155e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 31165e5c12b0Sopenharmony_ci block_t orphan_blks = 0; 31175e5c12b0Sopenharmony_ci unsigned long long cp_blk_no; 31185e5c12b0Sopenharmony_ci u32 flags = CP_UMOUNT_FLAG; 31195e5c12b0Sopenharmony_ci int i, ret; 31205e5c12b0Sopenharmony_ci uint32_t crc = 0; 31215e5c12b0Sopenharmony_ci 31225e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_ORPHAN_PRESENT_FLAG)) { 31235e5c12b0Sopenharmony_ci orphan_blks = __start_sum_addr(sbi) - 1; 31245e5c12b0Sopenharmony_ci flags |= CP_ORPHAN_PRESENT_FLAG; 31255e5c12b0Sopenharmony_ci } 31265e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_TRIMMED_FLAG)) 31275e5c12b0Sopenharmony_ci flags |= CP_TRIMMED_FLAG; 31285e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_DISABLED_FLAG)) 31295e5c12b0Sopenharmony_ci flags |= CP_DISABLED_FLAG; 31305e5c12b0Sopenharmony_ci if (is_set_ckpt_flags(cp, CP_LARGE_NAT_BITMAP_FLAG)) { 31315e5c12b0Sopenharmony_ci flags |= CP_LARGE_NAT_BITMAP_FLAG; 31325e5c12b0Sopenharmony_ci set_cp(checksum_offset, CP_MIN_CHKSUM_OFFSET); 31335e5c12b0Sopenharmony_ci } else { 31345e5c12b0Sopenharmony_ci set_cp(checksum_offset, CP_CHKSUM_OFFSET); 31355e5c12b0Sopenharmony_ci } 31365e5c12b0Sopenharmony_ci 31375e5c12b0Sopenharmony_ci set_cp(free_segment_count, get_free_segments(sbi)); 31385e5c12b0Sopenharmony_ci if (c.func == FSCK) { 31395e5c12b0Sopenharmony_ci struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 31405e5c12b0Sopenharmony_ci 31415e5c12b0Sopenharmony_ci set_cp(valid_block_count, fsck->chk.valid_blk_cnt); 31425e5c12b0Sopenharmony_ci set_cp(valid_node_count, fsck->chk.valid_node_cnt); 31435e5c12b0Sopenharmony_ci set_cp(valid_inode_count, fsck->chk.valid_inode_cnt); 31445e5c12b0Sopenharmony_ci } else { 31455e5c12b0Sopenharmony_ci set_cp(valid_block_count, sbi->total_valid_block_count); 31465e5c12b0Sopenharmony_ci set_cp(valid_node_count, sbi->total_valid_node_count); 31475e5c12b0Sopenharmony_ci set_cp(valid_inode_count, sbi->total_valid_inode_count); 31485e5c12b0Sopenharmony_ci } 31495e5c12b0Sopenharmony_ci set_cp(cp_pack_total_block_count, 8 + orphan_blks + get_sb(cp_payload)); 31505e5c12b0Sopenharmony_ci 31515e5c12b0Sopenharmony_ci flags = update_nat_bits_flags(sb, cp, flags); 31525e5c12b0Sopenharmony_ci set_cp(ckpt_flags, flags); 31535e5c12b0Sopenharmony_ci 31545e5c12b0Sopenharmony_ci crc = f2fs_checkpoint_chksum(cp); 31555e5c12b0Sopenharmony_ci *((__le32 *)((unsigned char *)cp + get_cp(checksum_offset))) = 31565e5c12b0Sopenharmony_ci cpu_to_le32(crc); 31575e5c12b0Sopenharmony_ci 31585e5c12b0Sopenharmony_ci cp_blk_no = get_sb(cp_blkaddr); 31595e5c12b0Sopenharmony_ci if (sbi->cur_cp == 2) 31605e5c12b0Sopenharmony_ci cp_blk_no += 1 << get_sb(log_blocks_per_seg); 31615e5c12b0Sopenharmony_ci 31625e5c12b0Sopenharmony_ci /* write the first cp */ 31635e5c12b0Sopenharmony_ci ret = dev_write_block(cp, cp_blk_no++); 31645e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31655e5c12b0Sopenharmony_ci 31665e5c12b0Sopenharmony_ci /* skip payload */ 31675e5c12b0Sopenharmony_ci cp_blk_no += get_sb(cp_payload); 31685e5c12b0Sopenharmony_ci /* skip orphan blocks */ 31695e5c12b0Sopenharmony_ci cp_blk_no += orphan_blks; 31705e5c12b0Sopenharmony_ci 31715e5c12b0Sopenharmony_ci /* update summary blocks having nullified journal entries */ 31725e5c12b0Sopenharmony_ci for (i = 0; i < NO_CHECK_TYPE; i++) { 31735e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, i); 31745e5c12b0Sopenharmony_ci u64 ssa_blk; 31755e5c12b0Sopenharmony_ci 31765e5c12b0Sopenharmony_ci ret = dev_write_block(curseg->sum_blk, cp_blk_no++); 31775e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31785e5c12b0Sopenharmony_ci 31795e5c12b0Sopenharmony_ci if (!(get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO))) { 31805e5c12b0Sopenharmony_ci /* update original SSA too */ 31815e5c12b0Sopenharmony_ci ssa_blk = GET_SUM_BLKADDR(sbi, curseg->segno); 31825e5c12b0Sopenharmony_ci ret = dev_write_block(curseg->sum_blk, ssa_blk); 31835e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31845e5c12b0Sopenharmony_ci } 31855e5c12b0Sopenharmony_ci } 31865e5c12b0Sopenharmony_ci 31875e5c12b0Sopenharmony_ci /* Write nat bits */ 31885e5c12b0Sopenharmony_ci if (flags & CP_NAT_BITS_FLAG) 31895e5c12b0Sopenharmony_ci write_nat_bits(sbi, sb, cp, sbi->cur_cp); 31905e5c12b0Sopenharmony_ci 31915e5c12b0Sopenharmony_ci /* in case of sudden power off */ 31925e5c12b0Sopenharmony_ci ret = f2fs_fsync_device(); 31935e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31945e5c12b0Sopenharmony_ci 31955e5c12b0Sopenharmony_ci /* write the last cp */ 31965e5c12b0Sopenharmony_ci ret = dev_write_block(cp, cp_blk_no++); 31975e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 31985e5c12b0Sopenharmony_ci 31995e5c12b0Sopenharmony_ci ret = f2fs_fsync_device(); 32005e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 32015e5c12b0Sopenharmony_ci} 32025e5c12b0Sopenharmony_ci 32035e5c12b0Sopenharmony_civoid write_checkpoints(struct f2fs_sb_info *sbi) 32045e5c12b0Sopenharmony_ci{ 32055e5c12b0Sopenharmony_ci /* copy valid checkpoint to its mirror position */ 32065e5c12b0Sopenharmony_ci duplicate_checkpoint(sbi); 32075e5c12b0Sopenharmony_ci 32085e5c12b0Sopenharmony_ci /* repair checkpoint at CP #0 position */ 32095e5c12b0Sopenharmony_ci sbi->cur_cp = 1; 32105e5c12b0Sopenharmony_ci write_checkpoint(sbi); 32115e5c12b0Sopenharmony_ci} 32125e5c12b0Sopenharmony_ci 32135e5c12b0Sopenharmony_civoid build_nat_area_bitmap(struct f2fs_sb_info *sbi) 32145e5c12b0Sopenharmony_ci{ 32155e5c12b0Sopenharmony_ci struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); 32165e5c12b0Sopenharmony_ci struct f2fs_journal *journal = &curseg->sum_blk->journal; 32175e5c12b0Sopenharmony_ci struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 32185e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 32195e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 32205e5c12b0Sopenharmony_ci struct f2fs_nat_block *nat_block; 32215e5c12b0Sopenharmony_ci struct node_info ni; 32225e5c12b0Sopenharmony_ci u32 nid, nr_nat_blks; 32235e5c12b0Sopenharmony_ci pgoff_t block_off; 32245e5c12b0Sopenharmony_ci pgoff_t block_addr; 32255e5c12b0Sopenharmony_ci int seg_off; 32265e5c12b0Sopenharmony_ci int ret; 32275e5c12b0Sopenharmony_ci unsigned int i; 32285e5c12b0Sopenharmony_ci 32295e5c12b0Sopenharmony_ci nat_block = (struct f2fs_nat_block *)calloc(BLOCK_SZ, 1); 32305e5c12b0Sopenharmony_ci ASSERT(nat_block); 32315e5c12b0Sopenharmony_ci 32325e5c12b0Sopenharmony_ci /* Alloc & build nat entry bitmap */ 32335e5c12b0Sopenharmony_ci nr_nat_blks = (get_sb(segment_count_nat) / 2) << 32345e5c12b0Sopenharmony_ci sbi->log_blocks_per_seg; 32355e5c12b0Sopenharmony_ci 32365e5c12b0Sopenharmony_ci fsck->nr_nat_entries = nr_nat_blks * NAT_ENTRY_PER_BLOCK; 32375e5c12b0Sopenharmony_ci fsck->nat_area_bitmap_sz = (fsck->nr_nat_entries + 7) / 8; 32385e5c12b0Sopenharmony_ci fsck->nat_area_bitmap = calloc(fsck->nat_area_bitmap_sz, 1); 32395e5c12b0Sopenharmony_ci ASSERT(fsck->nat_area_bitmap); 32405e5c12b0Sopenharmony_ci 32415e5c12b0Sopenharmony_ci fsck->entries = calloc(sizeof(struct f2fs_nat_entry), 32425e5c12b0Sopenharmony_ci fsck->nr_nat_entries); 32435e5c12b0Sopenharmony_ci ASSERT(fsck->entries); 32445e5c12b0Sopenharmony_ci 32455e5c12b0Sopenharmony_ci for (block_off = 0; block_off < nr_nat_blks; block_off++) { 32465e5c12b0Sopenharmony_ci 32475e5c12b0Sopenharmony_ci seg_off = block_off >> sbi->log_blocks_per_seg; 32485e5c12b0Sopenharmony_ci block_addr = (pgoff_t)(nm_i->nat_blkaddr + 32495e5c12b0Sopenharmony_ci (seg_off << sbi->log_blocks_per_seg << 1) + 32505e5c12b0Sopenharmony_ci (block_off & ((1 << sbi->log_blocks_per_seg) - 1))); 32515e5c12b0Sopenharmony_ci 32525e5c12b0Sopenharmony_ci if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) 32535e5c12b0Sopenharmony_ci block_addr += sbi->blocks_per_seg; 32545e5c12b0Sopenharmony_ci 32555e5c12b0Sopenharmony_ci ret = dev_read_block(nat_block, block_addr); 32565e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 32575e5c12b0Sopenharmony_ci 32585e5c12b0Sopenharmony_ci nid = block_off * NAT_ENTRY_PER_BLOCK; 32595e5c12b0Sopenharmony_ci for (i = 0; i < NAT_ENTRY_PER_BLOCK; i++) { 32605e5c12b0Sopenharmony_ci ni.nid = nid + i; 32615e5c12b0Sopenharmony_ci 32625e5c12b0Sopenharmony_ci if ((nid + i) == F2FS_NODE_INO(sbi) || 32635e5c12b0Sopenharmony_ci (nid + i) == F2FS_META_INO(sbi)) { 32645e5c12b0Sopenharmony_ci /* 32655e5c12b0Sopenharmony_ci * block_addr of node/meta inode should be 0x1. 32665e5c12b0Sopenharmony_ci * Set this bit, and fsck_verify will fix it. 32675e5c12b0Sopenharmony_ci */ 32685e5c12b0Sopenharmony_ci if (le32_to_cpu(nat_block->entries[i].block_addr) != 0x1) { 32695e5c12b0Sopenharmony_ci ASSERT_MSG("\tError: ino[0x%x] block_addr[0x%x] is invalid\n", 32705e5c12b0Sopenharmony_ci nid + i, le32_to_cpu(nat_block->entries[i].block_addr)); 32715e5c12b0Sopenharmony_ci f2fs_set_bit(nid + i, fsck->nat_area_bitmap); 32725e5c12b0Sopenharmony_ci } 32735e5c12b0Sopenharmony_ci continue; 32745e5c12b0Sopenharmony_ci } 32755e5c12b0Sopenharmony_ci 32765e5c12b0Sopenharmony_ci node_info_from_raw_nat(&ni, &nat_block->entries[i]); 32775e5c12b0Sopenharmony_ci if (ni.blk_addr == 0x0) 32785e5c12b0Sopenharmony_ci continue; 32795e5c12b0Sopenharmony_ci if (ni.ino == 0x0) { 32805e5c12b0Sopenharmony_ci ASSERT_MSG("\tError: ino[0x%8x] or blk_addr[0x%16x]" 32815e5c12b0Sopenharmony_ci " is invalid\n", ni.ino, ni.blk_addr); 32825e5c12b0Sopenharmony_ci } 32835e5c12b0Sopenharmony_ci if (ni.ino == (nid + i)) { 32845e5c12b0Sopenharmony_ci fsck->nat_valid_inode_cnt++; 32855e5c12b0Sopenharmony_ci DBG(3, "ino[0x%8x] maybe is inode\n", ni.ino); 32865e5c12b0Sopenharmony_ci } 32875e5c12b0Sopenharmony_ci if (nid + i == 0) { 32885e5c12b0Sopenharmony_ci /* 32895e5c12b0Sopenharmony_ci * nat entry [0] must be null. If 32905e5c12b0Sopenharmony_ci * it is corrupted, set its bit in 32915e5c12b0Sopenharmony_ci * nat_area_bitmap, fsck_verify will 32925e5c12b0Sopenharmony_ci * nullify it 32935e5c12b0Sopenharmony_ci */ 32945e5c12b0Sopenharmony_ci ASSERT_MSG("Invalid nat entry[0]: " 32955e5c12b0Sopenharmony_ci "blk_addr[0x%x]\n", ni.blk_addr); 32965e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt--; 32975e5c12b0Sopenharmony_ci } 32985e5c12b0Sopenharmony_ci 32995e5c12b0Sopenharmony_ci DBG(3, "nid[0x%8x] addr[0x%16x] ino[0x%8x]\n", 33005e5c12b0Sopenharmony_ci nid + i, ni.blk_addr, ni.ino); 33015e5c12b0Sopenharmony_ci f2fs_set_bit(nid + i, fsck->nat_area_bitmap); 33025e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt++; 33035e5c12b0Sopenharmony_ci 33045e5c12b0Sopenharmony_ci fsck->entries[nid + i] = nat_block->entries[i]; 33055e5c12b0Sopenharmony_ci } 33065e5c12b0Sopenharmony_ci } 33075e5c12b0Sopenharmony_ci 33085e5c12b0Sopenharmony_ci /* Traverse nat journal, update the corresponding entries */ 33095e5c12b0Sopenharmony_ci for (i = 0; i < nats_in_cursum(journal); i++) { 33105e5c12b0Sopenharmony_ci struct f2fs_nat_entry raw_nat; 33115e5c12b0Sopenharmony_ci nid = le32_to_cpu(nid_in_journal(journal, i)); 33125e5c12b0Sopenharmony_ci ni.nid = nid; 33135e5c12b0Sopenharmony_ci 33145e5c12b0Sopenharmony_ci DBG(3, "==> Found nid [0x%x] in nat cache, update it\n", nid); 33155e5c12b0Sopenharmony_ci 33165e5c12b0Sopenharmony_ci /* Clear the original bit and count */ 33175e5c12b0Sopenharmony_ci if (fsck->entries[nid].block_addr != 0x0) { 33185e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt--; 33195e5c12b0Sopenharmony_ci f2fs_clear_bit(nid, fsck->nat_area_bitmap); 33205e5c12b0Sopenharmony_ci if (fsck->entries[nid].ino == nid) 33215e5c12b0Sopenharmony_ci fsck->nat_valid_inode_cnt--; 33225e5c12b0Sopenharmony_ci } 33235e5c12b0Sopenharmony_ci 33245e5c12b0Sopenharmony_ci /* Use nat entries in journal */ 33255e5c12b0Sopenharmony_ci memcpy(&raw_nat, &nat_in_journal(journal, i), 33265e5c12b0Sopenharmony_ci sizeof(struct f2fs_nat_entry)); 33275e5c12b0Sopenharmony_ci node_info_from_raw_nat(&ni, &raw_nat); 33285e5c12b0Sopenharmony_ci if (ni.blk_addr != 0x0) { 33295e5c12b0Sopenharmony_ci if (ni.ino == 0x0) 33305e5c12b0Sopenharmony_ci ASSERT_MSG("\tError: ino[0x%8x] or blk_addr[0x%16x]" 33315e5c12b0Sopenharmony_ci " is invalid\n", ni.ino, ni.blk_addr); 33325e5c12b0Sopenharmony_ci if (ni.ino == nid) { 33335e5c12b0Sopenharmony_ci fsck->nat_valid_inode_cnt++; 33345e5c12b0Sopenharmony_ci DBG(3, "ino[0x%8x] maybe is inode\n", ni.ino); 33355e5c12b0Sopenharmony_ci } 33365e5c12b0Sopenharmony_ci f2fs_set_bit(nid, fsck->nat_area_bitmap); 33375e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt++; 33385e5c12b0Sopenharmony_ci DBG(3, "nid[0x%x] in nat cache\n", nid); 33395e5c12b0Sopenharmony_ci } 33405e5c12b0Sopenharmony_ci fsck->entries[nid] = raw_nat; 33415e5c12b0Sopenharmony_ci } 33425e5c12b0Sopenharmony_ci free(nat_block); 33435e5c12b0Sopenharmony_ci 33445e5c12b0Sopenharmony_ci DBG(1, "valid nat entries (block_addr != 0x0) [0x%8x : %u]\n", 33455e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt, 33465e5c12b0Sopenharmony_ci fsck->chk.valid_nat_entry_cnt); 33475e5c12b0Sopenharmony_ci} 33485e5c12b0Sopenharmony_ci 33495e5c12b0Sopenharmony_cistatic int check_sector_size(struct f2fs_super_block *sb) 33505e5c12b0Sopenharmony_ci{ 33515e5c12b0Sopenharmony_ci uint32_t log_sectorsize, log_sectors_per_block; 33525e5c12b0Sopenharmony_ci 33535e5c12b0Sopenharmony_ci log_sectorsize = log_base_2(c.sector_size); 33545e5c12b0Sopenharmony_ci log_sectors_per_block = log_base_2(c.sectors_per_blk); 33555e5c12b0Sopenharmony_ci 33565e5c12b0Sopenharmony_ci if (log_sectorsize == get_sb(log_sectorsize) && 33575e5c12b0Sopenharmony_ci log_sectors_per_block == get_sb(log_sectors_per_block)) 33585e5c12b0Sopenharmony_ci return 0; 33595e5c12b0Sopenharmony_ci 33605e5c12b0Sopenharmony_ci set_sb(log_sectorsize, log_sectorsize); 33615e5c12b0Sopenharmony_ci set_sb(log_sectors_per_block, log_sectors_per_block); 33625e5c12b0Sopenharmony_ci 33635e5c12b0Sopenharmony_ci update_superblock(sb, SB_MASK_ALL); 33645e5c12b0Sopenharmony_ci return 0; 33655e5c12b0Sopenharmony_ci} 33665e5c12b0Sopenharmony_ci 33675e5c12b0Sopenharmony_cistatic int tune_sb_features(struct f2fs_sb_info *sbi) 33685e5c12b0Sopenharmony_ci{ 33695e5c12b0Sopenharmony_ci int sb_changed = 0; 33705e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 33715e5c12b0Sopenharmony_ci 33725e5c12b0Sopenharmony_ci if (!(sb->feature & cpu_to_le32(F2FS_FEATURE_ENCRYPT)) && 33735e5c12b0Sopenharmony_ci c.feature & cpu_to_le32(F2FS_FEATURE_ENCRYPT)) { 33745e5c12b0Sopenharmony_ci sb->feature |= cpu_to_le32(F2FS_FEATURE_ENCRYPT); 33755e5c12b0Sopenharmony_ci MSG(0, "Info: Set Encryption feature\n"); 33765e5c12b0Sopenharmony_ci sb_changed = 1; 33775e5c12b0Sopenharmony_ci } 33785e5c12b0Sopenharmony_ci if (!(sb->feature & cpu_to_le32(F2FS_FEATURE_CASEFOLD)) && 33795e5c12b0Sopenharmony_ci c.feature & cpu_to_le32(F2FS_FEATURE_CASEFOLD)) { 33805e5c12b0Sopenharmony_ci if (!c.s_encoding) { 33815e5c12b0Sopenharmony_ci ERR_MSG("ERROR: Must specify encoding to enable casefolding.\n"); 33825e5c12b0Sopenharmony_ci return -1; 33835e5c12b0Sopenharmony_ci } 33845e5c12b0Sopenharmony_ci sb->feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD); 33855e5c12b0Sopenharmony_ci MSG(0, "Info: Set Casefold feature\n"); 33865e5c12b0Sopenharmony_ci sb_changed = 1; 33875e5c12b0Sopenharmony_ci } 33885e5c12b0Sopenharmony_ci /* TODO: quota needs to allocate inode numbers */ 33895e5c12b0Sopenharmony_ci 33905e5c12b0Sopenharmony_ci c.feature = sb->feature; 33915e5c12b0Sopenharmony_ci if (!sb_changed) 33925e5c12b0Sopenharmony_ci return 0; 33935e5c12b0Sopenharmony_ci 33945e5c12b0Sopenharmony_ci update_superblock(sb, SB_MASK_ALL); 33955e5c12b0Sopenharmony_ci return 0; 33965e5c12b0Sopenharmony_ci} 33975e5c12b0Sopenharmony_ci 33985e5c12b0Sopenharmony_cistatic struct fsync_inode_entry *get_fsync_inode(struct list_head *head, 33995e5c12b0Sopenharmony_ci nid_t ino) 34005e5c12b0Sopenharmony_ci{ 34015e5c12b0Sopenharmony_ci struct fsync_inode_entry *entry; 34025e5c12b0Sopenharmony_ci 34035e5c12b0Sopenharmony_ci list_for_each_entry(entry, head, list) 34045e5c12b0Sopenharmony_ci if (entry->ino == ino) 34055e5c12b0Sopenharmony_ci return entry; 34065e5c12b0Sopenharmony_ci 34075e5c12b0Sopenharmony_ci return NULL; 34085e5c12b0Sopenharmony_ci} 34095e5c12b0Sopenharmony_ci 34105e5c12b0Sopenharmony_cistatic struct fsync_inode_entry *add_fsync_inode(struct list_head *head, 34115e5c12b0Sopenharmony_ci nid_t ino) 34125e5c12b0Sopenharmony_ci{ 34135e5c12b0Sopenharmony_ci struct fsync_inode_entry *entry; 34145e5c12b0Sopenharmony_ci 34155e5c12b0Sopenharmony_ci entry = calloc(sizeof(struct fsync_inode_entry), 1); 34165e5c12b0Sopenharmony_ci if (!entry) 34175e5c12b0Sopenharmony_ci return NULL; 34185e5c12b0Sopenharmony_ci entry->ino = ino; 34195e5c12b0Sopenharmony_ci list_add_tail(&entry->list, head); 34205e5c12b0Sopenharmony_ci return entry; 34215e5c12b0Sopenharmony_ci} 34225e5c12b0Sopenharmony_ci 34235e5c12b0Sopenharmony_cistatic void del_fsync_inode(struct fsync_inode_entry *entry) 34245e5c12b0Sopenharmony_ci{ 34255e5c12b0Sopenharmony_ci list_del(&entry->list); 34265e5c12b0Sopenharmony_ci free(entry); 34275e5c12b0Sopenharmony_ci} 34285e5c12b0Sopenharmony_ci 34295e5c12b0Sopenharmony_cistatic void destroy_fsync_dnodes(struct list_head *head) 34305e5c12b0Sopenharmony_ci{ 34315e5c12b0Sopenharmony_ci struct fsync_inode_entry *entry, *tmp; 34325e5c12b0Sopenharmony_ci 34335e5c12b0Sopenharmony_ci list_for_each_entry_safe(entry, tmp, head, list) 34345e5c12b0Sopenharmony_ci del_fsync_inode(entry); 34355e5c12b0Sopenharmony_ci} 34365e5c12b0Sopenharmony_ci 34375e5c12b0Sopenharmony_cistatic int find_fsync_inode(struct f2fs_sb_info *sbi, struct list_head *head) 34385e5c12b0Sopenharmony_ci{ 34395e5c12b0Sopenharmony_ci struct curseg_info *curseg; 34405e5c12b0Sopenharmony_ci struct f2fs_node *node_blk; 34415e5c12b0Sopenharmony_ci block_t blkaddr; 34425e5c12b0Sopenharmony_ci unsigned int loop_cnt = 0; 34435e5c12b0Sopenharmony_ci unsigned int free_blocks = MAIN_SEGS(sbi) * sbi->blocks_per_seg - 34445e5c12b0Sopenharmony_ci sbi->total_valid_block_count; 34455e5c12b0Sopenharmony_ci int err = 0; 34465e5c12b0Sopenharmony_ci 34475e5c12b0Sopenharmony_ci /* get node pages in the current segment */ 34485e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 34495e5c12b0Sopenharmony_ci blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 34505e5c12b0Sopenharmony_ci 34515e5c12b0Sopenharmony_ci node_blk = calloc(F2FS_BLKSIZE, 1); 34525e5c12b0Sopenharmony_ci ASSERT(node_blk); 34535e5c12b0Sopenharmony_ci 34545e5c12b0Sopenharmony_ci while (1) { 34555e5c12b0Sopenharmony_ci struct fsync_inode_entry *entry; 34565e5c12b0Sopenharmony_ci 34575e5c12b0Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) 34585e5c12b0Sopenharmony_ci break; 34595e5c12b0Sopenharmony_ci 34605e5c12b0Sopenharmony_ci err = dev_read_block(node_blk, blkaddr); 34615e5c12b0Sopenharmony_ci if (err) 34625e5c12b0Sopenharmony_ci break; 34635e5c12b0Sopenharmony_ci 34645e5c12b0Sopenharmony_ci if (!is_recoverable_dnode(sbi, node_blk)) 34655e5c12b0Sopenharmony_ci break; 34665e5c12b0Sopenharmony_ci 34675e5c12b0Sopenharmony_ci if (!is_fsync_dnode(node_blk)) 34685e5c12b0Sopenharmony_ci goto next; 34695e5c12b0Sopenharmony_ci 34705e5c12b0Sopenharmony_ci entry = get_fsync_inode(head, ino_of_node(node_blk)); 34715e5c12b0Sopenharmony_ci if (!entry) { 34725e5c12b0Sopenharmony_ci entry = add_fsync_inode(head, ino_of_node(node_blk)); 34735e5c12b0Sopenharmony_ci if (!entry) { 34745e5c12b0Sopenharmony_ci err = -1; 34755e5c12b0Sopenharmony_ci break; 34765e5c12b0Sopenharmony_ci } 34775e5c12b0Sopenharmony_ci } 34785e5c12b0Sopenharmony_ci entry->blkaddr = blkaddr; 34795e5c12b0Sopenharmony_ci 34805e5c12b0Sopenharmony_ci if (IS_INODE(node_blk) && is_dent_dnode(node_blk)) 34815e5c12b0Sopenharmony_ci entry->last_dentry = blkaddr; 34825e5c12b0Sopenharmony_cinext: 34835e5c12b0Sopenharmony_ci /* sanity check in order to detect looped node chain */ 34845e5c12b0Sopenharmony_ci if (++loop_cnt >= free_blocks || 34855e5c12b0Sopenharmony_ci blkaddr == next_blkaddr_of_node(node_blk)) { 34865e5c12b0Sopenharmony_ci MSG(0, "\tdetect looped node chain, blkaddr:%u, next:%u\n", 34875e5c12b0Sopenharmony_ci blkaddr, 34885e5c12b0Sopenharmony_ci next_blkaddr_of_node(node_blk)); 34895e5c12b0Sopenharmony_ci err = -1; 34905e5c12b0Sopenharmony_ci break; 34915e5c12b0Sopenharmony_ci } 34925e5c12b0Sopenharmony_ci 34935e5c12b0Sopenharmony_ci blkaddr = next_blkaddr_of_node(node_blk); 34945e5c12b0Sopenharmony_ci } 34955e5c12b0Sopenharmony_ci 34965e5c12b0Sopenharmony_ci free(node_blk); 34975e5c12b0Sopenharmony_ci return err; 34985e5c12b0Sopenharmony_ci} 34995e5c12b0Sopenharmony_ci 35005e5c12b0Sopenharmony_cistatic int do_record_fsync_data(struct f2fs_sb_info *sbi, 35015e5c12b0Sopenharmony_ci struct f2fs_node *node_blk, 35025e5c12b0Sopenharmony_ci block_t blkaddr) 35035e5c12b0Sopenharmony_ci{ 35045e5c12b0Sopenharmony_ci unsigned int segno, offset; 35055e5c12b0Sopenharmony_ci struct seg_entry *se; 35065e5c12b0Sopenharmony_ci unsigned int ofs_in_node = 0; 35075e5c12b0Sopenharmony_ci unsigned int start, end; 35085e5c12b0Sopenharmony_ci int err = 0, recorded = 0; 35095e5c12b0Sopenharmony_ci 35105e5c12b0Sopenharmony_ci segno = GET_SEGNO(sbi, blkaddr); 35115e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 35125e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, blkaddr); 35135e5c12b0Sopenharmony_ci 35145e5c12b0Sopenharmony_ci if (f2fs_test_bit(offset, (char *)se->cur_valid_map)) { 35155e5c12b0Sopenharmony_ci ASSERT(0); 35165e5c12b0Sopenharmony_ci return -1; 35175e5c12b0Sopenharmony_ci } 35185e5c12b0Sopenharmony_ci if (f2fs_test_bit(offset, (char *)se->ckpt_valid_map)) { 35195e5c12b0Sopenharmony_ci ASSERT(0); 35205e5c12b0Sopenharmony_ci return -1; 35215e5c12b0Sopenharmony_ci } 35225e5c12b0Sopenharmony_ci 35235e5c12b0Sopenharmony_ci if (!se->ckpt_valid_blocks) 35245e5c12b0Sopenharmony_ci se->ckpt_type = CURSEG_WARM_NODE; 35255e5c12b0Sopenharmony_ci 35265e5c12b0Sopenharmony_ci se->ckpt_valid_blocks++; 35275e5c12b0Sopenharmony_ci f2fs_set_bit(offset, (char *)se->ckpt_valid_map); 35285e5c12b0Sopenharmony_ci 35295e5c12b0Sopenharmony_ci MSG(1, "do_record_fsync_data: [node] ino = %u, nid = %u, blkaddr = %u\n", 35305e5c12b0Sopenharmony_ci ino_of_node(node_blk), ofs_of_node(node_blk), blkaddr); 35315e5c12b0Sopenharmony_ci 35325e5c12b0Sopenharmony_ci /* inline data */ 35335e5c12b0Sopenharmony_ci if (IS_INODE(node_blk) && (node_blk->i.i_inline & F2FS_INLINE_DATA)) 35345e5c12b0Sopenharmony_ci return 0; 35355e5c12b0Sopenharmony_ci /* xattr node */ 35365e5c12b0Sopenharmony_ci if (ofs_of_node(node_blk) == XATTR_NODE_OFFSET) 35375e5c12b0Sopenharmony_ci return 0; 35385e5c12b0Sopenharmony_ci 35395e5c12b0Sopenharmony_ci /* step 3: recover data indices */ 35405e5c12b0Sopenharmony_ci start = start_bidx_of_node(ofs_of_node(node_blk), node_blk); 35415e5c12b0Sopenharmony_ci end = start + ADDRS_PER_PAGE(sbi, node_blk, NULL); 35425e5c12b0Sopenharmony_ci 35435e5c12b0Sopenharmony_ci for (; start < end; start++, ofs_in_node++) { 35445e5c12b0Sopenharmony_ci blkaddr = datablock_addr(node_blk, ofs_in_node); 35455e5c12b0Sopenharmony_ci 35465e5c12b0Sopenharmony_ci if (!is_valid_data_blkaddr(blkaddr)) 35475e5c12b0Sopenharmony_ci continue; 35485e5c12b0Sopenharmony_ci 35495e5c12b0Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) { 35505e5c12b0Sopenharmony_ci err = -1; 35515e5c12b0Sopenharmony_ci goto out; 35525e5c12b0Sopenharmony_ci } 35535e5c12b0Sopenharmony_ci 35545e5c12b0Sopenharmony_ci segno = GET_SEGNO(sbi, blkaddr); 35555e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, segno); 35565e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, blkaddr); 35575e5c12b0Sopenharmony_ci 35585e5c12b0Sopenharmony_ci if (f2fs_test_bit(offset, (char *)se->cur_valid_map)) 35595e5c12b0Sopenharmony_ci continue; 35605e5c12b0Sopenharmony_ci if (f2fs_test_bit(offset, (char *)se->ckpt_valid_map)) 35615e5c12b0Sopenharmony_ci continue; 35625e5c12b0Sopenharmony_ci 35635e5c12b0Sopenharmony_ci if (!se->ckpt_valid_blocks) 35645e5c12b0Sopenharmony_ci se->ckpt_type = CURSEG_WARM_DATA; 35655e5c12b0Sopenharmony_ci 35665e5c12b0Sopenharmony_ci se->ckpt_valid_blocks++; 35675e5c12b0Sopenharmony_ci f2fs_set_bit(offset, (char *)se->ckpt_valid_map); 35685e5c12b0Sopenharmony_ci 35695e5c12b0Sopenharmony_ci MSG(1, "do_record_fsync_data: [data] ino = %u, nid = %u, blkaddr = %u\n", 35705e5c12b0Sopenharmony_ci ino_of_node(node_blk), ofs_of_node(node_blk), blkaddr); 35715e5c12b0Sopenharmony_ci 35725e5c12b0Sopenharmony_ci recorded++; 35735e5c12b0Sopenharmony_ci } 35745e5c12b0Sopenharmony_ciout: 35755e5c12b0Sopenharmony_ci MSG(1, "recover_data: ino = %u, nid = %u, recorded = %d, err = %d\n", 35765e5c12b0Sopenharmony_ci ino_of_node(node_blk), ofs_of_node(node_blk), 35775e5c12b0Sopenharmony_ci recorded, err); 35785e5c12b0Sopenharmony_ci return err; 35795e5c12b0Sopenharmony_ci} 35805e5c12b0Sopenharmony_ci 35815e5c12b0Sopenharmony_cistatic int traverse_dnodes(struct f2fs_sb_info *sbi, 35825e5c12b0Sopenharmony_ci struct list_head *inode_list) 35835e5c12b0Sopenharmony_ci{ 35845e5c12b0Sopenharmony_ci struct curseg_info *curseg; 35855e5c12b0Sopenharmony_ci struct f2fs_node *node_blk; 35865e5c12b0Sopenharmony_ci block_t blkaddr; 35875e5c12b0Sopenharmony_ci int err = 0; 35885e5c12b0Sopenharmony_ci 35895e5c12b0Sopenharmony_ci /* get node pages in the current segment */ 35905e5c12b0Sopenharmony_ci curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); 35915e5c12b0Sopenharmony_ci blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); 35925e5c12b0Sopenharmony_ci 35935e5c12b0Sopenharmony_ci node_blk = calloc(F2FS_BLKSIZE, 1); 35945e5c12b0Sopenharmony_ci ASSERT(node_blk); 35955e5c12b0Sopenharmony_ci 35965e5c12b0Sopenharmony_ci while (1) { 35975e5c12b0Sopenharmony_ci struct fsync_inode_entry *entry; 35985e5c12b0Sopenharmony_ci 35995e5c12b0Sopenharmony_ci if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) 36005e5c12b0Sopenharmony_ci break; 36015e5c12b0Sopenharmony_ci 36025e5c12b0Sopenharmony_ci err = dev_read_block(node_blk, blkaddr); 36035e5c12b0Sopenharmony_ci if (err) 36045e5c12b0Sopenharmony_ci break; 36055e5c12b0Sopenharmony_ci 36065e5c12b0Sopenharmony_ci if (!is_recoverable_dnode(sbi, node_blk)) 36075e5c12b0Sopenharmony_ci break; 36085e5c12b0Sopenharmony_ci 36095e5c12b0Sopenharmony_ci entry = get_fsync_inode(inode_list, 36105e5c12b0Sopenharmony_ci ino_of_node(node_blk)); 36115e5c12b0Sopenharmony_ci if (!entry) 36125e5c12b0Sopenharmony_ci goto next; 36135e5c12b0Sopenharmony_ci 36145e5c12b0Sopenharmony_ci err = do_record_fsync_data(sbi, node_blk, blkaddr); 36155e5c12b0Sopenharmony_ci if (err) 36165e5c12b0Sopenharmony_ci break; 36175e5c12b0Sopenharmony_ci 36185e5c12b0Sopenharmony_ci if (entry->blkaddr == blkaddr) 36195e5c12b0Sopenharmony_ci del_fsync_inode(entry); 36205e5c12b0Sopenharmony_cinext: 36215e5c12b0Sopenharmony_ci blkaddr = next_blkaddr_of_node(node_blk); 36225e5c12b0Sopenharmony_ci } 36235e5c12b0Sopenharmony_ci 36245e5c12b0Sopenharmony_ci free(node_blk); 36255e5c12b0Sopenharmony_ci return err; 36265e5c12b0Sopenharmony_ci} 36275e5c12b0Sopenharmony_ci 36285e5c12b0Sopenharmony_cistatic int record_fsync_data(struct f2fs_sb_info *sbi) 36295e5c12b0Sopenharmony_ci{ 36305e5c12b0Sopenharmony_ci struct list_head inode_list = LIST_HEAD_INIT(inode_list); 36315e5c12b0Sopenharmony_ci int ret; 36325e5c12b0Sopenharmony_ci 36335e5c12b0Sopenharmony_ci if (!need_fsync_data_record(sbi)) 36345e5c12b0Sopenharmony_ci return 0; 36355e5c12b0Sopenharmony_ci 36365e5c12b0Sopenharmony_ci ret = find_fsync_inode(sbi, &inode_list); 36375e5c12b0Sopenharmony_ci if (ret) 36385e5c12b0Sopenharmony_ci goto out; 36395e5c12b0Sopenharmony_ci 36405e5c12b0Sopenharmony_ci ret = late_build_segment_manager(sbi); 36415e5c12b0Sopenharmony_ci if (ret < 0) { 36425e5c12b0Sopenharmony_ci ERR_MSG("late_build_segment_manager failed\n"); 36435e5c12b0Sopenharmony_ci goto out; 36445e5c12b0Sopenharmony_ci } 36455e5c12b0Sopenharmony_ci 36465e5c12b0Sopenharmony_ci ret = traverse_dnodes(sbi, &inode_list); 36475e5c12b0Sopenharmony_ciout: 36485e5c12b0Sopenharmony_ci destroy_fsync_dnodes(&inode_list); 36495e5c12b0Sopenharmony_ci return ret; 36505e5c12b0Sopenharmony_ci} 36515e5c12b0Sopenharmony_ci 36525e5c12b0Sopenharmony_ciint f2fs_do_mount(struct f2fs_sb_info *sbi) 36535e5c12b0Sopenharmony_ci{ 36545e5c12b0Sopenharmony_ci struct f2fs_checkpoint *cp = NULL; 36555e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = NULL; 36565e5c12b0Sopenharmony_ci int ret; 36575e5c12b0Sopenharmony_ci 36585e5c12b0Sopenharmony_ci sbi->active_logs = NR_CURSEG_TYPE; 36595e5c12b0Sopenharmony_ci ret = validate_super_block(sbi, SB0_ADDR); 36605e5c12b0Sopenharmony_ci if (ret) { 36615e5c12b0Sopenharmony_ci ret = validate_super_block(sbi, SB1_ADDR); 36625e5c12b0Sopenharmony_ci if (ret) { 36635e5c12b0Sopenharmony_ci dump_sbi_info(sbi); 36645e5c12b0Sopenharmony_ci return -1; 36655e5c12b0Sopenharmony_ci } 36665e5c12b0Sopenharmony_ci } 36675e5c12b0Sopenharmony_ci sb = F2FS_RAW_SUPER(sbi); 36685e5c12b0Sopenharmony_ci 36695e5c12b0Sopenharmony_ci ret = check_sector_size(sb); 36705e5c12b0Sopenharmony_ci if (ret) 36715e5c12b0Sopenharmony_ci return -1; 36725e5c12b0Sopenharmony_ci 36735e5c12b0Sopenharmony_ci print_raw_sb_info(sb); 36745e5c12b0Sopenharmony_ci 36755e5c12b0Sopenharmony_ci init_sb_info(sbi); 36765e5c12b0Sopenharmony_ci 36775e5c12b0Sopenharmony_ci ret = get_valid_checkpoint(sbi); 36785e5c12b0Sopenharmony_ci if (ret) { 36795e5c12b0Sopenharmony_ci ERR_MSG("Can't find valid checkpoint\n"); 36805e5c12b0Sopenharmony_ci dump_sbi_info(sbi); 36815e5c12b0Sopenharmony_ci print_ckpt_info(sbi); 36825e5c12b0Sopenharmony_ci return -1; 36835e5c12b0Sopenharmony_ci } 36845e5c12b0Sopenharmony_ci 36855e5c12b0Sopenharmony_ci c.bug_on = 0; 36865e5c12b0Sopenharmony_ci 36875e5c12b0Sopenharmony_ci if (sanity_check_ckpt(sbi)) { 36885e5c12b0Sopenharmony_ci ERR_MSG("Checkpoint is polluted\n"); 36895e5c12b0Sopenharmony_ci dump_sbi_info(sbi); 36905e5c12b0Sopenharmony_ci print_ckpt_info(sbi); 36915e5c12b0Sopenharmony_ci return -1; 36925e5c12b0Sopenharmony_ci } 36935e5c12b0Sopenharmony_ci cp = F2FS_CKPT(sbi); 36945e5c12b0Sopenharmony_ci 36955e5c12b0Sopenharmony_ci if (c.func != FSCK && c.func != DUMP && 36965e5c12b0Sopenharmony_ci !is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) { 36975e5c12b0Sopenharmony_ci ERR_MSG("Mount unclean image to replay log first\n"); 36985e5c12b0Sopenharmony_ci return -1; 36995e5c12b0Sopenharmony_ci } 37005e5c12b0Sopenharmony_ci 37015e5c12b0Sopenharmony_ci if (c.func == FSCK) { 37025e5c12b0Sopenharmony_ci#if defined(__APPLE__) 37035e5c12b0Sopenharmony_ci if (!c.no_kernel_check && 37045e5c12b0Sopenharmony_ci memcmp(c.sb_version, c.version, VERSION_NAME_LEN)) { 37055e5c12b0Sopenharmony_ci c.auto_fix = 0; 37065e5c12b0Sopenharmony_ci c.fix_on = 1; 37075e5c12b0Sopenharmony_ci memcpy(sbi->raw_super->version, 37085e5c12b0Sopenharmony_ci c.version, VERSION_NAME_LEN); 37095e5c12b0Sopenharmony_ci update_superblock(sbi->raw_super, SB_MASK_ALL); 37105e5c12b0Sopenharmony_ci } 37115e5c12b0Sopenharmony_ci#else 37125e5c12b0Sopenharmony_ci if (!c.no_kernel_check) { 37135e5c12b0Sopenharmony_ci u32 prev_time, cur_time, time_diff; 37145e5c12b0Sopenharmony_ci __le32 *ver_ts_ptr = (__le32 *)(sbi->raw_super->version 37155e5c12b0Sopenharmony_ci + VERSION_NAME_LEN); 37165e5c12b0Sopenharmony_ci 37175e5c12b0Sopenharmony_ci cur_time = (u32)get_cp(elapsed_time); 37185e5c12b0Sopenharmony_ci prev_time = le32_to_cpu(*ver_ts_ptr); 37195e5c12b0Sopenharmony_ci 37205e5c12b0Sopenharmony_ci MSG(0, "Info: version timestamp cur: %u, prev: %u\n", 37215e5c12b0Sopenharmony_ci cur_time, prev_time); 37225e5c12b0Sopenharmony_ci if (!memcmp(c.sb_version, c.version, 37235e5c12b0Sopenharmony_ci VERSION_NAME_LEN)) { 37245e5c12b0Sopenharmony_ci /* valid prev_time */ 37255e5c12b0Sopenharmony_ci if (prev_time != 0 && cur_time > prev_time) { 37265e5c12b0Sopenharmony_ci time_diff = cur_time - prev_time; 37275e5c12b0Sopenharmony_ci if (time_diff < CHECK_PERIOD) 37285e5c12b0Sopenharmony_ci goto out; 37295e5c12b0Sopenharmony_ci c.auto_fix = 0; 37305e5c12b0Sopenharmony_ci c.fix_on = 1; 37315e5c12b0Sopenharmony_ci } 37325e5c12b0Sopenharmony_ci } else { 37335e5c12b0Sopenharmony_ci memcpy(sbi->raw_super->version, 37345e5c12b0Sopenharmony_ci c.version, VERSION_NAME_LEN); 37355e5c12b0Sopenharmony_ci } 37365e5c12b0Sopenharmony_ci 37375e5c12b0Sopenharmony_ci *ver_ts_ptr = cpu_to_le32(cur_time); 37385e5c12b0Sopenharmony_ci update_superblock(sbi->raw_super, SB_MASK_ALL); 37395e5c12b0Sopenharmony_ci } 37405e5c12b0Sopenharmony_ci#endif 37415e5c12b0Sopenharmony_ci } 37425e5c12b0Sopenharmony_ciout: 37435e5c12b0Sopenharmony_ci print_ckpt_info(sbi); 37445e5c12b0Sopenharmony_ci 37455e5c12b0Sopenharmony_ci if (c.quota_fix) { 37465e5c12b0Sopenharmony_ci if (get_cp(ckpt_flags) & CP_QUOTA_NEED_FSCK_FLAG) 37475e5c12b0Sopenharmony_ci c.fix_on = 1; 37485e5c12b0Sopenharmony_ci } 37495e5c12b0Sopenharmony_ci if (c.layout) 37505e5c12b0Sopenharmony_ci return 1; 37515e5c12b0Sopenharmony_ci 37525e5c12b0Sopenharmony_ci if (tune_sb_features(sbi)) 37535e5c12b0Sopenharmony_ci return -1; 37545e5c12b0Sopenharmony_ci 37555e5c12b0Sopenharmony_ci /* precompute checksum seed for metadata */ 37565e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) 37575e5c12b0Sopenharmony_ci c.chksum_seed = f2fs_cal_crc32(~0, sb->uuid, sizeof(sb->uuid)); 37585e5c12b0Sopenharmony_ci 37595e5c12b0Sopenharmony_ci sbi->total_valid_node_count = get_cp(valid_node_count); 37605e5c12b0Sopenharmony_ci sbi->total_valid_inode_count = get_cp(valid_inode_count); 37615e5c12b0Sopenharmony_ci sbi->user_block_count = get_cp(user_block_count); 37625e5c12b0Sopenharmony_ci sbi->total_valid_block_count = get_cp(valid_block_count); 37635e5c12b0Sopenharmony_ci sbi->last_valid_block_count = sbi->total_valid_block_count; 37645e5c12b0Sopenharmony_ci sbi->alloc_valid_block_count = 0; 37655e5c12b0Sopenharmony_ci 37665e5c12b0Sopenharmony_ci if (early_build_segment_manager(sbi)) { 37675e5c12b0Sopenharmony_ci ERR_MSG("early_build_segment_manager failed\n"); 37685e5c12b0Sopenharmony_ci return -1; 37695e5c12b0Sopenharmony_ci } 37705e5c12b0Sopenharmony_ci 37715e5c12b0Sopenharmony_ci if (build_node_manager(sbi)) { 37725e5c12b0Sopenharmony_ci ERR_MSG("build_node_manager failed\n"); 37735e5c12b0Sopenharmony_ci return -1; 37745e5c12b0Sopenharmony_ci } 37755e5c12b0Sopenharmony_ci 37765e5c12b0Sopenharmony_ci if (record_fsync_data(sbi)) { 37775e5c12b0Sopenharmony_ci ERR_MSG("record_fsync_data failed\n"); 37785e5c12b0Sopenharmony_ci return -1; 37795e5c12b0Sopenharmony_ci } 37805e5c12b0Sopenharmony_ci 37815e5c12b0Sopenharmony_ci if (!f2fs_should_proceed(sb, get_cp(ckpt_flags))) 37825e5c12b0Sopenharmony_ci return 1; 37835e5c12b0Sopenharmony_ci 37845e5c12b0Sopenharmony_ci if (late_build_segment_manager(sbi) < 0) { 37855e5c12b0Sopenharmony_ci ERR_MSG("late_build_segment_manager failed\n"); 37865e5c12b0Sopenharmony_ci return -1; 37875e5c12b0Sopenharmony_ci } 37885e5c12b0Sopenharmony_ci 37895e5c12b0Sopenharmony_ci if (f2fs_late_init_nid_bitmap(sbi)) { 37905e5c12b0Sopenharmony_ci ERR_MSG("f2fs_late_init_nid_bitmap failed\n"); 37915e5c12b0Sopenharmony_ci return -1; 37925e5c12b0Sopenharmony_ci } 37935e5c12b0Sopenharmony_ci 37945e5c12b0Sopenharmony_ci /* Check nat_bits */ 37955e5c12b0Sopenharmony_ci if (c.func == FSCK && is_set_ckpt_flags(cp, CP_NAT_BITS_FLAG)) { 37965e5c12b0Sopenharmony_ci if (check_nat_bits(sbi, sb, cp) && c.fix_on) 37975e5c12b0Sopenharmony_ci write_nat_bits(sbi, sb, cp, sbi->cur_cp); 37985e5c12b0Sopenharmony_ci } 37995e5c12b0Sopenharmony_ci return 0; 38005e5c12b0Sopenharmony_ci} 38015e5c12b0Sopenharmony_ci 38025e5c12b0Sopenharmony_civoid f2fs_do_umount(struct f2fs_sb_info *sbi) 38035e5c12b0Sopenharmony_ci{ 38045e5c12b0Sopenharmony_ci struct sit_info *sit_i = SIT_I(sbi); 38055e5c12b0Sopenharmony_ci struct f2fs_sm_info *sm_i = SM_I(sbi); 38065e5c12b0Sopenharmony_ci struct f2fs_nm_info *nm_i = NM_I(sbi); 38075e5c12b0Sopenharmony_ci unsigned int i; 38085e5c12b0Sopenharmony_ci 38095e5c12b0Sopenharmony_ci /* free nm_info */ 38105e5c12b0Sopenharmony_ci if (c.func == SLOAD || c.func == FSCK) 38115e5c12b0Sopenharmony_ci free(nm_i->nid_bitmap); 38125e5c12b0Sopenharmony_ci free(nm_i->nat_bitmap); 38135e5c12b0Sopenharmony_ci free(sbi->nm_info); 38145e5c12b0Sopenharmony_ci 38155e5c12b0Sopenharmony_ci /* free sit_info */ 38165e5c12b0Sopenharmony_ci free(sit_i->bitmap); 38175e5c12b0Sopenharmony_ci free(sit_i->sit_bitmap); 38185e5c12b0Sopenharmony_ci free(sit_i->sentries); 38195e5c12b0Sopenharmony_ci free(sm_i->sit_info); 38205e5c12b0Sopenharmony_ci 38215e5c12b0Sopenharmony_ci /* free sm_info */ 38225e5c12b0Sopenharmony_ci for (i = 0; i < NR_CURSEG_TYPE; i++) 38235e5c12b0Sopenharmony_ci free(sm_i->curseg_array[i].sum_blk); 38245e5c12b0Sopenharmony_ci 38255e5c12b0Sopenharmony_ci free(sm_i->curseg_array); 38265e5c12b0Sopenharmony_ci free(sbi->sm_info); 38275e5c12b0Sopenharmony_ci 38285e5c12b0Sopenharmony_ci free(sbi->ckpt); 38295e5c12b0Sopenharmony_ci free(sbi->raw_super); 38305e5c12b0Sopenharmony_ci} 38315e5c12b0Sopenharmony_ci 38325e5c12b0Sopenharmony_ci#ifdef WITH_ANDROID 38335e5c12b0Sopenharmony_ciint f2fs_sparse_initialize_meta(struct f2fs_sb_info *sbi) 38345e5c12b0Sopenharmony_ci{ 38355e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = sbi->raw_super; 38365e5c12b0Sopenharmony_ci uint32_t sit_seg_count, sit_size; 38375e5c12b0Sopenharmony_ci uint32_t nat_seg_count, nat_size; 38385e5c12b0Sopenharmony_ci uint64_t sit_seg_addr, nat_seg_addr, payload_addr; 38395e5c12b0Sopenharmony_ci uint32_t seg_size = 1 << get_sb(log_blocks_per_seg); 38405e5c12b0Sopenharmony_ci int ret; 38415e5c12b0Sopenharmony_ci 38425e5c12b0Sopenharmony_ci if (!c.sparse_mode) 38435e5c12b0Sopenharmony_ci return 0; 38445e5c12b0Sopenharmony_ci 38455e5c12b0Sopenharmony_ci sit_seg_addr = get_sb(sit_blkaddr); 38465e5c12b0Sopenharmony_ci sit_seg_count = get_sb(segment_count_sit); 38475e5c12b0Sopenharmony_ci sit_size = sit_seg_count * seg_size; 38485e5c12b0Sopenharmony_ci 38495e5c12b0Sopenharmony_ci DBG(1, "\tSparse: filling sit area at block offset: 0x%08"PRIx64" len: %u\n", 38505e5c12b0Sopenharmony_ci sit_seg_addr, sit_size); 38515e5c12b0Sopenharmony_ci ret = dev_fill(NULL, sit_seg_addr * F2FS_BLKSIZE, 38525e5c12b0Sopenharmony_ci sit_size * F2FS_BLKSIZE); 38535e5c12b0Sopenharmony_ci if (ret) { 38545e5c12b0Sopenharmony_ci MSG(1, "\tError: While zeroing out the sit area " 38555e5c12b0Sopenharmony_ci "on disk!!!\n"); 38565e5c12b0Sopenharmony_ci return -1; 38575e5c12b0Sopenharmony_ci } 38585e5c12b0Sopenharmony_ci 38595e5c12b0Sopenharmony_ci nat_seg_addr = get_sb(nat_blkaddr); 38605e5c12b0Sopenharmony_ci nat_seg_count = get_sb(segment_count_nat); 38615e5c12b0Sopenharmony_ci nat_size = nat_seg_count * seg_size; 38625e5c12b0Sopenharmony_ci 38635e5c12b0Sopenharmony_ci DBG(1, "\tSparse: filling nat area at block offset 0x%08"PRIx64" len: %u\n", 38645e5c12b0Sopenharmony_ci nat_seg_addr, nat_size); 38655e5c12b0Sopenharmony_ci ret = dev_fill(NULL, nat_seg_addr * F2FS_BLKSIZE, 38665e5c12b0Sopenharmony_ci nat_size * F2FS_BLKSIZE); 38675e5c12b0Sopenharmony_ci if (ret) { 38685e5c12b0Sopenharmony_ci MSG(1, "\tError: While zeroing out the nat area " 38695e5c12b0Sopenharmony_ci "on disk!!!\n"); 38705e5c12b0Sopenharmony_ci return -1; 38715e5c12b0Sopenharmony_ci } 38725e5c12b0Sopenharmony_ci 38735e5c12b0Sopenharmony_ci payload_addr = get_sb(segment0_blkaddr) + 1; 38745e5c12b0Sopenharmony_ci 38755e5c12b0Sopenharmony_ci DBG(1, "\tSparse: filling bitmap area at block offset 0x%08"PRIx64" len: %u\n", 38765e5c12b0Sopenharmony_ci payload_addr, get_sb(cp_payload)); 38775e5c12b0Sopenharmony_ci ret = dev_fill(NULL, payload_addr * F2FS_BLKSIZE, 38785e5c12b0Sopenharmony_ci get_sb(cp_payload) * F2FS_BLKSIZE); 38795e5c12b0Sopenharmony_ci if (ret) { 38805e5c12b0Sopenharmony_ci MSG(1, "\tError: While zeroing out the nat/sit bitmap area " 38815e5c12b0Sopenharmony_ci "on disk!!!\n"); 38825e5c12b0Sopenharmony_ci return -1; 38835e5c12b0Sopenharmony_ci } 38845e5c12b0Sopenharmony_ci 38855e5c12b0Sopenharmony_ci payload_addr += seg_size; 38865e5c12b0Sopenharmony_ci 38875e5c12b0Sopenharmony_ci DBG(1, "\tSparse: filling bitmap area at block offset 0x%08"PRIx64" len: %u\n", 38885e5c12b0Sopenharmony_ci payload_addr, get_sb(cp_payload)); 38895e5c12b0Sopenharmony_ci ret = dev_fill(NULL, payload_addr * F2FS_BLKSIZE, 38905e5c12b0Sopenharmony_ci get_sb(cp_payload) * F2FS_BLKSIZE); 38915e5c12b0Sopenharmony_ci if (ret) { 38925e5c12b0Sopenharmony_ci MSG(1, "\tError: While zeroing out the nat/sit bitmap area " 38935e5c12b0Sopenharmony_ci "on disk!!!\n"); 38945e5c12b0Sopenharmony_ci return -1; 38955e5c12b0Sopenharmony_ci } 38965e5c12b0Sopenharmony_ci return 0; 38975e5c12b0Sopenharmony_ci} 38985e5c12b0Sopenharmony_ci#else 38995e5c12b0Sopenharmony_ciint f2fs_sparse_initialize_meta(struct f2fs_sb_info *sbi) { return 0; } 39005e5c12b0Sopenharmony_ci#endif 3901