Changeset 9b9d37bb in mainline for uspace/lib/ext4/libext4_filesystem.c
- Timestamp:
- 2011-10-06T09:48:53Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1114173
- Parents:
- 3712434
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4_filesystem.c
r3712434 r9b9d37bb 36 36 */ 37 37 38 #include <byteorder.h> 38 39 #include <errno.h> 39 40 #include <malloc.h> … … 144 145 ext4_block_group_ref_t **ref) 145 146 { 147 EXT4FS_DBG(""); 148 146 149 int rc; 147 150 aoff64_t block_id; … … 161 164 block_id = ext4_superblock_get_first_data_block(fs->superblock) + 1; 162 165 166 EXT4FS_DBG("block_size = \%d", ext4_superblock_get_block_size(fs->superblock)); 167 EXT4FS_DBG("descriptors_per_block = \%d", descriptors_per_block); 168 EXT4FS_DBG("bgid = \%d", bgid); 169 EXT4FS_DBG("first_data_block: \%d", (uint32_t)block_id); 170 163 171 /* Find the block containing the descriptor we are looking for */ 164 172 block_id += bgid / descriptors_per_block; 165 173 offset = (bgid % descriptors_per_block) * EXT4_BLOCK_GROUP_DESCRIPTOR_SIZE; 166 174 175 EXT4FS_DBG("updated block_id: \%d", (uint32_t)block_id); 176 167 177 rc = block_get(&newref->block, fs->device, block_id, 0); 168 178 if (rc != EOK) { 179 180 EXT4FS_DBG("block_get error: \%d", rc); 181 169 182 free(newref); 170 183 return rc; 171 184 } 172 185 186 EXT4FS_DBG("block read"); 187 173 188 newref->block_group = newref->block->data + offset; 174 189 175 190 *ref = newref; 191 192 EXT4FS_DBG("finished"); 176 193 177 194 return EOK; … … 184 201 ext4_inode_ref_t **ref) 185 202 { 203 EXT4FS_DBG(""); 204 186 205 int rc; 187 206 aoff64_t block_id; … … 202 221 } 203 222 223 EXT4FS_DBG("allocated"); 224 204 225 inodes_per_group = ext4_superblock_get_inodes_per_group(fs->superblock); 226 227 EXT4FS_DBG("inodes_per_group_loaded"); 205 228 206 229 /* inode numbers are 1-based, but it is simpler to work with 0-based … … 211 234 offset_in_group = index % inodes_per_group; 212 235 236 EXT4FS_DBG("index: \%d", index); 237 EXT4FS_DBG("inodes_per_group: \%d", inodes_per_group); 238 EXT4FS_DBG("bg_id: \%d", block_group); 239 213 240 rc = ext4_filesystem_get_block_group_ref(fs, block_group, &bg_ref); 214 241 if (rc != EOK) { … … 216 243 return rc; 217 244 } 245 246 EXT4FS_DBG("block_group_ref loaded"); 218 247 219 248 inode_table_start = ext4_block_group_get_inode_table_first_block( 220 249 bg_ref->block_group); 221 250 251 EXT4FS_DBG("inode_table block loaded"); 252 222 253 inode_size = ext4_superblock_get_inode_size(fs->superblock); 223 254 block_size = ext4_superblock_get_block_size(fs->superblock); … … 228 259 offset_in_block = byte_offset_in_group % block_size; 229 260 261 EXT4FS_DBG("superblock info loaded"); 262 230 263 rc = block_get(&newref->block, fs->device, block_id, 0); 231 264 if (rc != EOK) { … … 233 266 return rc; 234 267 } 268 269 EXT4FS_DBG("block got"); 235 270 236 271 newref->inode = newref->block->data + offset_in_block; … … 242 277 *ref = newref; 243 278 279 EXT4FS_DBG("finished"); 280 281 return EOK; 282 } 283 284 int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *ref) 285 { 286 int rc; 287 288 rc = block_put(ref->block); 289 free(ref); 290 291 return rc; 292 } 293 294 int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *fs, ext4_inode_t* inode, 295 aoff64_t iblock, uint32_t* fblock) 296 { 297 int rc; 298 aoff64_t limits[4]; 299 uint32_t block_ids_per_block; 300 aoff64_t blocks_per_level[4]; 301 uint32_t offset_in_block; 302 uint32_t current_block; 303 aoff64_t block_offset_in_level; 304 int i; 305 int level; 306 block_t *block; 307 308 /* Handle simple case when we are dealing with direct reference */ 309 if (iblock < EXT4_INODE_DIRECT_BLOCKS) { 310 current_block = ext4_inode_get_direct_block(inode, (uint32_t)iblock); 311 *fblock = current_block; 312 return EOK; 313 } 314 315 /* Compute limits for indirect block levels 316 * TODO: compute this once when loading filesystem and store in ext2_filesystem_t 317 */ 318 block_ids_per_block = ext4_superblock_get_block_size(fs->superblock) / sizeof(uint32_t); 319 limits[0] = EXT4_INODE_DIRECT_BLOCKS; 320 blocks_per_level[0] = 1; 321 for (i = 1; i < 4; i++) { 322 blocks_per_level[i] = blocks_per_level[i-1] * 323 block_ids_per_block; 324 limits[i] = limits[i-1] + blocks_per_level[i]; 325 } 326 327 /* Determine the indirection level needed to get the desired block */ 328 level = -1; 329 for (i = 1; i < 4; i++) { 330 if (iblock < limits[i]) { 331 level = i; 332 break; 333 } 334 } 335 336 if (level == -1) { 337 return EIO; 338 } 339 340 /* Compute offsets for the topmost level */ 341 block_offset_in_level = iblock - limits[level-1]; 342 current_block = ext4_inode_get_indirect_block(inode, level-1); 343 offset_in_block = block_offset_in_level / blocks_per_level[level-1]; 344 345 /* Navigate through other levels, until we find the block number 346 * or find null reference meaning we are dealing with sparse file 347 */ 348 while (level > 0) { 349 rc = block_get(&block, fs->device, current_block, 0); 350 if (rc != EOK) { 351 return rc; 352 } 353 354 assert(offset_in_block < block_ids_per_block); 355 current_block = uint32_t_le2host(((uint32_t*)block->data)[offset_in_block]); 356 357 rc = block_put(block); 358 if (rc != EOK) { 359 return rc; 360 } 361 362 if (current_block == 0) { 363 /* This is a sparse file */ 364 *fblock = 0; 365 return EOK; 366 } 367 368 level -= 1; 369 370 /* If we are on the last level, break here as 371 * there is no next level to visit 372 */ 373 if (level == 0) { 374 break; 375 } 376 377 /* Visit the next level */ 378 block_offset_in_level %= blocks_per_level[level]; 379 offset_in_block = block_offset_in_level / blocks_per_level[level-1]; 380 } 381 382 *fblock = current_block; 383 244 384 return EOK; 245 385 }
Note:
See TracChangeset
for help on using the changeset viewer.