1 /** 2 * segment.c 3 * 4 * Many parts of codes are copied from Linux kernel/fs/f2fs. 5 * 6 * Copyright (C) 2015 Huawei Ltd. 7 * Witten by: 8 * Hou Pengyang <houpengyang (at) huawei.com> 9 * Liu Shuoran <liushuoran (at) huawei.com> 10 * Jaegeuk Kim <jaegeuk (at) kernel.org> 11 * 12 * This program is free software; you can redistribute it and/or modify 13 * it under the terms of the GNU General Public License version 2 as 14 * published by the Free Software Foundation. 15 */ 16 #include "fsck.h" 17 #include "node.h" 18 19 static void write_inode(u64 blkaddr, struct f2fs_node *inode) 20 { 21 if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) 22 inode->i.i_inode_checksum = 23 cpu_to_le32(f2fs_inode_chksum(inode)); 24 ASSERT(dev_write_block(inode, blkaddr) >= 0); 25 } 26 27 void reserve_new_block(struct f2fs_sb_info *sbi, block_t *to, 28 struct f2fs_summary *sum, int type) 29 { 30 struct f2fs_fsck *fsck = F2FS_FSCK(sbi); 31 struct seg_entry *se; 32 u64 blkaddr, offset; 33 u64 old_blkaddr = *to; 34 35 blkaddr = SM_I(sbi)->main_blkaddr; 36 37 if (find_next_free_block(sbi, &blkaddr, 0, type)) { 38 ERR_MSG("Not enough space to allocate blocks"); 39 ASSERT(0); 40 } 41 42 se = get_seg_entry(sbi, GET_SEGNO(sbi, blkaddr)); 43 offset = OFFSET_IN_SEG(sbi, blkaddr); 44 se->type = type; 45 se->valid_blocks++; 46 f2fs_set_bit(offset, (char *)se->cur_valid_map); 47 if (c.func == FSCK) { 48 f2fs_set_main_bitmap(sbi, blkaddr, type); 49 f2fs_set_sit_bitmap(sbi, blkaddr); 50 } 51 52 if (old_blkaddr == NULL_ADDR) { 53 sbi->total_valid_block_count++; 54 if (c.func == FSCK) 55 fsck->chk.valid_blk_cnt++; 56 } 57 se->dirty = 1; 58 59 /* read/write SSA */ 60 *to = (block_t)blkaddr; 61 update_sum_entry(sbi, *to, sum); 62 } 63 64 int new_data_block(struct f2fs_sb_info *sbi, void *block, 65 struct dnode_of_data *dn, int type) 66 { 67 struct f2fs_summary sum; 68 struct node_info ni; 69 unsigned int blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node); 70 struct f2fs_checkpoint *cp = F2FS_CKPT(sbi); 71 72 if (!is_set_ckpt_flags(cp, CP_UMOUNT_FLAG)) { 73 c.alloc_failed = 1; 74 return -EINVAL; 75 } 76 77 ASSERT(dn->node_blk); 78 memset(block, 0, BLOCK_SZ); 79 80 get_node_info(sbi, dn->nid, &ni); 81 set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); 82 reserve_new_block(sbi, &dn->data_blkaddr, &sum, type); 83 84 if (blkaddr == NULL_ADDR) 85 inc_inode_blocks(dn); 86 else if (blkaddr == NEW_ADDR) 87 dn->idirty = 1; 88 set_data_blkaddr(dn); 89 return 0; 90 } 91 92 u64 f2fs_read(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 93 u64 count, pgoff_t offset) 94 { 95 struct dnode_of_data dn; 96 struct node_info ni; 97 struct f2fs_node *inode; 98 char *blk_buffer; 99 u64 filesize; 100 u64 off_in_blk; 101 u64 len_in_blk; 102 u64 read_count; 103 u64 remained_blkentries; 104 block_t blkaddr; 105 void *index_node = NULL; 106 107 memset(&dn, 0, sizeof(dn)); 108 109 /* Memory allocation for block buffer and inode. */ 110 blk_buffer = calloc(BLOCK_SZ, 2); 111 ASSERT(blk_buffer); 112 inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ); 113 114 /* Read inode */ 115 get_node_info(sbi, ino, &ni); 116 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 117 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 118 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 119 120 /* Adjust count with file length. */ 121 filesize = le64_to_cpu(inode->i.i_size); 122 if (offset > filesize) 123 count = 0; 124 else if (count + offset > filesize) 125 count = filesize - offset; 126 127 /* Main loop for file blocks */ 128 read_count = remained_blkentries = 0; 129 while (count > 0) { 130 if (remained_blkentries == 0) { 131 set_new_dnode(&dn, inode, NULL, ino); 132 get_dnode_of_data(sbi, &dn, F2FS_BYTES_TO_BLK(offset), 133 LOOKUP_NODE); 134 if (index_node) 135 free(index_node); 136 index_node = (dn.node_blk == dn.inode_blk) ? 137 NULL : dn.node_blk; 138 remained_blkentries = ADDRS_PER_PAGE(dn.node_blk); 139 } 140 ASSERT(remained_blkentries > 0); 141 142 blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node); 143 if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) 144 break; 145 146 off_in_blk = offset % BLOCK_SZ; 147 len_in_blk = BLOCK_SZ - off_in_blk; 148 if (len_in_blk > count) 149 len_in_blk = count; 150 151 /* Read data from single block. */ 152 if (len_in_blk < BLOCK_SZ) { 153 ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0); 154 memcpy(buffer, blk_buffer + off_in_blk, len_in_blk); 155 } else { 156 /* Direct read */ 157 ASSERT(dev_read_block(buffer, blkaddr) >= 0); 158 } 159 160 offset += len_in_blk; 161 count -= len_in_blk; 162 buffer += len_in_blk; 163 read_count += len_in_blk; 164 165 dn.ofs_in_node++; 166 remained_blkentries--; 167 } 168 if (index_node) 169 free(index_node); 170 free(blk_buffer); 171 172 return read_count; 173 } 174 175 u64 f2fs_write(struct f2fs_sb_info *sbi, nid_t ino, u8 *buffer, 176 u64 count, pgoff_t offset) 177 { 178 struct dnode_of_data dn; 179 struct node_info ni; 180 struct f2fs_node *inode; 181 char *blk_buffer; 182 u64 off_in_blk; 183 u64 len_in_blk; 184 u64 written_count; 185 u64 remained_blkentries; 186 block_t blkaddr; 187 void* index_node = NULL; 188 int idirty = 0; 189 int err; 190 191 /* Memory allocation for block buffer and inode. */ 192 blk_buffer = calloc(BLOCK_SZ, 2); 193 ASSERT(blk_buffer); 194 inode = (struct f2fs_node*)(blk_buffer + BLOCK_SZ); 195 196 /* Read inode */ 197 get_node_info(sbi, ino, &ni); 198 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 199 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 200 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 201 202 /* Main loop for file blocks */ 203 written_count = remained_blkentries = 0; 204 while (count > 0) { 205 if (remained_blkentries == 0) { 206 set_new_dnode(&dn, inode, NULL, ino); 207 err = get_dnode_of_data(sbi, &dn, 208 F2FS_BYTES_TO_BLK(offset), ALLOC_NODE); 209 if (err) 210 break; 211 idirty |= dn.idirty; 212 if (index_node) 213 free(index_node); 214 index_node = (dn.node_blk == dn.inode_blk) ? 215 NULL : dn.node_blk; 216 remained_blkentries = ADDRS_PER_PAGE(dn.node_blk); 217 } 218 ASSERT(remained_blkentries > 0); 219 220 blkaddr = datablock_addr(dn.node_blk, dn.ofs_in_node); 221 if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) { 222 err = new_data_block(sbi, blk_buffer, 223 &dn, CURSEG_WARM_DATA); 224 if (err) 225 break; 226 blkaddr = dn.data_blkaddr; 227 } 228 229 off_in_blk = offset % BLOCK_SZ; 230 len_in_blk = BLOCK_SZ - off_in_blk; 231 if (len_in_blk > count) 232 len_in_blk = count; 233 234 /* Write data to single block. */ 235 if (len_in_blk < BLOCK_SZ) { 236 ASSERT(dev_read_block(blk_buffer, blkaddr) >= 0); 237 memcpy(blk_buffer + off_in_blk, buffer, len_in_blk); 238 ASSERT(dev_write_block(blk_buffer, blkaddr) >= 0); 239 } else { 240 /* Direct write */ 241 ASSERT(dev_write_block(buffer, blkaddr) >= 0); 242 } 243 244 offset += len_in_blk; 245 count -= len_in_blk; 246 buffer += len_in_blk; 247 written_count += len_in_blk; 248 249 dn.ofs_in_node++; 250 if ((--remained_blkentries == 0 || count == 0) && (dn.ndirty)) 251 ASSERT(dev_write_block(dn.node_blk, dn.node_blkaddr) >= 0); 252 } 253 if (offset > le64_to_cpu(inode->i.i_size)) { 254 inode->i.i_size = cpu_to_le64(offset); 255 idirty = 1; 256 } 257 if (idirty) { 258 ASSERT(inode == dn.inode_blk); 259 write_inode(ni.blk_addr, inode); 260 } 261 if (index_node) 262 free(index_node); 263 free(blk_buffer); 264 265 return written_count; 266 } 267 268 /* This function updates only inode->i.i_size */ 269 void f2fs_filesize_update(struct f2fs_sb_info *sbi, nid_t ino, u64 filesize) 270 { 271 struct node_info ni; 272 struct f2fs_node *inode; 273 274 inode = calloc(BLOCK_SZ, 1); 275 ASSERT(inode); 276 get_node_info(sbi, ino, &ni); 277 278 ASSERT(dev_read_block(inode, ni.blk_addr) >= 0); 279 ASSERT(!S_ISDIR(le16_to_cpu(inode->i.i_mode))); 280 ASSERT(!S_ISLNK(le16_to_cpu(inode->i.i_mode))); 281 282 inode->i.i_size = cpu_to_le64(filesize); 283 284 write_inode(ni.blk_addr, inode); 285 free(inode); 286 } 287 288 int f2fs_build_file(struct f2fs_sb_info *sbi, struct dentry *de) 289 { 290 int fd, n; 291 pgoff_t off = 0; 292 u8 buffer[BLOCK_SZ]; 293 294 if (de->ino == 0) 295 return -1; 296 297 fd = open(de->full_path, O_RDONLY); 298 if (fd < 0) { 299 MSG(0, "Skip: Fail to open %s\n", de->full_path); 300 return -1; 301 } 302 303 /* inline_data support */ 304 if (de->size <= DEF_MAX_INLINE_DATA) { 305 struct node_info ni; 306 struct f2fs_node *node_blk; 307 int ret; 308 309 get_node_info(sbi, de->ino, &ni); 310 311 node_blk = calloc(BLOCK_SZ, 1); 312 ASSERT(node_blk); 313 314 ret = dev_read_block(node_blk, ni.blk_addr); 315 ASSERT(ret >= 0); 316 317 node_blk->i.i_inline |= F2FS_INLINE_DATA; 318 node_blk->i.i_inline |= F2FS_DATA_EXIST; 319 320 if (c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR)) { 321 node_blk->i.i_inline |= F2FS_EXTRA_ATTR; 322 node_blk->i.i_extra_isize = 323 cpu_to_le16(F2FS_TOTAL_EXTRA_ATTR_SIZE); 324 } 325 n = read(fd, buffer, BLOCK_SZ); 326 ASSERT((unsigned long)n == de->size); 327 memcpy(inline_data_addr(node_blk), buffer, de->size); 328 node_blk->i.i_size = cpu_to_le64(de->size); 329 write_inode(ni.blk_addr, node_blk); 330 free(node_blk); 331 } else { 332 while ((n = read(fd, buffer, BLOCK_SZ)) > 0) { 333 f2fs_write(sbi, de->ino, buffer, n, off); 334 off += n; 335 } 336 } 337 338 close(fd); 339 if (n < 0) 340 return -1; 341 342 update_free_segments(sbi); 343 344 MSG(1, "Info: Create %s -> %s\n" 345 " -- ino=%x, type=%x, mode=%x, uid=%x, " 346 "gid=%x, cap=%"PRIx64", size=%lu, pino=%x\n", 347 de->full_path, de->path, 348 de->ino, de->file_type, de->mode, 349 de->uid, de->gid, de->capabilities, de->size, de->pino); 350 return 0; 351 } 352