15e5c12b0Sopenharmony_ci/** 25e5c12b0Sopenharmony_ci * segment.c 35e5c12b0Sopenharmony_ci * 45e5c12b0Sopenharmony_ci * Many parts of codes are copied from Linux kernel/fs/f2fs. 55e5c12b0Sopenharmony_ci * 65e5c12b0Sopenharmony_ci * Copyright (C) 2015 Huawei Ltd. 75e5c12b0Sopenharmony_ci * Witten by: 85e5c12b0Sopenharmony_ci * Hou Pengyang <houpengyang@huawei.com> 95e5c12b0Sopenharmony_ci * Liu Shuoran <liushuoran@huawei.com> 105e5c12b0Sopenharmony_ci * Jaegeuk Kim <jaegeuk@kernel.org> 115e5c12b0Sopenharmony_ci * Copyright (c) 2020 Google Inc. 125e5c12b0Sopenharmony_ci * Robin Hsu <robinhsu@google.com> 135e5c12b0Sopenharmony_ci * : add sload compression support 145e5c12b0Sopenharmony_ci * 155e5c12b0Sopenharmony_ci * This program is free software; you can redistribute it and/or modify 165e5c12b0Sopenharmony_ci * it under the terms of the GNU General Public License version 2 as 175e5c12b0Sopenharmony_ci * published by the Free Software Foundation. 185e5c12b0Sopenharmony_ci */ 195e5c12b0Sopenharmony_ci#include "fsck.h" 205e5c12b0Sopenharmony_ci#include "node.h" 215e5c12b0Sopenharmony_ci#include "quotaio.h" 225e5c12b0Sopenharmony_ci 235e5c12b0Sopenharmony_ciint reserve_new_block(struct f2fs_sb_info *sbi, block_t *to, 245e5c12b0Sopenharmony_ci struct f2fs_summary *sum, int type, bool is_inode) 255e5c12b0Sopenharmony_ci{ 265e5c12b0Sopenharmony_ci struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 275e5c12b0Sopenharmony_ci struct seg_entry *se; 285e5c12b0Sopenharmony_ci u64 blkaddr, offset; 295e5c12b0Sopenharmony_ci u64 old_blkaddr = *to; 305e5c12b0Sopenharmony_ci bool is_node = IS_NODESEG(type); 315e5c12b0Sopenharmony_ci int left = 0; 325e5c12b0Sopenharmony_ci 335e5c12b0Sopenharmony_ci if (old_blkaddr == NULL_ADDR) { 345e5c12b0Sopenharmony_ci if (c.func == FSCK) { 355e5c12b0Sopenharmony_ci if (fsck->chk.valid_blk_cnt >= sbi->user_block_count) { 365e5c12b0Sopenharmony_ci ERR_MSG("Not enough space\n"); 375e5c12b0Sopenharmony_ci return -ENOSPC; 385e5c12b0Sopenharmony_ci } 395e5c12b0Sopenharmony_ci if (is_node && fsck->chk.valid_node_cnt >= 405e5c12b0Sopenharmony_ci sbi->total_valid_node_count) { 415e5c12b0Sopenharmony_ci ERR_MSG("Not enough space for node block\n"); 425e5c12b0Sopenharmony_ci return -ENOSPC; 435e5c12b0Sopenharmony_ci } 445e5c12b0Sopenharmony_ci } else { 455e5c12b0Sopenharmony_ci if (sbi->total_valid_block_count >= 465e5c12b0Sopenharmony_ci sbi->user_block_count) { 475e5c12b0Sopenharmony_ci ERR_MSG("Not enough space\n"); 485e5c12b0Sopenharmony_ci return -ENOSPC; 495e5c12b0Sopenharmony_ci } 505e5c12b0Sopenharmony_ci if (is_node && sbi->total_valid_node_count >= 515e5c12b0Sopenharmony_ci sbi->total_node_count) { 525e5c12b0Sopenharmony_ci ERR_MSG("Not enough space for node block\n"); 535e5c12b0Sopenharmony_ci return -ENOSPC; 545e5c12b0Sopenharmony_ci } 555e5c12b0Sopenharmony_ci } 565e5c12b0Sopenharmony_ci } 575e5c12b0Sopenharmony_ci 585e5c12b0Sopenharmony_ci blkaddr = SM_I(sbi)->main_blkaddr; 595e5c12b0Sopenharmony_ci 605e5c12b0Sopenharmony_ci if (sbi->raw_super->feature & cpu_to_le32(F2FS_FEATURE_RO)) { 615e5c12b0Sopenharmony_ci if (IS_NODESEG(type)) { 625e5c12b0Sopenharmony_ci type = CURSEG_HOT_NODE; 635e5c12b0Sopenharmony_ci blkaddr = __end_block_addr(sbi); 645e5c12b0Sopenharmony_ci left = 1; 655e5c12b0Sopenharmony_ci } else if (IS_DATASEG(type)) { 665e5c12b0Sopenharmony_ci type = CURSEG_HOT_DATA; 675e5c12b0Sopenharmony_ci blkaddr = SM_I(sbi)->main_blkaddr; 685e5c12b0Sopenharmony_ci left = 0; 695e5c12b0Sopenharmony_ci } 705e5c12b0Sopenharmony_ci } 715e5c12b0Sopenharmony_ci 725e5c12b0Sopenharmony_ci if (find_next_free_block(sbi, &blkaddr, left, type, false)) { 735e5c12b0Sopenharmony_ci ERR_MSG("Can't find free block"); 745e5c12b0Sopenharmony_ci ASSERT(0); 755e5c12b0Sopenharmony_ci } 765e5c12b0Sopenharmony_ci 775e5c12b0Sopenharmony_ci se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr)); 785e5c12b0Sopenharmony_ci offset = OFFSET_IN_SEG(sbi, blkaddr); 795e5c12b0Sopenharmony_ci se->type = type; 805e5c12b0Sopenharmony_ci se->valid_blocks++; 815e5c12b0Sopenharmony_ci f2fs_set_bit(offset, (char *)se->cur_valid_map); 825e5c12b0Sopenharmony_ci if (need_fsync_data_record(sbi)) { 835e5c12b0Sopenharmony_ci se->ckpt_type = type; 845e5c12b0Sopenharmony_ci se->ckpt_valid_blocks++; 855e5c12b0Sopenharmony_ci f2fs_set_bit(offset, (char *)se->ckpt_valid_map); 865e5c12b0Sopenharmony_ci } 875e5c12b0Sopenharmony_ci if (c.func == FSCK) { 885e5c12b0Sopenharmony_ci f2fs_set_main_bitmap(sbi, blkaddr, type); 895e5c12b0Sopenharmony_ci f2fs_set_sit_bitmap(sbi, blkaddr); 905e5c12b0Sopenharmony_ci } 915e5c12b0Sopenharmony_ci 925e5c12b0Sopenharmony_ci if (old_blkaddr == NULL_ADDR) { 935e5c12b0Sopenharmony_ci sbi->total_valid_block_count++; 945e5c12b0Sopenharmony_ci if (is_node) { 955e5c12b0Sopenharmony_ci sbi->total_valid_node_count++; 965e5c12b0Sopenharmony_ci if (is_inode) 975e5c12b0Sopenharmony_ci sbi->total_valid_inode_count++; 985e5c12b0Sopenharmony_ci } 995e5c12b0Sopenharmony_ci if (c.func == FSCK) { 1005e5c12b0Sopenharmony_ci fsck->chk.valid_blk_cnt++; 1015e5c12b0Sopenharmony_ci if (is_node) { 1025e5c12b0Sopenharmony_ci fsck->chk.valid_node_cnt++; 1035e5c12b0Sopenharmony_ci if (is_inode) 1045e5c12b0Sopenharmony_ci fsck->chk.valid_inode_cnt++; 1055e5c12b0Sopenharmony_ci } 1065e5c12b0Sopenharmony_ci } 1075e5c12b0Sopenharmony_ci } 1085e5c12b0Sopenharmony_ci se->dirty = 1; 1095e5c12b0Sopenharmony_ci 1105e5c12b0Sopenharmony_ci /* read/write SSA */ 1115e5c12b0Sopenharmony_ci *to = (block_t)blkaddr; 1125e5c12b0Sopenharmony_ci update_sum_entry(sbi, *to, sum); 1135e5c12b0Sopenharmony_ci 1145e5c12b0Sopenharmony_ci return 0; 1155e5c12b0Sopenharmony_ci} 1165e5c12b0Sopenharmony_ci 1175e5c12b0Sopenharmony_ciint new_data_block(struct f2fs_sb_info *sbi, void *block, 1185e5c12b0Sopenharmony_ci struct dnode_of_data *dn, int type) 1195e5c12b0Sopenharmony_ci{ 1205e5c12b0Sopenharmony_ci struct f2fs_super_block *sb = F2FS_RAW_SUPER(sbi); 1215e5c12b0Sopenharmony_ci struct f2fs_summary sum; 1225e5c12b0Sopenharmony_ci struct node_info ni; 1235e5c12b0Sopenharmony_ci unsigned int blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node); 1245e5c12b0Sopenharmony_ci int ret; 1255e5c12b0Sopenharmony_ci 1265e5c12b0Sopenharmony_ci if ((get_sb(feature) & cpu_to_le32(F2FS_FEATURE_RO)) && 1275e5c12b0Sopenharmony_ci type != CURSEG_HOT_DATA) 1285e5c12b0Sopenharmony_ci type = CURSEG_HOT_DATA; 1295e5c12b0Sopenharmony_ci 1305e5c12b0Sopenharmony_ci ASSERT(dn->node_blk); 1315e5c12b0Sopenharmony_ci memset(block, 0, BLOCK_SZ); 1325e5c12b0Sopenharmony_ci 1335e5c12b0Sopenharmony_ci get_node_info(sbi, dn->nid, &ni); 1345e5c12b0Sopenharmony_ci set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); 1355e5c12b0Sopenharmony_ci 1365e5c12b0Sopenharmony_ci dn->data_blkaddr = blkaddr; 1375e5c12b0Sopenharmony_ci ret = reserve_new_block(sbi, &dn->data_blkaddr, &sum, type, 0); 1385e5c12b0Sopenharmony_ci if (ret) { 1395e5c12b0Sopenharmony_ci c.alloc_failed = 1; 1405e5c12b0Sopenharmony_ci return ret; 1415e5c12b0Sopenharmony_ci } 1425e5c12b0Sopenharmony_ci 1435e5c12b0Sopenharmony_ci if (blkaddr == NULL_ADDR) 1445e5c12b0Sopenharmony_ci inc_inode_blocks(dn); 1455e5c12b0Sopenharmony_ci else if (blkaddr == NEW_ADDR) 1465e5c12b0Sopenharmony_ci dn->idirty = 1; 1475e5c12b0Sopenharmony_ci set_data_blkaddr(dn); 1485e5c12b0Sopenharmony_ci return 0; 1495e5c12b0Sopenharmony_ci} 1505e5c12b0Sopenharmony_ci 1515e5c12b0Sopenharmony_ciu64 f2fs_quota_size(struct quota_file *qf) 1525e5c12b0Sopenharmony_ci{ 1535e5c12b0Sopenharmony_ci struct node_info ni; 1545e5c12b0Sopenharmony_ci struct f2fs_node *inode; 1555e5c12b0Sopenharmony_ci u64 filesize; 1565e5c12b0Sopenharmony_ci 1575e5c12b0Sopenharmony_ci inode = (struct f2fs_node *) calloc(BLOCK_SZ, 1); 1585e5c12b0Sopenharmony_ci ASSERT(inode); 1595e5c12b0Sopenharmony_ci 1605e5c12b0Sopenharmony_ci /* Read inode */ 1615e5c12b0Sopenharmony_ci get_node_info(qf->sbi, qf->ino, &ni); 1625e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 1635e5c12b0Sopenharmony_ci ASSERT(S_ISREG(le16_to_cpu(inode->i.i_mode))); 1645e5c12b0Sopenharmony_ci 1655e5c12b0Sopenharmony_ci filesize = le64_to_cpu(inode->i.i_size); 1665e5c12b0Sopenharmony_ci free(inode); 1675e5c12b0Sopenharmony_ci return filesize; 1685e5c12b0Sopenharmony_ci} 1695e5c12b0Sopenharmony_ci 1705e5c12b0Sopenharmony_ciu64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 1715e5c12b0Sopenharmony_ci u64 count, pgoff_t offset) 1725e5c12b0Sopenharmony_ci{ 1735e5c12b0Sopenharmony_ci struct dnode_of_data dn; 1745e5c12b0Sopenharmony_ci struct node_info ni; 1755e5c12b0Sopenharmony_ci struct f2fs_node *inode; 1765e5c12b0Sopenharmony_ci char *blk_buffer; 1775e5c12b0Sopenharmony_ci u64 filesize; 1785e5c12b0Sopenharmony_ci u64 off_in_blk; 1795e5c12b0Sopenharmony_ci u64 len_in_blk; 1805e5c12b0Sopenharmony_ci u64 read_count; 1815e5c12b0Sopenharmony_ci u64 remained_blkentries; 1825e5c12b0Sopenharmony_ci block_t blkaddr; 1835e5c12b0Sopenharmony_ci void *index_node = NULL; 1845e5c12b0Sopenharmony_ci 1855e5c12b0Sopenharmony_ci memset(&dn, 0, sizeof(dn)); 1865e5c12b0Sopenharmony_ci 1875e5c12b0Sopenharmony_ci /* Memory allocation for block buffer and inode. */ 1885e5c12b0Sopenharmony_ci blk_buffer = calloc(BLOCK_SZ, 2); 1895e5c12b0Sopenharmony_ci ASSERT(blk_buffer); 1905e5c12b0Sopenharmony_ci inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ); 1915e5c12b0Sopenharmony_ci 1925e5c12b0Sopenharmony_ci /* Read inode */ 1935e5c12b0Sopenharmony_ci get_node_info(sbi, ino, &ni); 1945e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 1955e5c12b0Sopenharmony_ci ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 1965e5c12b0Sopenharmony_ci ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 1975e5c12b0Sopenharmony_ci 1985e5c12b0Sopenharmony_ci /* Adjust count with file length. */ 1995e5c12b0Sopenharmony_ci filesize = le64_to_cpu(inode->i.i_size); 2005e5c12b0Sopenharmony_ci if (offset > filesize) 2015e5c12b0Sopenharmony_ci count = 0; 2025e5c12b0Sopenharmony_ci else if (count + offset > filesize) 2035e5c12b0Sopenharmony_ci count = filesize - offset; 2045e5c12b0Sopenharmony_ci 2055e5c12b0Sopenharmony_ci /* Main loop for file blocks */ 2065e5c12b0Sopenharmony_ci read_count = remained_blkentries = 0; 2075e5c12b0Sopenharmony_ci while (count > 0) { 2085e5c12b0Sopenharmony_ci if (remained_blkentries == 0) { 2095e5c12b0Sopenharmony_ci set_new_dnode(&dn, inode, NULL, ino); 2105e5c12b0Sopenharmony_ci get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset), 2115e5c12b0Sopenharmony_ci LOOKUP_NODE); 2125e5c12b0Sopenharmony_ci if (index_node) 2135e5c12b0Sopenharmony_ci free(index_node); 2145e5c12b0Sopenharmony_ci index_node = (dn.node_blk == dn.inode_blk) ? 2155e5c12b0Sopenharmony_ci NULL : dn.node_blk; 2165e5c12b0Sopenharmony_ci remained_blkentries = ADDRS_PER_PAGE(sbi, 2175e5c12b0Sopenharmony_ci dn.node_blk, dn.inode_blk); 2185e5c12b0Sopenharmony_ci } 2195e5c12b0Sopenharmony_ci ASSERT(remained_blkentries > 0); 2205e5c12b0Sopenharmony_ci 2215e5c12b0Sopenharmony_ci blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node); 2225e5c12b0Sopenharmony_ci if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) 2235e5c12b0Sopenharmony_ci break; 2245e5c12b0Sopenharmony_ci 2255e5c12b0Sopenharmony_ci off_in_blk = offset % BLOCK_SZ; 2265e5c12b0Sopenharmony_ci len_in_blk = BLOCK_SZ - off_in_blk; 2275e5c12b0Sopenharmony_ci if (len_in_blk > count) 2285e5c12b0Sopenharmony_ci len_in_blk = count; 2295e5c12b0Sopenharmony_ci 2305e5c12b0Sopenharmony_ci /* Read data from single block. */ 2315e5c12b0Sopenharmony_ci if (len_in_blk < BLOCK_SZ) { 2325e5c12b0Sopenharmony_ci ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0); 2335e5c12b0Sopenharmony_ci memcpy(buffer, blk_buffer + off_in_blk, len_in_blk); 2345e5c12b0Sopenharmony_ci } else { 2355e5c12b0Sopenharmony_ci /* Direct read */ 2365e5c12b0Sopenharmony_ci ASSERT(dev_read_block(buffer, blkaddr) >= 0); 2375e5c12b0Sopenharmony_ci } 2385e5c12b0Sopenharmony_ci 2395e5c12b0Sopenharmony_ci offset += len_in_blk; 2405e5c12b0Sopenharmony_ci count -= len_in_blk; 2415e5c12b0Sopenharmony_ci buffer += len_in_blk; 2425e5c12b0Sopenharmony_ci read_count += len_in_blk; 2435e5c12b0Sopenharmony_ci 2445e5c12b0Sopenharmony_ci dn.ofs_in_node++; 2455e5c12b0Sopenharmony_ci remained_blkentries--; 2465e5c12b0Sopenharmony_ci } 2475e5c12b0Sopenharmony_ci if (index_node) 2485e5c12b0Sopenharmony_ci free(index_node); 2495e5c12b0Sopenharmony_ci free(blk_buffer); 2505e5c12b0Sopenharmony_ci 2515e5c12b0Sopenharmony_ci return read_count; 2525e5c12b0Sopenharmony_ci} 2535e5c12b0Sopenharmony_ci 2545e5c12b0Sopenharmony_ci/* 2555e5c12b0Sopenharmony_ci * Do not call this function directly. Instead, call one of the following: 2565e5c12b0Sopenharmony_ci * u64 f2fs_write(); 2575e5c12b0Sopenharmony_ci * u64 f2fs_write_compress_data(); 2585e5c12b0Sopenharmony_ci * u64 f2fs_write_addrtag(); 2595e5c12b0Sopenharmony_ci */ 2605e5c12b0Sopenharmony_cistatic u64 f2fs_write_ex(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 2615e5c12b0Sopenharmony_ci u64 count, pgoff_t offset, enum wr_addr_type addr_type) 2625e5c12b0Sopenharmony_ci{ 2635e5c12b0Sopenharmony_ci struct dnode_of_data dn; 2645e5c12b0Sopenharmony_ci struct node_info ni; 2655e5c12b0Sopenharmony_ci struct f2fs_node *inode; 2665e5c12b0Sopenharmony_ci char *blk_buffer; 2675e5c12b0Sopenharmony_ci u64 off_in_blk; 2685e5c12b0Sopenharmony_ci u64 len_in_blk; 2695e5c12b0Sopenharmony_ci u64 written_count; 2705e5c12b0Sopenharmony_ci u64 remained_blkentries; 2715e5c12b0Sopenharmony_ci block_t blkaddr; 2725e5c12b0Sopenharmony_ci void* index_node = NULL; 2735e5c12b0Sopenharmony_ci int idirty = 0; 2745e5c12b0Sopenharmony_ci int err; 2755e5c12b0Sopenharmony_ci bool has_data = (addr_type == WR_NORMAL 2765e5c12b0Sopenharmony_ci || addr_type == WR_COMPRESS_DATA); 2775e5c12b0Sopenharmony_ci 2785e5c12b0Sopenharmony_ci if (count == 0) 2795e5c12b0Sopenharmony_ci return 0; 2805e5c12b0Sopenharmony_ci 2815e5c12b0Sopenharmony_ci /* 2825e5c12b0Sopenharmony_ci * Enforce calling from f2fs_write(), f2fs_write_compress_data(), 2835e5c12b0Sopenharmony_ci * and f2fs_write_addrtag(). Beside, check if is properly called. 2845e5c12b0Sopenharmony_ci */ 2855e5c12b0Sopenharmony_ci ASSERT((!has_data && buffer == NULL) || (has_data && buffer != NULL)); 2865e5c12b0Sopenharmony_ci if (addr_type != WR_NORMAL) 2875e5c12b0Sopenharmony_ci ASSERT(offset % F2FS_BLKSIZE == 0); /* block boundary only */ 2885e5c12b0Sopenharmony_ci 2895e5c12b0Sopenharmony_ci /* Memory allocation for block buffer and inode. */ 2905e5c12b0Sopenharmony_ci blk_buffer = calloc(BLOCK_SZ, 2); 2915e5c12b0Sopenharmony_ci ASSERT(blk_buffer); 2925e5c12b0Sopenharmony_ci inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ); 2935e5c12b0Sopenharmony_ci 2945e5c12b0Sopenharmony_ci /* Read inode */ 2955e5c12b0Sopenharmony_ci get_node_info(sbi, ino, &ni); 2965e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 2975e5c12b0Sopenharmony_ci ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 2985e5c12b0Sopenharmony_ci ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 2995e5c12b0Sopenharmony_ci 3005e5c12b0Sopenharmony_ci /* Main loop for file blocks */ 3015e5c12b0Sopenharmony_ci written_count = remained_blkentries = 0; 3025e5c12b0Sopenharmony_ci while (count > 0) { 3035e5c12b0Sopenharmony_ci if (remained_blkentries == 0) { 3045e5c12b0Sopenharmony_ci set_new_dnode(&dn, inode, NULL, ino); 3055e5c12b0Sopenharmony_ci err = get_dnode_of_data(sbi, &dn, 3065e5c12b0Sopenharmony_ci F2FS_BYTES_TO_BLK(offset), ALLOC_NODE); 3075e5c12b0Sopenharmony_ci if (err) 3085e5c12b0Sopenharmony_ci break; 3095e5c12b0Sopenharmony_ci idirty |= dn.idirty; 3105e5c12b0Sopenharmony_ci free(index_node); 3115e5c12b0Sopenharmony_ci index_node = (dn.node_blk == dn.inode_blk) ? 3125e5c12b0Sopenharmony_ci NULL : dn.node_blk; 3135e5c12b0Sopenharmony_ci remained_blkentries = ADDRS_PER_PAGE(sbi, 3145e5c12b0Sopenharmony_ci dn.node_blk, dn.inode_blk) - 3155e5c12b0Sopenharmony_ci dn.ofs_in_node; 3165e5c12b0Sopenharmony_ci } 3175e5c12b0Sopenharmony_ci ASSERT(remained_blkentries > 0); 3185e5c12b0Sopenharmony_ci 3195e5c12b0Sopenharmony_ci if (!has_data) { 3205e5c12b0Sopenharmony_ci dn.data_blkaddr = addr_type; 3215e5c12b0Sopenharmony_ci set_data_blkaddr(&dn); 3225e5c12b0Sopenharmony_ci idirty |= dn.idirty; 3235e5c12b0Sopenharmony_ci if (dn.ndirty) 3245e5c12b0Sopenharmony_ci ASSERT(dev_write_block(dn.node_blk, 3255e5c12b0Sopenharmony_ci dn.node_blkaddr) >= 0); 3265e5c12b0Sopenharmony_ci written_count = 0; 3275e5c12b0Sopenharmony_ci break; 3285e5c12b0Sopenharmony_ci } 3295e5c12b0Sopenharmony_ci 3305e5c12b0Sopenharmony_ci blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node); 3315e5c12b0Sopenharmony_ci if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) { 3325e5c12b0Sopenharmony_ci err = new_data_block(sbi, blk_buffer, 3335e5c12b0Sopenharmony_ci &dn, CURSEG_WARM_DATA); 3345e5c12b0Sopenharmony_ci if (err) 3355e5c12b0Sopenharmony_ci break; 3365e5c12b0Sopenharmony_ci blkaddr = dn.data_blkaddr; 3375e5c12b0Sopenharmony_ci idirty |= dn.idirty; 3385e5c12b0Sopenharmony_ci } 3395e5c12b0Sopenharmony_ci 3405e5c12b0Sopenharmony_ci off_in_blk = offset % BLOCK_SZ; 3415e5c12b0Sopenharmony_ci len_in_blk = BLOCK_SZ - off_in_blk; 3425e5c12b0Sopenharmony_ci if (len_in_blk > count) 3435e5c12b0Sopenharmony_ci len_in_blk = count; 3445e5c12b0Sopenharmony_ci 3455e5c12b0Sopenharmony_ci /* Write data to single block. */ 3465e5c12b0Sopenharmony_ci if (len_in_blk < BLOCK_SZ) { 3475e5c12b0Sopenharmony_ci ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0); 3485e5c12b0Sopenharmony_ci memcpy(blk_buffer + off_in_blk, buffer, len_in_blk); 3495e5c12b0Sopenharmony_ci ASSERT(dev_write_block(blk_buffer, blkaddr) >= 0); 3505e5c12b0Sopenharmony_ci } else { 3515e5c12b0Sopenharmony_ci /* Direct write */ 3525e5c12b0Sopenharmony_ci ASSERT(dev_write_block(buffer, blkaddr) >= 0); 3535e5c12b0Sopenharmony_ci } 3545e5c12b0Sopenharmony_ci 3555e5c12b0Sopenharmony_ci offset += len_in_blk; 3565e5c12b0Sopenharmony_ci count -= len_in_blk; 3575e5c12b0Sopenharmony_ci buffer += len_in_blk; 3585e5c12b0Sopenharmony_ci written_count += len_in_blk; 3595e5c12b0Sopenharmony_ci 3605e5c12b0Sopenharmony_ci dn.ofs_in_node++; 3615e5c12b0Sopenharmony_ci if ((--remained_blkentries == 0 || count == 0) && (dn.ndirty)) 3625e5c12b0Sopenharmony_ci ASSERT(dev_write_block(dn.node_blk, dn.node_blkaddr) 3635e5c12b0Sopenharmony_ci >= 0); 3645e5c12b0Sopenharmony_ci } 3655e5c12b0Sopenharmony_ci if (addr_type == WR_NORMAL && offset > le64_to_cpu(inode->i.i_size)) { 3665e5c12b0Sopenharmony_ci inode->i.i_size = cpu_to_le64(offset); 3675e5c12b0Sopenharmony_ci idirty = 1; 3685e5c12b0Sopenharmony_ci } 3695e5c12b0Sopenharmony_ci if (idirty) { 3705e5c12b0Sopenharmony_ci ASSERT(inode == dn.inode_blk); 3715e5c12b0Sopenharmony_ci ASSERT(write_inode(inode, ni.blk_addr) >= 0); 3725e5c12b0Sopenharmony_ci } 3735e5c12b0Sopenharmony_ci 3745e5c12b0Sopenharmony_ci free(index_node); 3755e5c12b0Sopenharmony_ci free(blk_buffer); 3765e5c12b0Sopenharmony_ci 3775e5c12b0Sopenharmony_ci return written_count; 3785e5c12b0Sopenharmony_ci} 3795e5c12b0Sopenharmony_ci 3805e5c12b0Sopenharmony_ciu64 f2fs_write(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 3815e5c12b0Sopenharmony_ci u64 count, pgoff_t offset) 3825e5c12b0Sopenharmony_ci{ 3835e5c12b0Sopenharmony_ci return f2fs_write_ex(sbi, ino, buffer, count, offset, WR_NORMAL); 3845e5c12b0Sopenharmony_ci} 3855e5c12b0Sopenharmony_ci 3865e5c12b0Sopenharmony_ciu64 f2fs_write_compress_data(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 3875e5c12b0Sopenharmony_ci u64 count, pgoff_t offset) 3885e5c12b0Sopenharmony_ci{ 3895e5c12b0Sopenharmony_ci return f2fs_write_ex(sbi, ino, buffer, count, offset, WR_COMPRESS_DATA); 3905e5c12b0Sopenharmony_ci} 3915e5c12b0Sopenharmony_ci 3925e5c12b0Sopenharmony_ciu64 f2fs_write_addrtag(struct f2fs_sb_info *sbi, nid_t ino, pgoff_t offset, 3935e5c12b0Sopenharmony_ci unsigned int addrtag) 3945e5c12b0Sopenharmony_ci{ 3955e5c12b0Sopenharmony_ci ASSERT(addrtag == COMPRESS_ADDR || addrtag == NEW_ADDR 3965e5c12b0Sopenharmony_ci || addrtag == NULL_ADDR); 3975e5c12b0Sopenharmony_ci return f2fs_write_ex(sbi, ino, NULL, F2FS_BLKSIZE, offset, addrtag); 3985e5c12b0Sopenharmony_ci} 3995e5c12b0Sopenharmony_ci 4005e5c12b0Sopenharmony_ci/* This function updates only inode->i.i_size */ 4015e5c12b0Sopenharmony_civoid f2fs_filesize_update(struct f2fs_sb_info *sbi, nid_t ino, u64 filesize) 4025e5c12b0Sopenharmony_ci{ 4035e5c12b0Sopenharmony_ci struct node_info ni; 4045e5c12b0Sopenharmony_ci struct f2fs_node *inode; 4055e5c12b0Sopenharmony_ci 4065e5c12b0Sopenharmony_ci inode = calloc(BLOCK_SZ, 1); 4075e5c12b0Sopenharmony_ci ASSERT(inode); 4085e5c12b0Sopenharmony_ci get_node_info(sbi, ino, &ni); 4095e5c12b0Sopenharmony_ci 4105e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 4115e5c12b0Sopenharmony_ci ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 4125e5c12b0Sopenharmony_ci ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 4135e5c12b0Sopenharmony_ci 4145e5c12b0Sopenharmony_ci inode->i.i_size = cpu_to_le64(filesize); 4155e5c12b0Sopenharmony_ci 4165e5c12b0Sopenharmony_ci ASSERT(write_inode(inode, ni.blk_addr) >= 0); 4175e5c12b0Sopenharmony_ci free(inode); 4185e5c12b0Sopenharmony_ci} 4195e5c12b0Sopenharmony_ci 4205e5c12b0Sopenharmony_ci#define MAX_BULKR_RETRY 5 4215e5c12b0Sopenharmony_ciint bulkread(int fd, void *rbuf, size_t rsize, bool *eof) 4225e5c12b0Sopenharmony_ci{ 4235e5c12b0Sopenharmony_ci int n = 0; 4245e5c12b0Sopenharmony_ci int retry = MAX_BULKR_RETRY; 4255e5c12b0Sopenharmony_ci int cur; 4265e5c12b0Sopenharmony_ci 4275e5c12b0Sopenharmony_ci if (!rsize) 4285e5c12b0Sopenharmony_ci return 0; 4295e5c12b0Sopenharmony_ci 4305e5c12b0Sopenharmony_ci if (eof != NULL) 4315e5c12b0Sopenharmony_ci *eof = false; 4325e5c12b0Sopenharmony_ci while (rsize && (cur = read(fd, rbuf, rsize)) != 0) { 4335e5c12b0Sopenharmony_ci if (cur == -1) { 4345e5c12b0Sopenharmony_ci if (errno == EINTR && retry--) 4355e5c12b0Sopenharmony_ci continue; 4365e5c12b0Sopenharmony_ci return -1; 4375e5c12b0Sopenharmony_ci } 4385e5c12b0Sopenharmony_ci retry = MAX_BULKR_RETRY; 4395e5c12b0Sopenharmony_ci 4405e5c12b0Sopenharmony_ci rsize -= cur; 4415e5c12b0Sopenharmony_ci n += cur; 4425e5c12b0Sopenharmony_ci } 4435e5c12b0Sopenharmony_ci if (eof != NULL) 4445e5c12b0Sopenharmony_ci *eof = (cur == 0); 4455e5c12b0Sopenharmony_ci return n; 4465e5c12b0Sopenharmony_ci} 4475e5c12b0Sopenharmony_ci 4485e5c12b0Sopenharmony_ciu64 f2fs_fix_mutable(struct f2fs_sb_info *sbi, nid_t ino, pgoff_t offset, 4495e5c12b0Sopenharmony_ci unsigned int compressed) 4505e5c12b0Sopenharmony_ci{ 4515e5c12b0Sopenharmony_ci unsigned int i; 4525e5c12b0Sopenharmony_ci u64 wlen; 4535e5c12b0Sopenharmony_ci 4545e5c12b0Sopenharmony_ci if (c.compress.readonly) 4555e5c12b0Sopenharmony_ci return 0; 4565e5c12b0Sopenharmony_ci 4575e5c12b0Sopenharmony_ci for (i = 0; i < compressed - 1; i++) { 4585e5c12b0Sopenharmony_ci wlen = f2fs_write_addrtag(sbi, ino, 4595e5c12b0Sopenharmony_ci offset + (i << F2FS_BLKSIZE_BITS), NEW_ADDR); 4605e5c12b0Sopenharmony_ci if (wlen) 4615e5c12b0Sopenharmony_ci return wlen; 4625e5c12b0Sopenharmony_ci } 4635e5c12b0Sopenharmony_ci return 0; 4645e5c12b0Sopenharmony_ci} 4655e5c12b0Sopenharmony_ci 4665e5c12b0Sopenharmony_cistatic inline int is_consecutive(u32 prev_addr, u32 cur_addr) 4675e5c12b0Sopenharmony_ci{ 4685e5c12b0Sopenharmony_ci if (is_valid_data_blkaddr(cur_addr) && (cur_addr == prev_addr + 1)) 4695e5c12b0Sopenharmony_ci return 1; 4705e5c12b0Sopenharmony_ci return 0; 4715e5c12b0Sopenharmony_ci} 4725e5c12b0Sopenharmony_ci 4735e5c12b0Sopenharmony_cistatic inline void copy_extent_info(struct extent_info *t_ext, 4745e5c12b0Sopenharmony_ci struct extent_info *s_ext) 4755e5c12b0Sopenharmony_ci{ 4765e5c12b0Sopenharmony_ci t_ext->fofs = s_ext->fofs; 4775e5c12b0Sopenharmony_ci t_ext->blk = s_ext->blk; 4785e5c12b0Sopenharmony_ci t_ext->len = s_ext->len; 4795e5c12b0Sopenharmony_ci} 4805e5c12b0Sopenharmony_ci 4815e5c12b0Sopenharmony_cistatic inline void update_extent_info(struct f2fs_node *inode, 4825e5c12b0Sopenharmony_ci struct extent_info *ext) 4835e5c12b0Sopenharmony_ci{ 4845e5c12b0Sopenharmony_ci inode->i.i_ext.fofs = cpu_to_le32(ext->fofs); 4855e5c12b0Sopenharmony_ci inode->i.i_ext.blk_addr = cpu_to_le32(ext->blk); 4865e5c12b0Sopenharmony_ci inode->i.i_ext.len = cpu_to_le32(ext->len); 4875e5c12b0Sopenharmony_ci} 4885e5c12b0Sopenharmony_ci 4895e5c12b0Sopenharmony_cistatic void update_largest_extent(struct f2fs_sb_info *sbi, nid_t ino) 4905e5c12b0Sopenharmony_ci{ 4915e5c12b0Sopenharmony_ci struct dnode_of_data dn; 4925e5c12b0Sopenharmony_ci struct node_info ni; 4935e5c12b0Sopenharmony_ci struct f2fs_node *inode; 4945e5c12b0Sopenharmony_ci u32 blkaddr, prev_blkaddr, cur_blk = 0, end_blk; 4955e5c12b0Sopenharmony_ci struct extent_info largest_ext, cur_ext; 4965e5c12b0Sopenharmony_ci u64 remained_blkentries = 0; 4975e5c12b0Sopenharmony_ci u32 cluster_size; 4985e5c12b0Sopenharmony_ci int count; 4995e5c12b0Sopenharmony_ci void *index_node = NULL; 5005e5c12b0Sopenharmony_ci 5015e5c12b0Sopenharmony_ci memset(&dn, 0, sizeof(dn)); 5025e5c12b0Sopenharmony_ci largest_ext.len = cur_ext.len = 0; 5035e5c12b0Sopenharmony_ci 5045e5c12b0Sopenharmony_ci inode = (struct f2fs_node *) calloc(BLOCK_SZ, 1); 5055e5c12b0Sopenharmony_ci ASSERT(inode); 5065e5c12b0Sopenharmony_ci 5075e5c12b0Sopenharmony_ci /* Read inode info */ 5085e5c12b0Sopenharmony_ci get_node_info(sbi, ino, &ni); 5095e5c12b0Sopenharmony_ci ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 5105e5c12b0Sopenharmony_ci cluster_size = 1 << inode->i.i_log_cluster_size; 5115e5c12b0Sopenharmony_ci 5125e5c12b0Sopenharmony_ci if (inode->i.i_inline & F2FS_INLINE_DATA) 5135e5c12b0Sopenharmony_ci goto exit; 5145e5c12b0Sopenharmony_ci 5155e5c12b0Sopenharmony_ci end_blk = f2fs_max_file_offset(&inode->i) >> F2FS_BLKSIZE_BITS; 5165e5c12b0Sopenharmony_ci 5175e5c12b0Sopenharmony_ci while (cur_blk <= end_blk) { 5185e5c12b0Sopenharmony_ci if (remained_blkentries == 0) { 5195e5c12b0Sopenharmony_ci set_new_dnode(&dn, inode, NULL, ino); 5205e5c12b0Sopenharmony_ci get_dnode_of_data(sbi, &dn, cur_blk, LOOKUP_NODE); 5215e5c12b0Sopenharmony_ci if (index_node) 5225e5c12b0Sopenharmony_ci free(index_node); 5235e5c12b0Sopenharmony_ci index_node = (dn.node_blk == dn.inode_blk) ? 5245e5c12b0Sopenharmony_ci NULL : dn.node_blk; 5255e5c12b0Sopenharmony_ci remained_blkentries = ADDRS_PER_PAGE(sbi, 5265e5c12b0Sopenharmony_ci dn.node_blk, dn.inode_blk); 5275e5c12b0Sopenharmony_ci } 5285e5c12b0Sopenharmony_ci ASSERT(remained_blkentries > 0); 5295e5c12b0Sopenharmony_ci 5305e5c12b0Sopenharmony_ci blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node); 5315e5c12b0Sopenharmony_ci if (cur_ext.len > 0) { 5325e5c12b0Sopenharmony_ci if (is_consecutive(prev_blkaddr, blkaddr)) 5335e5c12b0Sopenharmony_ci cur_ext.len++; 5345e5c12b0Sopenharmony_ci else { 5355e5c12b0Sopenharmony_ci if (cur_ext.len > largest_ext.len) 5365e5c12b0Sopenharmony_ci copy_extent_info(&largest_ext, 5375e5c12b0Sopenharmony_ci &cur_ext); 5385e5c12b0Sopenharmony_ci cur_ext.len = 0; 5395e5c12b0Sopenharmony_ci } 5405e5c12b0Sopenharmony_ci } 5415e5c12b0Sopenharmony_ci 5425e5c12b0Sopenharmony_ci if (cur_ext.len == 0 && is_valid_data_blkaddr(blkaddr)) { 5435e5c12b0Sopenharmony_ci cur_ext.fofs = cur_blk; 5445e5c12b0Sopenharmony_ci cur_ext.len = 1; 5455e5c12b0Sopenharmony_ci cur_ext.blk = blkaddr; 5465e5c12b0Sopenharmony_ci } 5475e5c12b0Sopenharmony_ci 5485e5c12b0Sopenharmony_ci prev_blkaddr = blkaddr; 5495e5c12b0Sopenharmony_ci count = blkaddr == COMPRESS_ADDR ? cluster_size : 1; 5505e5c12b0Sopenharmony_ci cur_blk += count; 5515e5c12b0Sopenharmony_ci dn.ofs_in_node += count; 5525e5c12b0Sopenharmony_ci remained_blkentries -= count; 5535e5c12b0Sopenharmony_ci } 5545e5c12b0Sopenharmony_ci 5555e5c12b0Sopenharmony_ciexit: 5565e5c12b0Sopenharmony_ci if (cur_ext.len > largest_ext.len) 5575e5c12b0Sopenharmony_ci copy_extent_info(&largest_ext, &cur_ext); 5585e5c12b0Sopenharmony_ci if (largest_ext.len > 0) { 5595e5c12b0Sopenharmony_ci update_extent_info(inode, &largest_ext); 5605e5c12b0Sopenharmony_ci ASSERT(write_inode(inode, ni.blk_addr) >= 0); 5615e5c12b0Sopenharmony_ci } 5625e5c12b0Sopenharmony_ci 5635e5c12b0Sopenharmony_ci if (index_node) 5645e5c12b0Sopenharmony_ci free(index_node); 5655e5c12b0Sopenharmony_ci free(inode); 5665e5c12b0Sopenharmony_ci} 5675e5c12b0Sopenharmony_ci 5685e5c12b0Sopenharmony_ciint f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de) 5695e5c12b0Sopenharmony_ci{ 5705e5c12b0Sopenharmony_ci int fd, n = -1; 5715e5c12b0Sopenharmony_ci pgoff_t off = 0; 5725e5c12b0Sopenharmony_ci u8 buffer[BLOCK_SZ]; 5735e5c12b0Sopenharmony_ci struct node_info ni; 5745e5c12b0Sopenharmony_ci struct f2fs_node *node_blk; 5755e5c12b0Sopenharmony_ci 5765e5c12b0Sopenharmony_ci if (de->ino == 0) 5775e5c12b0Sopenharmony_ci return -1; 5785e5c12b0Sopenharmony_ci 5795e5c12b0Sopenharmony_ci if (de->from_devino) { 5805e5c12b0Sopenharmony_ci struct hardlink_cache_entry *found_hardlink; 5815e5c12b0Sopenharmony_ci 5825e5c12b0Sopenharmony_ci found_hardlink = f2fs_search_hardlink(sbi, de); 5835e5c12b0Sopenharmony_ci if (found_hardlink && found_hardlink->to_ino && 5845e5c12b0Sopenharmony_ci found_hardlink->nbuild) 5855e5c12b0Sopenharmony_ci return 0; 5865e5c12b0Sopenharmony_ci 5875e5c12b0Sopenharmony_ci found_hardlink->nbuild++; 5885e5c12b0Sopenharmony_ci } 5895e5c12b0Sopenharmony_ci 5905e5c12b0Sopenharmony_ci fd = open(de->full_path, O_RDONLY); 5915e5c12b0Sopenharmony_ci if (fd < 0) { 5925e5c12b0Sopenharmony_ci MSG(0, "Skip: Fail to open %s\n", de->full_path); 5935e5c12b0Sopenharmony_ci return -1; 5945e5c12b0Sopenharmony_ci } 5955e5c12b0Sopenharmony_ci 5965e5c12b0Sopenharmony_ci /* inline_data support */ 5975e5c12b0Sopenharmony_ci if (de->size <= DEF_MAX_INLINE_DATA) { 5985e5c12b0Sopenharmony_ci int ret; 5995e5c12b0Sopenharmony_ci 6005e5c12b0Sopenharmony_ci get_node_info(sbi, de->ino, &ni); 6015e5c12b0Sopenharmony_ci 6025e5c12b0Sopenharmony_ci node_blk = calloc(BLOCK_SZ, 1); 6035e5c12b0Sopenharmony_ci ASSERT(node_blk); 6045e5c12b0Sopenharmony_ci 6055e5c12b0Sopenharmony_ci ret = dev_read_block(node_blk, ni.blk_addr); 6065e5c12b0Sopenharmony_ci ASSERT(ret >= 0); 6075e5c12b0Sopenharmony_ci 6085e5c12b0Sopenharmony_ci node_blk->i.i_inline |= F2FS_INLINE_DATA; 6095e5c12b0Sopenharmony_ci node_blk->i.i_inline |= F2FS_DATA_EXIST; 6105e5c12b0Sopenharmony_ci 6115e5c12b0Sopenharmony_ci if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) { 6125e5c12b0Sopenharmony_ci node_blk->i.i_inline |= F2FS_EXTRA_ATTR; 6135e5c12b0Sopenharmony_ci node_blk->i.i_extra_isize = 6145e5c12b0Sopenharmony_ci cpu_to_le16(calc_extra_isize()); 6155e5c12b0Sopenharmony_ci } 6165e5c12b0Sopenharmony_ci n = read(fd, buffer, BLOCK_SZ); 6175e5c12b0Sopenharmony_ci ASSERT((unsigned long)n == de->size); 6185e5c12b0Sopenharmony_ci memcpy(inline_data_addr(node_blk), buffer, de->size); 6195e5c12b0Sopenharmony_ci node_blk->i.i_size = cpu_to_le64(de->size); 6205e5c12b0Sopenharmony_ci ASSERT(write_inode(node_blk, ni.blk_addr) >= 0); 6215e5c12b0Sopenharmony_ci free(node_blk); 6225e5c12b0Sopenharmony_ci#ifdef WITH_SLOAD 6235e5c12b0Sopenharmony_ci } else if (c.func == SLOAD && c.compress.enabled && 6245e5c12b0Sopenharmony_ci c.compress.filter_ops->filter(de->full_path)) { 6255e5c12b0Sopenharmony_ci bool eof = false; 6265e5c12b0Sopenharmony_ci u8 *rbuf = c.compress.cc.rbuf; 6275e5c12b0Sopenharmony_ci unsigned int cblocks = 0; 6285e5c12b0Sopenharmony_ci 6295e5c12b0Sopenharmony_ci node_blk = calloc(BLOCK_SZ, 1); 6305e5c12b0Sopenharmony_ci ASSERT(node_blk); 6315e5c12b0Sopenharmony_ci 6325e5c12b0Sopenharmony_ci /* read inode */ 6335e5c12b0Sopenharmony_ci get_node_info(sbi, de->ino, &ni); 6345e5c12b0Sopenharmony_ci ASSERT(dev_read_block(node_blk, ni.blk_addr) >= 0); 6355e5c12b0Sopenharmony_ci /* update inode meta */ 6365e5c12b0Sopenharmony_ci node_blk->i.i_compress_algrithm = c.compress.alg; 6375e5c12b0Sopenharmony_ci node_blk->i.i_log_cluster_size = 6385e5c12b0Sopenharmony_ci c.compress.cc.log_cluster_size; 6395e5c12b0Sopenharmony_ci node_blk->i.i_flags = cpu_to_le32(F2FS_COMPR_FL); 6405e5c12b0Sopenharmony_ci if (c.compress.readonly) 6415e5c12b0Sopenharmony_ci node_blk->i.i_inline |= F2FS_COMPRESS_RELEASED; 6425e5c12b0Sopenharmony_ci ASSERT(write_inode(node_blk, ni.blk_addr) >= 0); 6435e5c12b0Sopenharmony_ci 6445e5c12b0Sopenharmony_ci while (!eof && (n = bulkread(fd, rbuf, c.compress.cc.rlen, 6455e5c12b0Sopenharmony_ci &eof)) > 0) { 6465e5c12b0Sopenharmony_ci int ret = c.compress.ops->compress(&c.compress.cc); 6475e5c12b0Sopenharmony_ci u64 wlen; 6485e5c12b0Sopenharmony_ci u32 csize = ALIGN_UP(c.compress.cc.clen + 6495e5c12b0Sopenharmony_ci COMPRESS_HEADER_SIZE, BLOCK_SZ); 6505e5c12b0Sopenharmony_ci unsigned int cur_cblk; 6515e5c12b0Sopenharmony_ci 6525e5c12b0Sopenharmony_ci if (ret || n < c.compress.cc.rlen || 6535e5c12b0Sopenharmony_ci n < (int)(csize + BLOCK_SZ * 6545e5c12b0Sopenharmony_ci c.compress.min_blocks)) { 6555e5c12b0Sopenharmony_ci wlen = f2fs_write(sbi, de->ino, rbuf, n, off); 6565e5c12b0Sopenharmony_ci ASSERT((int)wlen == n); 6575e5c12b0Sopenharmony_ci } else { 6585e5c12b0Sopenharmony_ci wlen = f2fs_write_addrtag(sbi, de->ino, off, 6595e5c12b0Sopenharmony_ci WR_COMPRESS_ADDR); 6605e5c12b0Sopenharmony_ci ASSERT(!wlen); 6615e5c12b0Sopenharmony_ci wlen = f2fs_write_compress_data(sbi, de->ino, 6625e5c12b0Sopenharmony_ci (u8 *)c.compress.cc.cbuf, 6635e5c12b0Sopenharmony_ci csize, off + BLOCK_SZ); 6645e5c12b0Sopenharmony_ci ASSERT(wlen == csize); 6655e5c12b0Sopenharmony_ci c.compress.ops->reset(&c.compress.cc); 6665e5c12b0Sopenharmony_ci cur_cblk = (c.compress.cc.rlen - csize) / 6675e5c12b0Sopenharmony_ci BLOCK_SZ; 6685e5c12b0Sopenharmony_ci cblocks += cur_cblk; 6695e5c12b0Sopenharmony_ci wlen = f2fs_fix_mutable(sbi, de->ino, 6705e5c12b0Sopenharmony_ci off + BLOCK_SZ + csize, 6715e5c12b0Sopenharmony_ci cur_cblk); 6725e5c12b0Sopenharmony_ci ASSERT(!wlen); 6735e5c12b0Sopenharmony_ci } 6745e5c12b0Sopenharmony_ci off += n; 6755e5c12b0Sopenharmony_ci } 6765e5c12b0Sopenharmony_ci if (n == -1) { 6775e5c12b0Sopenharmony_ci fprintf(stderr, "Load file '%s' failed: ", 6785e5c12b0Sopenharmony_ci de->full_path); 6795e5c12b0Sopenharmony_ci perror(NULL); 6805e5c12b0Sopenharmony_ci } 6815e5c12b0Sopenharmony_ci /* read inode */ 6825e5c12b0Sopenharmony_ci get_node_info(sbi, de->ino, &ni); 6835e5c12b0Sopenharmony_ci ASSERT(dev_read_block(node_blk, ni.blk_addr) >= 0); 6845e5c12b0Sopenharmony_ci /* update inode meta */ 6855e5c12b0Sopenharmony_ci node_blk->i.i_size = cpu_to_le64(off); 6865e5c12b0Sopenharmony_ci if (!c.compress.readonly) { 6875e5c12b0Sopenharmony_ci node_blk->i.i_compr_blocks = cpu_to_le64(cblocks); 6885e5c12b0Sopenharmony_ci node_blk->i.i_blocks += cpu_to_le64(cblocks); 6895e5c12b0Sopenharmony_ci } 6905e5c12b0Sopenharmony_ci ASSERT(write_inode(node_blk, ni.blk_addr) >= 0); 6915e5c12b0Sopenharmony_ci free(node_blk); 6925e5c12b0Sopenharmony_ci 6935e5c12b0Sopenharmony_ci if (!c.compress.readonly) { 6945e5c12b0Sopenharmony_ci sbi->total_valid_block_count += cblocks; 6955e5c12b0Sopenharmony_ci if (sbi->total_valid_block_count >= 6965e5c12b0Sopenharmony_ci sbi->user_block_count) { 6975e5c12b0Sopenharmony_ci ERR_MSG("Not enough space\n"); 6985e5c12b0Sopenharmony_ci ASSERT(0); 6995e5c12b0Sopenharmony_ci } 7005e5c12b0Sopenharmony_ci } 7015e5c12b0Sopenharmony_ci#endif 7025e5c12b0Sopenharmony_ci } else { 7035e5c12b0Sopenharmony_ci while ((n = read(fd, buffer, BLOCK_SZ)) > 0) { 7045e5c12b0Sopenharmony_ci f2fs_write(sbi, de->ino, buffer, n, off); 7055e5c12b0Sopenharmony_ci off += n; 7065e5c12b0Sopenharmony_ci } 7075e5c12b0Sopenharmony_ci } 7085e5c12b0Sopenharmony_ci 7095e5c12b0Sopenharmony_ci close(fd); 7105e5c12b0Sopenharmony_ci if (n < 0) 7115e5c12b0Sopenharmony_ci return -1; 7125e5c12b0Sopenharmony_ci 7135e5c12b0Sopenharmony_ci if (!c.compress.enabled || (c.feature & cpu_to_le32(F2FS_FEATURE_RO))) 7145e5c12b0Sopenharmony_ci update_largest_extent(sbi, de->ino); 7155e5c12b0Sopenharmony_ci update_free_segments(sbi); 7165e5c12b0Sopenharmony_ci 7175e5c12b0Sopenharmony_ci MSG(1, "Info: Create %s -> %s\n" 7185e5c12b0Sopenharmony_ci " -- ino=%x, type=%x, mode=%x, uid=%x, " 7195e5c12b0Sopenharmony_ci "gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n", 7205e5c12b0Sopenharmony_ci de->full_path, de->path, 7215e5c12b0Sopenharmony_ci de->ino, de->file_type, de->mode, 7225e5c12b0Sopenharmony_ci de->uid, de->gid, de->capabilities, de->size, de->pino); 7235e5c12b0Sopenharmony_ci return 0; 7245e5c12b0Sopenharmony_ci} 725