Changeset 9b9d37bb in mainline
- 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
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
boot/Makefile.common
r3712434 r9b9d37bb 75 75 $(USPACE_PATH)/srv/loc/loc \ 76 76 $(USPACE_PATH)/srv/bd/rd/rd \ 77 $(USPACE_PATH)/srv/vfs/vfs 77 $(USPACE_PATH)/srv/vfs/vfs \ 78 79 # TODO: For comfort ext4fs debugging - delete before merge 80 INIT_TASKS += $(USPACE_PATH)/srv/bd/ata_bd/ata_bd 78 81 79 82 ifeq ($(RDFMT),tmpfs) -
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 *); -
uspace/srv/fs/ext4fs/ext4fs_ops.c
r3712434 r9b9d37bb 40 40 #include <libext4.h> 41 41 #include <libfs.h> 42 #include <macros.h> 42 43 #include <malloc.h> 43 #include <stdio.h>44 44 #include <adt/hash_table.h> 45 45 #include <ipc/loc.h> … … 48 48 49 49 #define EXT4FS_NODE(node) ((node) ? (ext4fs_node_t *) (node)->data : NULL) 50 #define EXT4FS_DBG(format, ...) {if (true) printf("ext4fs: %s: " format "\n", __FUNCTION__, ##__VA_ARGS__);}51 50 52 51 #define OPEN_NODES_KEYS 2 … … 73 72 * Forward declarations of auxiliary functions 74 73 */ 74 75 static int ext4fs_read_directory(ipc_callid_t, aoff64_t, size_t, 76 ext4fs_instance_t *, ext4_inode_ref_t *, size_t *); 77 static int ext4fs_read_file(ipc_callid_t, aoff64_t, size_t, ext4fs_instance_t *, 78 ext4_inode_ref_t *, size_t *); 79 static bool ext4fs_is_dots(const uint8_t *, size_t); 75 80 static int ext4fs_instance_get(service_id_t, ext4fs_instance_t **); 76 81 static int ext4fs_node_get_core(fs_node_t **, ext4fs_instance_t *, fs_index_t); … … 142 147 int ext4fs_global_init(void) 143 148 { 149 EXT4FS_DBG(""); 150 144 151 if (!hash_table_create(&open_nodes, OPEN_NODES_BUCKETS, 145 152 OPEN_NODES_KEYS, &open_nodes_ops)) { … … 152 159 int ext4fs_global_fini(void) 153 160 { 161 EXT4FS_DBG(""); 162 154 163 hash_table_destroy(&open_nodes); 155 164 return EOK; … … 169 178 fibril_mutex_lock(&instance_list_mutex); 170 179 171 EXT4FS_DBG("Checking lists");172 173 180 if (list_empty(&instance_list)) { 174 181 fibril_mutex_unlock(&instance_list_mutex); 175 182 return EINVAL; 176 183 } 177 178 EXT4FS_DBG("checked");179 184 180 185 list_foreach(instance_list, link) { … … 188 193 } 189 194 190 EXT4FS_DBG("Not found");191 192 195 fibril_mutex_unlock(&instance_list_mutex); 193 196 return EINVAL; … … 197 200 int ext4fs_root_get(fs_node_t **rfn, service_id_t service_id) 198 201 { 202 EXT4FS_DBG(""); 203 199 204 return ext4fs_node_get(rfn, service_id, EXT4_INODE_ROOT_INDEX); 200 205 } … … 203 208 int ext4fs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component) 204 209 { 205 // TODO 210 EXT4FS_DBG(""); 211 212 ext4fs_node_t *eparent = EXT4FS_NODE(pfn); 213 ext4_filesystem_t *fs; 214 ext4_directory_iterator_t it; 215 int rc; 216 size_t name_size; 217 size_t component_size; 218 bool found = false; 219 uint32_t inode; 220 221 fs = eparent->instance->filesystem; 222 223 if (!ext4_inode_is_type(fs->superblock, eparent->inode_ref->inode, 224 EXT4_INODE_MODE_DIRECTORY)) { 225 return ENOTDIR; 226 } 227 228 rc = ext4_directory_iterator_init(&it, fs, eparent->inode_ref, 0); 229 if (rc != EOK) { 230 return rc; 231 } 232 233 /* Find length of component in bytes 234 * TODO: check for library function call that does this 235 */ 236 component_size = 0; 237 while (*(component+component_size) != 0) { 238 component_size++; 239 } 240 241 while (it.current != NULL) { 242 inode = ext4_directory_entry_ll_get_inode(it.current); 243 244 /* ignore empty directory entries */ 245 if (inode != 0) { 246 name_size = ext4_directory_entry_ll_get_name_length(fs->superblock, 247 it.current); 248 249 if (name_size == component_size && bcmp(component, &it.current->name, 250 name_size) == 0) { 251 rc = ext4fs_node_get_core(rfn, eparent->instance, 252 inode); 253 if (rc != EOK) { 254 ext4_directory_iterator_fini(&it); 255 return rc; 256 } 257 found = true; 258 break; 259 } 260 } 261 262 rc = ext4_directory_iterator_next(&it); 263 if (rc != EOK) { 264 ext4_directory_iterator_fini(&it); 265 return rc; 266 } 267 } 268 269 ext4_directory_iterator_fini(&it); 270 271 if (!found) { 272 return ENOENT; 273 } 274 206 275 return EOK; 207 276 } … … 225 294 fs_index_t index) 226 295 { 227 228 296 int rc; 229 297 fs_node_t *node = NULL; … … 290 358 291 359 292 int ext4fs_node_put_core(ext4fs_node_t *enode) { 293 // TODO 360 int ext4fs_node_put_core(ext4fs_node_t *enode) 361 { 362 int rc; 363 unsigned long key[] = { 364 [OPEN_NODES_DEV_HANDLE_KEY] = enode->instance->service_id, 365 [OPEN_NODES_INODE_KEY] = enode->inode_ref->index, 366 }; 367 368 hash_table_remove(&open_nodes, key, OPEN_NODES_KEYS); 369 assert(enode->instance->open_nodes_count > 0); 370 enode->instance->open_nodes_count--; 371 372 rc = ext4_filesystem_put_inode_ref(enode->inode_ref); 373 if (rc != EOK) { 374 return rc; 375 } 376 377 free(enode->fs_node); 378 free(enode); 379 294 380 return EOK; 295 381 } … … 304 390 int ext4fs_node_put(fs_node_t *fn) 305 391 { 306 EXT4FS_DBG("");307 392 int rc; 308 393 ext4fs_node_t *enode = EXT4FS_NODE(fn); … … 328 413 int ext4fs_create_node(fs_node_t **rfn, service_id_t service_id, int flags) 329 414 { 415 EXT4FS_DBG(""); 416 330 417 // TODO 331 418 return ENOTSUP; … … 335 422 int ext4fs_destroy_node(fs_node_t *fn) 336 423 { 424 EXT4FS_DBG(""); 425 337 426 // TODO 338 427 return ENOTSUP; … … 342 431 int ext4fs_link(fs_node_t *pfn, fs_node_t *cfn, const char *name) 343 432 { 433 EXT4FS_DBG(""); 434 344 435 // TODO 345 436 return ENOTSUP; … … 349 440 int ext4fs_unlink(fs_node_t *pfn, fs_node_t *cfn, const char *nm) 350 441 { 442 EXT4FS_DBG(""); 443 351 444 // TODO 352 445 return ENOTSUP; … … 356 449 int ext4fs_has_children(bool *has_children, fs_node_t *fn) 357 450 { 451 EXT4FS_DBG(""); 452 358 453 // TODO 359 454 return EOK; … … 363 458 fs_index_t ext4fs_index_get(fs_node_t *fn) 364 459 { 365 // TODO366 return 0;460 ext4fs_node_t *enode = EXT4FS_NODE(fn); 461 return enode->inode_ref->index; 367 462 } 368 463 … … 370 465 aoff64_t ext4fs_size_get(fs_node_t *fn) 371 466 { 372 // TODO 373 return 0; 467 ext4fs_node_t *enode = EXT4FS_NODE(fn); 468 aoff64_t size = ext4_inode_get_size(enode->instance->filesystem->superblock, 469 enode->inode_ref->inode); 470 return size; 374 471 } 375 472 … … 377 474 unsigned ext4fs_lnkcnt_get(fs_node_t *fn) 378 475 { 379 // TODO 380 return 0; 476 ext4fs_node_t *enode = EXT4FS_NODE(fn); 477 unsigned count = ext4_inode_get_links_count(enode->inode_ref->inode); 478 return count; 381 479 } 382 480 … … 384 482 bool ext4fs_is_directory(fs_node_t *fn) 385 483 { 484 EXT4FS_DBG(""); 485 386 486 // TODO 387 487 return false; … … 391 491 bool ext4fs_is_file(fs_node_t *fn) 392 492 { 393 // TODO 394 return false; 493 ext4fs_node_t *enode = EXT4FS_NODE(fn); 494 bool is_file = ext4_inode_is_type(enode->instance->filesystem->superblock, 495 enode->inode_ref->inode, EXT4_INODE_MODE_FILE); 496 return is_file; 395 497 } 396 498 … … 398 500 service_id_t ext4fs_service_get(fs_node_t *fn) 399 501 { 502 EXT4FS_DBG(""); 503 400 504 // TODO 401 505 return 0; … … 432 536 fs_index_t *index, aoff64_t *size, unsigned *lnkcnt) 433 537 { 538 EXT4FS_DBG(""); 434 539 435 540 int rc; … … 511 616 static int ext4fs_unmounted(service_id_t service_id) 512 617 { 618 EXT4FS_DBG(""); 513 619 514 620 int rc; … … 545 651 size_t *rbytes) 546 652 { 547 // TODO 548 return 0; 549 } 550 653 EXT4FS_DBG(""); 654 655 ext4fs_instance_t *inst; 656 ext4_inode_ref_t *inode_ref; 657 int rc; 658 659 /* 660 * Receive the read request. 661 */ 662 ipc_callid_t callid; 663 size_t size; 664 if (!async_data_read_receive(&callid, &size)) { 665 async_answer_0(callid, EINVAL); 666 return EINVAL; 667 } 668 669 rc = ext4fs_instance_get(service_id, &inst); 670 if (rc != EOK) { 671 async_answer_0(callid, rc); 672 return rc; 673 } 674 675 rc = ext4_filesystem_get_inode_ref(inst->filesystem, index, &inode_ref); 676 if (rc != EOK) { 677 async_answer_0(callid, rc); 678 return rc; 679 } 680 681 if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode, 682 EXT4_INODE_MODE_FILE)) { 683 rc = ext4fs_read_file(callid, pos, size, inst, inode_ref, 684 rbytes); 685 } else if (ext4_inode_is_type(inst->filesystem->superblock, 686 inode_ref->inode, EXT4_INODE_MODE_DIRECTORY)) { 687 rc = ext4fs_read_directory(callid, pos, size, inst, inode_ref, 688 rbytes); 689 } else { 690 /* Other inode types not supported */ 691 async_answer_0(callid, ENOTSUP); 692 rc = ENOTSUP; 693 } 694 695 ext4_filesystem_put_inode_ref(inode_ref); 696 return rc; 697 } 698 699 bool ext4fs_is_dots(const uint8_t *name, size_t name_size) { 700 if (name_size == 1 && name[0] == '.') { 701 return true; 702 } 703 704 if (name_size == 2 && name[0] == '.' && name[1] == '.') { 705 return true; 706 } 707 708 return false; 709 } 710 711 int ext4fs_read_directory(ipc_callid_t callid, aoff64_t pos, size_t size, 712 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) 713 { 714 EXT4FS_DBG(""); 715 716 ext4_directory_iterator_t it; 717 aoff64_t next; 718 uint8_t *buf; 719 size_t name_size; 720 int rc; 721 bool found = false; 722 723 rc = ext4_directory_iterator_init(&it, inst->filesystem, inode_ref, pos); 724 if (rc != EOK) { 725 async_answer_0(callid, rc); 726 return rc; 727 } 728 729 /* Find next interesting directory entry. 730 * We want to skip . and .. entries 731 * as these are not used in HelenOS 732 */ 733 while (it.current != NULL) { 734 if (it.current->inode == 0) { 735 goto skip; 736 } 737 738 name_size = ext4_directory_entry_ll_get_name_length( 739 inst->filesystem->superblock, it.current); 740 741 /* skip . and .. */ 742 if (ext4fs_is_dots(&it.current->name, name_size)) { 743 goto skip; 744 } 745 746 /* The on-disk entry does not contain \0 at the end 747 * end of entry name, so we copy it to new buffer 748 * and add the \0 at the end 749 */ 750 buf = malloc(name_size+1); 751 if (buf == NULL) { 752 ext4_directory_iterator_fini(&it); 753 async_answer_0(callid, ENOMEM); 754 return ENOMEM; 755 } 756 memcpy(buf, &it.current->name, name_size); 757 *(buf + name_size) = 0; 758 found = true; 759 (void) async_data_read_finalize(callid, buf, name_size + 1); 760 free(buf); 761 break; 762 763 skip: 764 rc = ext4_directory_iterator_next(&it); 765 if (rc != EOK) { 766 ext4_directory_iterator_fini(&it); 767 async_answer_0(callid, rc); 768 return rc; 769 } 770 } 771 772 if (found) { 773 rc = ext4_directory_iterator_next(&it); 774 if (rc != EOK) 775 return rc; 776 next = it.current_offset; 777 } 778 779 rc = ext4_directory_iterator_fini(&it); 780 if (rc != EOK) 781 return rc; 782 783 if (found) { 784 *rbytes = next - pos; 785 return EOK; 786 } else { 787 async_answer_0(callid, ENOENT); 788 return ENOENT; 789 } 790 } 791 792 int ext4fs_read_file(ipc_callid_t callid, aoff64_t pos, size_t size, 793 ext4fs_instance_t *inst, ext4_inode_ref_t *inode_ref, size_t *rbytes) 794 { 795 EXT4FS_DBG(""); 796 797 int rc; 798 uint32_t block_size; 799 aoff64_t file_block; 800 uint64_t file_size; 801 uint32_t fs_block; 802 size_t offset_in_block; 803 size_t bytes; 804 block_t *block; 805 uint8_t *buffer; 806 807 file_size = ext4_inode_get_size(inst->filesystem->superblock, 808 inode_ref->inode); 809 810 if (pos >= file_size) { 811 /* Read 0 bytes successfully */ 812 async_data_read_finalize(callid, NULL, 0); 813 *rbytes = 0; 814 return EOK; 815 } 816 817 /* For now, we only read data from one block at a time */ 818 block_size = ext4_superblock_get_block_size(inst->filesystem->superblock); 819 file_block = pos / block_size; 820 offset_in_block = pos % block_size; 821 bytes = min(block_size - offset_in_block, size); 822 823 /* Handle end of file */ 824 if (pos + bytes > file_size) { 825 bytes = file_size - pos; 826 } 827 828 /* Get the real block number */ 829 rc = ext4_filesystem_get_inode_data_block_index(inst->filesystem, 830 inode_ref->inode, file_block, &fs_block); 831 if (rc != EOK) { 832 async_answer_0(callid, rc); 833 return rc; 834 } 835 836 /* Check for sparse file 837 * If ext2_filesystem_get_inode_data_block_index returned 838 * fs_block == 0, it means that the given block is not allocated for the 839 * file and we need to return a buffer of zeros 840 */ 841 if (fs_block == 0) { 842 buffer = malloc(bytes); 843 if (buffer == NULL) { 844 async_answer_0(callid, ENOMEM); 845 return ENOMEM; 846 } 847 848 memset(buffer, 0, bytes); 849 850 async_data_read_finalize(callid, buffer, bytes); 851 *rbytes = bytes; 852 853 free(buffer); 854 855 return EOK; 856 } 857 858 /* Usual case - we need to read a block from device */ 859 rc = block_get(&block, inst->service_id, fs_block, BLOCK_FLAGS_NONE); 860 if (rc != EOK) { 861 async_answer_0(callid, rc); 862 return rc; 863 } 864 865 assert(offset_in_block + bytes <= block_size); 866 async_data_read_finalize(callid, block->data + offset_in_block, bytes); 867 868 rc = block_put(block); 869 if (rc != EOK) 870 return rc; 871 872 *rbytes = bytes; 873 return EOK; 874 } 551 875 552 876 static int
Note:
See TracChangeset
for help on using the changeset viewer.