Changeset 9b9d37bb in mainline for uspace/lib/ext4
- Timestamp:
- 2011-10-06T09:48:53Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1114173
- Parents:
- 3712434
- Location:
- uspace/lib/ext4
- Files:
-
- 8 edited
-
libext4.h (modified) (1 diff)
-
libext4_directory.c (modified) (1 diff)
-
libext4_directory.h (modified) (1 diff)
-
libext4_filesystem.c (modified) (10 diffs)
-
libext4_filesystem.h (modified) (1 diff)
-
libext4_inode.c (modified) (2 diffs)
-
libext4_inode.h (modified) (5 diffs)
-
libext4_superblock.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/libext4.h
r3712434 r9b9d37bb 40 40 #include "libext4_superblock.h" 41 41 42 #include <stdio.h> 43 #define EXT4FS_DBG(format, ...) {if (true) printf("ext4fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);} 44 42 45 #endif 43 46 -
uspace/lib/ext4/libext4_directory.c
r3712434 r9b9d37bb 36 36 */ 37 37 38 #include <byteorder.h> 39 #include <errno.h> 38 40 #include "libext4.h" 41 42 static int ext4_directory_iterator_set(ext4_directory_iterator_t *, 43 uint32_t); 44 45 46 uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *de) 47 { 48 return uint32_t_le2host(de->inode); 49 } 50 51 uint16_t ext4_directory_entry_ll_get_entry_length( 52 ext4_directory_entry_ll_t *de) 53 { 54 return uint16_t_le2host(de->entry_length); 55 } 56 57 uint16_t ext4_directory_entry_ll_get_name_length( 58 ext4_superblock_t *sb, ext4_directory_entry_ll_t *de) 59 { 60 if (ext4_superblock_get_rev_level(sb) == 0 && 61 ext4_superblock_get_minor_rev_level(sb) < 5) { 62 return ((uint16_t)de->name_length_high) << 8 | 63 ((uint16_t)de->name_length); 64 } 65 return de->name_length; 66 } 67 68 int ext4_directory_iterator_init(ext4_directory_iterator_t *it, 69 ext4_filesystem_t *fs, ext4_inode_ref_t *inode_ref, aoff64_t pos) 70 { 71 it->inode_ref = inode_ref; 72 it->fs = fs; 73 it->current = NULL; 74 it->current_offset = 0; 75 it->current_block = NULL; 76 77 return ext4_directory_iterator_seek(it, pos); 78 } 79 80 81 int ext4_directory_iterator_next(ext4_directory_iterator_t *it) 82 { 83 uint16_t skip; 84 85 assert(it->current != NULL); 86 87 skip = ext4_directory_entry_ll_get_entry_length(it->current); 88 89 return ext4_directory_iterator_seek(it, it->current_offset + skip); 90 } 91 92 93 int ext4_directory_iterator_seek(ext4_directory_iterator_t *it, aoff64_t pos) 94 { 95 int rc; 96 97 uint64_t size; 98 aoff64_t current_block_idx; 99 aoff64_t next_block_idx; 100 uint32_t next_block_phys_idx; 101 uint32_t block_size; 102 103 size = ext4_inode_get_size(it->fs->superblock, it->inode_ref->inode); 104 105 /* The iterator is not valid until we seek to the desired position */ 106 it->current = NULL; 107 108 /* Are we at the end? */ 109 if (pos >= size) { 110 if (it->current_block) { 111 rc = block_put(it->current_block); 112 it->current_block = NULL; 113 if (rc != EOK) { 114 return rc; 115 } 116 } 117 118 it->current_offset = pos; 119 return EOK; 120 } 121 122 block_size = ext4_superblock_get_block_size(it->fs->superblock); 123 current_block_idx = it->current_offset / block_size; 124 next_block_idx = pos / block_size; 125 126 /* If we don't have a block or are moving accross block boundary, 127 * we need to get another block 128 */ 129 if (it->current_block == NULL || current_block_idx != next_block_idx) { 130 if (it->current_block) { 131 rc = block_put(it->current_block); 132 it->current_block = NULL; 133 if (rc != EOK) { 134 return rc; 135 } 136 } 137 138 rc = ext4_filesystem_get_inode_data_block_index(it->fs, 139 it->inode_ref->inode, next_block_idx, &next_block_phys_idx); 140 if (rc != EOK) { 141 return rc; 142 } 143 144 rc = block_get(&it->current_block, it->fs->device, next_block_phys_idx, 145 BLOCK_FLAGS_NONE); 146 if (rc != EOK) { 147 it->current_block = NULL; 148 return rc; 149 } 150 } 151 152 it->current_offset = pos; 153 return ext4_directory_iterator_set(it, block_size); 154 } 155 156 static int ext4_directory_iterator_set(ext4_directory_iterator_t *it, 157 uint32_t block_size) 158 { 159 uint32_t offset_in_block = it->current_offset % block_size; 160 161 it->current = NULL; 162 163 /* Ensure proper alignment */ 164 if ((offset_in_block % 4) != 0) { 165 return EIO; 166 } 167 168 /* Ensure that the core of the entry does not overflow the block */ 169 if (offset_in_block > block_size - 8) { 170 return EIO; 171 } 172 173 ext4_directory_entry_ll_t *entry = it->current_block->data + offset_in_block; 174 175 /* Ensure that the whole entry does not overflow the block */ 176 uint16_t length = ext4_directory_entry_ll_get_entry_length(entry); 177 if (offset_in_block + length > block_size) { 178 return EIO; 179 } 180 181 /* Ensure the name length is not too large */ 182 if (ext4_directory_entry_ll_get_name_length(it->fs->superblock, 183 entry) > length-8) { 184 return EIO; 185 } 186 187 it->current = entry; 188 return EOK; 189 } 190 191 192 int ext4_directory_iterator_fini(ext4_directory_iterator_t *it) 193 { 194 int rc; 195 196 it->fs = NULL; 197 it->inode_ref = NULL; 198 it->current = NULL; 199 200 if (it->current_block) { 201 rc = block_put(it->current_block); 202 if (rc != EOK) { 203 return rc; 204 } 205 } 206 207 return EOK; 208 } 39 209 40 210 -
uspace/lib/ext4/libext4_directory.h
r3712434 r9b9d37bb 34 34 #define LIBEXT4_LIBEXT4_DIRECTORY_H_ 35 35 36 #include "libext4_filesystem.h" 37 #include "libext4_inode.h" 38 39 /** 40 * Linked list directory entry structure 41 */ 42 typedef struct ext4_directory_entry_ll { 43 uint32_t inode; // Inode for the entry 44 uint16_t entry_length; // Distance to the next directory entry 45 uint8_t name_length; // Lower 8 bits of name length 46 union { 47 uint8_t name_length_high; // Higher 8 bits of name length 48 uint8_t inode_type; // Type of referenced inode (in rev >= 0.5) 49 } __attribute__ ((packed)); 50 uint8_t name; // First byte of name, if present 51 } __attribute__ ((packed)) ext4_directory_entry_ll_t; 52 53 typedef struct ext4_directory_iterator { 54 ext4_filesystem_t *fs; 55 ext4_inode_ref_t *inode_ref; 56 block_t *current_block; 57 aoff64_t current_offset; 58 ext4_directory_entry_ll_t *current; 59 } ext4_directory_iterator_t; 60 61 extern uint32_t ext4_directory_entry_ll_get_inode(ext4_directory_entry_ll_t *); 62 extern uint16_t ext4_directory_entry_ll_get_entry_length( 63 ext4_directory_entry_ll_t *); 64 extern uint16_t ext4_directory_entry_ll_get_name_length( 65 ext4_superblock_t *, ext4_directory_entry_ll_t *); 66 67 extern int ext4_directory_iterator_init(ext4_directory_iterator_t *, 68 ext4_filesystem_t *, ext4_inode_ref_t *, aoff64_t); 69 extern int ext4_directory_iterator_next(ext4_directory_iterator_t *); 70 extern int ext4_directory_iterator_seek(ext4_directory_iterator_t *, aoff64_t pos); 71 extern int ext4_directory_iterator_fini(ext4_directory_iterator_t *); 36 72 37 73 #endif -
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 } -
uspace/lib/ext4/libext4_filesystem.h
r3712434 r9b9d37bb 108 108 extern int ext4_filesystem_get_inode_ref(ext4_filesystem_t *, uint32_t, 109 109 ext4_inode_ref_t **); 110 110 extern int ext4_filesystem_put_inode_ref(ext4_inode_ref_t *); 111 extern int ext4_filesystem_get_inode_data_block_index(ext4_filesystem_t *, 112 ext4_inode_t *, aoff64_t iblock, uint32_t *); 111 113 112 114 #endif -
uspace/lib/ext4/libext4_inode.c
r3712434 r9b9d37bb 39 39 #include "libext4.h" 40 40 41 uint32_t ext4_inode_get_mode(ext4_superblock_t *sb, ext4_inode_t *inode) 42 { 43 if (ext4_superblock_get_creator_os(sb) == EXT4_SUPERBLOCK_OS_HURD) { 44 return ((uint32_t)uint16_t_le2host(inode->osd2.hurd2.mode_high)) << 16 | 45 ((uint32_t)uint16_t_le2host(inode->mode)); 46 } 47 return uint16_t_le2host(inode->mode); 48 } 49 50 bool ext4_inode_is_type(ext4_superblock_t *sb, ext4_inode_t *inode, uint32_t type) 51 { 52 uint32_t mode = ext4_inode_get_mode(sb, inode); 53 return (mode & EXT4_INODE_MODE_TYPE_MASK) == type; 54 } 55 41 56 /* 42 uint32_t ext4_inode_get_mode(ext4_inode_t *inode)43 57 uint32_t ext4_inode_get_uid(ext4_inode_t *inode) 44 58 */ 45 59 46 uint64_t ext4_inode_get_size(ext4_ inode_t *inode)60 uint64_t ext4_inode_get_size(ext4_superblock_t *sb, ext4_inode_t *inode) 47 61 { 48 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 | 49 ((uint64_t)uint32_t_le2host(inode->size_lo)); 62 uint32_t major_rev = ext4_superblock_get_rev_level(sb); 63 64 if (major_rev > 0 && ext4_inode_is_type(sb, inode, EXT4_INODE_MODE_FILE)) { 65 return ((uint64_t)uint32_t_le2host(inode->size_hi)) << 32 | 66 ((uint64_t)uint32_t_le2host(inode->size_lo)); 67 } 68 return uint32_t_le2host(inode->size_lo); 50 69 } 51 70 … … 68 87 */ 69 88 89 uint32_t ext4_inode_get_direct_block(ext4_inode_t *inode, uint8_t idx) 90 { 91 assert(idx < EXT4_INODE_DIRECT_BLOCK_COUNT); 92 return uint32_t_le2host(inode->blocks[idx]); 93 } 94 95 uint32_t ext4_inode_get_indirect_block(ext4_inode_t *inode, uint8_t idx) 96 { 97 assert(idx < EXT4_INODE_INDIRECT_BLOCK_COUNT); 98 return uint32_t_le2host(inode->blocks[idx + EXT4_INODE_INDIRECT_BLOCK]); 99 } 100 70 101 /** 71 102 * @} -
uspace/lib/ext4/libext4_inode.h
r3712434 r9b9d37bb 36 36 #include <libblock.h> 37 37 #include <sys/types.h> 38 #include "libext4_superblock.h" 38 39 39 #define EXT4_DIRECT_BLOCK_COUNT 12 40 #define EXT4_INDIRECT_BLOCK EXT4_DIRECT_BLOCK_COUNT 41 #define EXT4_DOUBLE_INDIRECT_BLOCK (EXT4_INDIRECT_BLOCK + 1) 42 #define EXT4_TRIPPLE_INDIRECT_BLOCK (EXT4_DOUBLE_INDIRECT_BLOCK + 1) 43 #define EXT4_INODE_BLOCKS (EXT4_TRIPPLE_INDIRECT_BLOCK + 1) 40 41 #define EXT4_INODE_DIRECT_BLOCK_COUNT 12 42 #define EXT4_INODE_INDIRECT_BLOCK EXT4_INODE_DIRECT_BLOCK_COUNT 43 #define EXT4_INODE_DOUBLE_INDIRECT_BLOCK (EXT4_INODE_INDIRECT_BLOCK + 1) 44 #define EXT4_INODE_TRIPPLE_INDIRECT_BLOCK (EXT4_INODE_DOUBLE_INDIRECT_BLOCK + 1) 45 #define EXT4_INODE_BLOCKS (EXT4_INODE_TRIPPLE_INDIRECT_BLOCK + 1) 46 #define EXT4_INODE_INDIRECT_BLOCK_COUNT (EXT4_INODE_BLOCKS - EXT4_INODE_DIRECT_BLOCK_COUNT) 44 47 45 48 /* … … 64 67 uint32_t size_hi; 65 68 uint32_t obso_faddr; // Obsoleted fragment address 66 uint32_t unused_osd2[3]; // OS dependent - not used in HelenOS 69 union { 70 struct { 71 uint16_t blocks_high; /* were l_i_reserved1 */ 72 uint16_t file_acl_high; 73 uint16_t uid_high; /* these 2 fields */ 74 uint16_t gid_high; /* were reserved2[0] */ 75 uint32_t reserved2; 76 } linux2; 77 struct { 78 uint16_t reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ 79 uint16_t mode_high; 80 uint16_t uid_high; 81 uint16_t gid_high; 82 uint32_t author; 83 } hurd2; 84 struct { 85 uint16_t reserved1; /* Obsoleted fragment number/size which are removed in ext4 */ 86 uint16_t file_acl_high; 87 uint32_t reserved2[2]; 88 } masix2; 89 } __attribute__ ((packed)) osd2; 90 67 91 uint16_t extra_isize; 68 92 uint16_t pad1; … … 75 99 } __attribute__ ((packed)) ext4_inode_t; 76 100 101 #define EXT4_INODE_MODE_FIFO 0x1000 102 #define EXT4_INODE_MODE_CHARDEV 0x2000 103 #define EXT4_INODE_MODE_DIRECTORY 0x4000 104 #define EXT4_INODE_MODE_BLOCKDEV 0x6000 105 #define EXT4_INODE_MODE_FILE 0x8000 106 #define EXT4_INODE_MODE_SOFTLINK 0xA000 107 #define EXT4_INODE_MODE_SOCKET 0xC000 108 #define EXT4_INODE_MODE_TYPE_MASK 0xF000 77 109 78 110 #define EXT4_INODE_ROOT_INDEX 2 … … 84 116 } ext4_inode_ref_t; 85 117 118 119 extern uint32_t ext4_inode_get_mode(ext4_superblock_t *, ext4_inode_t *); 120 extern bool ext4_inode_is_type(ext4_superblock_t *, ext4_inode_t *, uint32_t); 86 121 /* 87 extern uint16_t ext4_inode_get_mode(ext4_inode_t *);88 122 extern uint32_t ext4_inode_get_uid(ext4_inode_t *); 89 123 */ 90 extern uint64_t ext4_inode_get_size(ext4_ inode_t *);124 extern uint64_t ext4_inode_get_size(ext4_superblock_t *, ext4_inode_t *); 91 125 /* 92 126 extern uint32_t ext4_inode_get_access_time(ext4_inode_t *); … … 101 135 extern uint32_t ext4_inode_get_flags(ext4_inode_t *); 102 136 */ 137 138 uint32_t ext4_inode_get_direct_block(ext4_inode_t *, uint8_t); 139 uint32_t ext4_inode_get_indirect_block(ext4_inode_t *, uint8_t); 103 140 104 141 /* -
uspace/lib/ext4/libext4_superblock.h
r3712434 r9b9d37bb 140 140 #define EXT4_SUPERBLOCK_SIZE 1024 141 141 #define EXT4_SUPERBLOCK_OFFSET 1024 142 143 #define EXT4_SUPERBLOCK_OS_LINUX 0 144 #define EXT4_SUPERBLOCK_OS_HURD 1 142 145 143 146 extern uint32_t ext4_superblock_get_inodes_count(ext4_superblock_t *);
Note:
See TracChangeset
for help on using the changeset viewer.
