1 /** 2 * node.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@huawei.com> 9 * Liu Shuoran <liushuoran@huawei.com> 10 * Jaegeuk Kim <jaegeuk@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 void f2fs_alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) 20 { 21 struct f2fs_nm_info *nm_i = NM_I(sbi); 22 nid_t i; 23 24 for (i = 0; i < nm_i->max_nid; i++) 25 if(f2fs_test_bit(i, nm_i->nid_bitmap) == 0) 26 break; 27 28 ASSERT(i < nm_i->max_nid); 29 f2fs_set_bit(i, nm_i->nid_bitmap); 30 *nid = i; 31 } 32 33 void f2fs_release_nid(struct f2fs_sb_info *sbi, nid_t nid) 34 { 35 struct f2fs_nm_info *nm_i = NM_I(sbi); 36 37 ASSERT(nid < nm_i->max_nid); 38 ASSERT(f2fs_test_bit(nid, nm_i->nid_bitmap)); 39 40 f2fs_clear_bit(nid, nm_i->nid_bitmap); 41 } 42 43 void set_data_blkaddr(struct dnode_of_data *dn) 44 { 45 __le32 *addr_array; 46 struct f2fs_node *node_blk = dn->node_blk; 47 unsigned int ofs_in_node = dn->ofs_in_node; 48 49 addr_array = blkaddr_in_node(node_blk); 50 addr_array[ofs_in_node] = cpu_to_le32(dn->data_blkaddr); 51 if (dn->node_blk != dn->inode_blk) 52 dn->ndirty = 1; 53 else 54 dn->idirty = 1; 55 } 56 57 /* 58 * In this function, we get a new node blk, and write back 59 * node_blk would be sloadd in RAM, linked by dn->node_blk 60 */ 61 block_t new_node_block(struct f2fs_sb_info *sbi, 62 struct dnode_of_data *dn, unsigned int ofs) 63 { 64 struct f2fs_node *f2fs_inode; 65 struct f2fs_node *node_blk; 66 struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); 67 struct f2fs_summary sum; 68 struct node_info ni; 69 block_t blkaddr = NULL_ADDR; 70 int type; 71 int ret; 72 73 f2fs_inode = dn->inode_blk; 74 75 node_blk = calloc(BLOCK_SZ, 1); 76 ASSERT(node_blk); 77 78 node_blk->footer.nid = cpu_to_le32(dn->nid); 79 node_blk->footer.ino = f2fs_inode->footer.ino; 80 node_blk->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT); 81 node_blk->footer.cp_ver = ckpt->checkpoint_ver; 82 83 type = CURSEG_COLD_NODE; 84 if (IS_DNODE(node_blk)) { 85 if (S_ISDIR(le16_to_cpu(f2fs_inode->i.i_mode))) 86 type = CURSEG_HOT_NODE; 87 else 88 type = CURSEG_WARM_NODE; 89 } 90 91 get_node_info(sbi, dn->nid, &ni); 92 set_summary(&sum, dn->nid, 0, ni.version); 93 ret = reserve_new_block(sbi, &blkaddr, &sum, type, !ofs); 94 if (ret) { 95 free(node_blk); 96 return 0; 97 } 98 99 /* update nat info */ 100 update_nat_blkaddr(sbi, le32_to_cpu(f2fs_inode->footer.ino), 101 dn->nid, blkaddr); 102 103 dn->node_blk = node_blk; 104 inc_inode_blocks(dn); 105 return blkaddr; 106 } 107 108 /* 109 * get_node_path - Get the index path of pgoff_t block 110 * @offset: offset in the current index node block. 111 * @noffset: NO. of the index block within a file. 112 * return: depth of the index path. 113 * 114 * By default, it sets inline_xattr and inline_data 115 */ 116 static int get_node_path(struct f2fs_node *node, long block, 117 int offset[4], unsigned int noffset[4]) 118 { 119 const long direct_index = ADDRS_PER_INODE(&node->i); 120 const long direct_blks = ADDRS_PER_BLOCK(&node->i); 121 const long dptrs_per_blk = NIDS_PER_BLOCK; 122 const long indirect_blks = ADDRS_PER_BLOCK(&node->i) * NIDS_PER_BLOCK; 123 const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; 124 int n = 0; 125 int level = 0; 126 127 noffset[0] = 0; 128 if (block < direct_index) { 129 offset[n] = block; 130 goto got; 131 } 132 133 block -= direct_index; 134 if (block < direct_blks) { 135 offset[n++] = NODE_DIR1_BLOCK; 136 noffset[n]= 1; 137 offset[n] = block; 138 level = 1; 139 goto got; 140 } 141 block -= direct_blks; 142 if (block < direct_blks) { 143 offset[n++] = NODE_DIR2_BLOCK; 144 noffset[n] = 2; 145 offset[n] = block; 146 level = 1; 147 goto got; 148 } 149 block -= direct_blks; 150 if (block < indirect_blks) { 151 offset[n++] = NODE_IND1_BLOCK; 152 noffset[n] = 3; 153 offset[n++] = block / direct_blks; 154 noffset[n] = 4 + offset[n - 1]; 155 offset[n] = block % direct_blks; 156 level = 2; 157 goto got; 158 } 159 block -= indirect_blks; 160 if (block < indirect_blks) { 161 offset[n++] = NODE_IND2_BLOCK; 162 noffset[n] = 4 + dptrs_per_blk; 163 offset[n++] = block / direct_blks; 164 noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; 165 offset[n] = block % direct_blks; 166 level = 2; 167 goto got; 168 } 169 block -= indirect_blks; 170 if (block < dindirect_blks) { 171 offset[n++] = NODE_DIND_BLOCK; 172 noffset[n] = 5 + (dptrs_per_blk * 2); 173 offset[n++] = block / indirect_blks; 174 noffset[n] = 6 + (dptrs_per_blk * 2) + 175 offset[n - 1] * (dptrs_per_blk + 1); 176 offset[n++] = (block / direct_blks) % dptrs_per_blk; 177 noffset[n] = 7 + (dptrs_per_blk * 2) + 178 offset[n - 2] * (dptrs_per_blk + 1) + 179 offset[n - 1]; 180 offset[n] = block % direct_blks; 181 level = 3; 182 goto got; 183 } else { 184 ASSERT(0); 185 } 186 got: 187 return level; 188 } 189 190 int get_dnode_of_data(struct f2fs_sb_info *sbi, struct dnode_of_data *dn, 191 pgoff_t index, int mode) 192 { 193 int offset[4]; 194 unsigned int noffset[4]; 195 struct f2fs_node *parent = NULL; 196 nid_t nids[4]; 197 block_t nblk[4]; 198 struct node_info ni; 199 int level, i; 200 int ret; 201 202 level = get_node_path(dn->inode_blk, index, offset, noffset); 203 204 nids[0] = dn->nid; 205 parent = dn->inode_blk; 206 if (level != 0) 207 nids[1] = get_nid(parent, offset[0], 1); 208 else 209 dn->node_blk = dn->inode_blk; 210 211 get_node_info(sbi, nids[0], &ni); 212 nblk[0] = ni.blk_addr; 213 214 for (i = 1; i <= level; i++) { 215 if (!nids[i] && mode == ALLOC_NODE) { 216 f2fs_alloc_nid(sbi, &nids[i]); 217 218 dn->nid = nids[i]; 219 220 /* Function new_node_blk get a new f2fs_node blk and update*/ 221 /* We should make sure that dn->node_blk == NULL*/ 222 nblk[i] = new_node_block(sbi, dn, noffset[i]); 223 if (!nblk[i]) { 224 f2fs_release_nid(sbi, nids[i]); 225 c.alloc_failed = 1; 226 return -EINVAL; 227 } 228 229 set_nid(parent, offset[i - 1], nids[i], i == 1); 230 } else { 231 /* If Sparse file no read API, */ 232 struct node_info ni; 233 234 get_node_info(sbi, nids[i], &ni); 235 dn->node_blk = calloc(BLOCK_SZ, 1); 236 ASSERT(dn->node_blk); 237 238 ret = dev_read_block(dn->node_blk, ni.blk_addr); 239 ASSERT(ret >= 0); 240 241 nblk[i] = ni.blk_addr; 242 } 243 244 if (mode == ALLOC_NODE){ 245 /* Parent node may have changed */ 246 ret = dev_write_block(parent, nblk[i - 1]); 247 ASSERT(ret >= 0); 248 } 249 if (i != 1) 250 free(parent); 251 252 if (i < level) { 253 parent = dn->node_blk; 254 nids[i + 1] = get_nid(parent, offset[i], 0); 255 } 256 } 257 258 dn->nid = nids[level]; 259 dn->ofs_in_node = offset[level]; 260 dn->data_blkaddr = datablock_addr(dn->node_blk, dn->ofs_in_node); 261 dn->node_blkaddr = nblk[level]; 262 return 0; 263 } 264