Changeset ad34feb in mainline for uspace/lib/ext2/libext2_filesystem.c
- Timestamp:
- 2011-02-23T23:07:28Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 102d400
- Parents:
- a54af66
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext2/libext2_filesystem.c
ra54af66 rad34feb 41 41 #include <libblock.h> 42 42 #include <malloc.h> 43 #include <assert.h> 43 44 44 45 /** … … 255 256 256 257 /** 258 * Find a filesystem block number where iblock-th data block 259 * of the given inode is located. 260 * 261 * @return EOK on success or negative error code on failure 262 */ 263 int ext2_filesystem_get_inode_data_block_index(ext2_filesystem_t *fs, ext2_inode_t* inode, 264 aoff64_t iblock, uint32_t* fblock) 265 { 266 int rc; 267 aoff64_t limits[4]; 268 uint32_t block_ids_per_block; 269 aoff64_t blocks_per_level[4]; 270 uint32_t offset_in_block; 271 uint32_t current_block; 272 aoff64_t block_offset_in_level; 273 int i; 274 int level; 275 block_t *block; 276 277 if (iblock < EXT2_INODE_DIRECT_BLOCKS) { 278 current_block = ext2_inode_get_direct_block(inode, (uint32_t)iblock); 279 if (current_block == 0) { 280 return EIO; 281 } 282 *fblock = current_block; 283 return EOK; 284 } 285 286 // Compute limits for indirect block levels 287 // TODO: compute this once when loading filesystem and store in ext2_filesystem_t 288 block_ids_per_block = ext2_superblock_get_block_size(fs->superblock) / sizeof(uint32_t); 289 limits[0] = EXT2_INODE_DIRECT_BLOCKS; 290 blocks_per_level[0] = 1; 291 for (i = 1; i < 4; i++) { 292 blocks_per_level[i] = blocks_per_level[i-1] * 293 block_ids_per_block; 294 limits[i] = limits[i-1] + blocks_per_level[i]; 295 } 296 297 // Determine the indirection level needed to get the desired block 298 level = -1; 299 for (i = 1; i < 4; i++) { 300 if (iblock < limits[i]) { 301 level = i; 302 break; 303 } 304 } 305 306 if (level == -1) { 307 return EIO; 308 } 309 310 block_offset_in_level = iblock - limits[level-1]; 311 current_block = ext2_inode_get_indirect_block(inode, level-1); 312 offset_in_block = block_offset_in_level / blocks_per_level[level-1]; 313 314 while (level > 0) { 315 rc = block_get(&block, fs->device, current_block, 0); 316 if (rc != EOK) { 317 return rc; 318 } 319 320 assert(offset_in_block < block_ids_per_block); 321 current_block = ((uint32_t*)block->data)[offset_in_block]; 322 323 rc = block_put(block); 324 if (rc != EOK) { 325 return rc; 326 } 327 328 if (current_block == 0) { 329 return EIO; 330 } 331 332 level -= 1; 333 334 if (level == 0) { 335 break; 336 } 337 338 offset_in_block = block_offset_in_level / blocks_per_level[level-1]; 339 block_offset_in_level %= blocks_per_level[level-1]; 340 } 341 342 *fblock = current_block; 343 344 return EOK; 345 } 346 347 /** 257 348 * Finalize an instance of filesystem 258 349 *
Note:
See TracChangeset
for help on using the changeset viewer.