Changeset a35b458 in mainline for uspace/lib/ext4/src/ops.c
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ext4/src/ops.c
r3061bc1 ra35b458 117 117 node_key_t *key = (node_key_t *)key_arg; 118 118 ext4_node_t *enode = hash_table_get_inst(item, ext4_node_t, link); 119 119 120 120 return key->service_id == enode->instance->service_id 121 121 && key->index == enode->inode_ref->index; … … 142 142 if (!hash_table_create(&open_nodes, 0, 0, &open_nodes_ops)) 143 143 return ENOMEM; 144 144 145 145 return EOK; 146 146 } … … 173 173 { 174 174 fibril_mutex_lock(&instance_list_mutex); 175 175 176 176 if (list_empty(&instance_list)) { 177 177 fibril_mutex_unlock(&instance_list_mutex); 178 178 return EINVAL; 179 179 } 180 180 181 181 list_foreach(instance_list, link, ext4_instance_t, tmp) { 182 182 if (tmp->service_id == service_id) { … … 186 186 } 187 187 } 188 188 189 189 fibril_mutex_unlock(&instance_list_mutex); 190 190 return EINVAL; … … 219 219 ext4_node_t *eparent = EXT4_NODE(pfn); 220 220 ext4_filesystem_t *fs = eparent->instance->filesystem; 221 221 222 222 if (!ext4_inode_is_type(fs->superblock, eparent->inode_ref->inode, 223 223 EXT4_INODE_MODE_DIRECTORY)) 224 224 return ENOTDIR; 225 225 226 226 /* Try to find entry */ 227 227 ext4_directory_search_result_t result; … … 233 233 return EOK; 234 234 } 235 236 return rc; 237 } 238 235 236 return rc; 237 } 238 239 239 /* Load node from search result */ 240 240 uint32_t inode = ext4_directory_entry_ll_get_inode(result.dentry); … … 268 268 if (rc != EOK) 269 269 return rc; 270 270 271 271 return ext4_node_get_core(rfn, inst, index); 272 272 } … … 285 285 { 286 286 fibril_mutex_lock(&open_nodes_lock); 287 287 288 288 /* Check if the node is not already open */ 289 289 node_key_t key = { … … 291 291 .index = index 292 292 }; 293 293 294 294 ht_link_t *already_open = hash_table_find(&open_nodes, &key); 295 295 ext4_node_t *enode = NULL; … … 298 298 *rfn = enode->fs_node; 299 299 enode->references++; 300 300 301 301 fibril_mutex_unlock(&open_nodes_lock); 302 302 return EOK; 303 303 } 304 304 305 305 /* Prepare new enode */ 306 306 enode = malloc(sizeof(ext4_node_t)); … … 309 309 return ENOMEM; 310 310 } 311 311 312 312 /* Prepare new fs_node and initialize */ 313 313 fs_node_t *fs_node = malloc(sizeof(fs_node_t)); … … 317 317 return ENOMEM; 318 318 } 319 319 320 320 fs_node_initialize(fs_node); 321 321 322 322 /* Load i-node from filesystem */ 323 323 ext4_inode_ref_t *inode_ref; … … 330 330 return rc; 331 331 } 332 332 333 333 /* Initialize enode */ 334 334 enode->inode_ref = inode_ref; … … 336 336 enode->references = 1; 337 337 enode->fs_node = fs_node; 338 338 339 339 fs_node->data = enode; 340 340 *rfn = fs_node; 341 341 342 342 hash_table_insert(&open_nodes, &enode->link); 343 343 inst->open_nodes_count++; 344 344 345 345 fibril_mutex_unlock(&open_nodes_lock); 346 346 347 347 return EOK; 348 348 } … … 360 360 assert(enode->instance->open_nodes_count > 0); 361 361 enode->instance->open_nodes_count--; 362 362 363 363 /* Put inode back in filesystem */ 364 364 errno_t rc = ext4_filesystem_put_inode_ref(enode->inode_ref); 365 365 if (rc != EOK) 366 366 return rc; 367 367 368 368 /* Destroy data structure */ 369 369 free(enode->fs_node); 370 370 free(enode); 371 371 372 372 return EOK; 373 373 } … … 399 399 { 400 400 fibril_mutex_lock(&open_nodes_lock); 401 401 402 402 ext4_node_t *enode = EXT4_NODE(fn); 403 403 assert(enode->references > 0); … … 410 410 } 411 411 } 412 412 413 413 fibril_mutex_unlock(&open_nodes_lock); 414 414 415 415 return EOK; 416 416 } … … 432 432 if (enode == NULL) 433 433 return ENOMEM; 434 434 435 435 /* Allocate fs_node */ 436 436 fs_node_t *fs_node; … … 440 440 return ENOMEM; 441 441 } 442 442 443 443 /* Load instance */ 444 444 ext4_instance_t *inst; … … 449 449 return rc; 450 450 } 451 451 452 452 /* Allocate new i-node in filesystem */ 453 453 ext4_inode_ref_t *inode_ref; … … 458 458 return rc; 459 459 } 460 460 461 461 /* Do some interconnections in references */ 462 462 enode->inode_ref = inode_ref; 463 463 enode->instance = inst; 464 464 enode->references = 1; 465 465 466 466 fibril_mutex_lock(&open_nodes_lock); 467 467 hash_table_insert(&open_nodes, &enode->link); 468 468 fibril_mutex_unlock(&open_nodes_lock); 469 469 inst->open_nodes_count++; 470 470 471 471 enode->inode_ref->dirty = true; 472 472 473 473 fs_node_initialize(fs_node); 474 474 fs_node->data = enode; 475 475 enode->fs_node = fs_node; 476 476 *rfn = fs_node; 477 477 478 478 return EOK; 479 479 } … … 495 495 return rc; 496 496 } 497 497 498 498 if (has_children) { 499 499 ext4_node_put(fn); 500 500 return EINVAL; 501 501 } 502 502 503 503 ext4_node_t *enode = EXT4_NODE(fn); 504 504 ext4_inode_ref_t *inode_ref = enode->inode_ref; 505 505 506 506 /* Release data blocks */ 507 507 rc = ext4_filesystem_truncate_inode(inode_ref, 0); … … 510 510 return rc; 511 511 } 512 512 513 513 /* 514 514 * TODO: Sset real deletion time when it will be supported. … … 517 517 ext4_inode_set_deletion_time(inode_ref->inode, 0xdeadbeef); 518 518 inode_ref->dirty = true; 519 519 520 520 /* Free inode */ 521 521 rc = ext4_filesystem_free_inode(inode_ref); … … 524 524 return rc; 525 525 } 526 526 527 527 return ext4_node_put(fn); 528 528 } … … 542 542 if (str_size(name) > EXT4_DIRECTORY_FILENAME_LEN) 543 543 return ENAMETOOLONG; 544 544 545 545 ext4_node_t *parent = EXT4_NODE(pfn); 546 546 ext4_node_t *child = EXT4_NODE(cfn); 547 547 ext4_filesystem_t *fs = parent->instance->filesystem; 548 548 549 549 /* Add entry to parent directory */ 550 550 errno_t rc = ext4_directory_add_entry(parent->inode_ref, name, … … 552 552 if (rc != EOK) 553 553 return rc; 554 554 555 555 /* Fill new dir -> add '.' and '..' entries */ 556 556 if (ext4_inode_is_type(fs->superblock, child->inode_ref->inode, … … 562 562 return rc; 563 563 } 564 564 565 565 rc = ext4_directory_add_entry(child->inode_ref, "..", 566 566 parent->inode_ref); … … 570 570 return rc; 571 571 } 572 572 573 573 /* Initialize directory index if supported */ 574 574 if (ext4_superblock_has_feature_compatible(fs->superblock, … … 577 577 if (rc != EOK) 578 578 return rc; 579 579 580 580 ext4_inode_set_flag(child->inode_ref->inode, 581 581 EXT4_INODE_FLAG_INDEX); 582 582 child->inode_ref->dirty = true; 583 583 } 584 584 585 585 uint16_t parent_links = 586 586 ext4_inode_get_links_count(parent->inode_ref->inode); 587 587 parent_links++; 588 588 ext4_inode_set_links_count(parent->inode_ref->inode, parent_links); 589 589 590 590 parent->inode_ref->dirty = true; 591 591 } 592 592 593 593 uint16_t child_links = 594 594 ext4_inode_get_links_count(child->inode_ref->inode); 595 595 child_links++; 596 596 ext4_inode_set_links_count(child->inode_ref->inode, child_links); 597 597 598 598 child->inode_ref->dirty = true; 599 599 600 600 return EOK; 601 601 } … … 616 616 if (rc != EOK) 617 617 return rc; 618 618 619 619 /* Cannot unlink non-empty node */ 620 620 if (has_children) 621 621 return ENOTEMPTY; 622 622 623 623 /* Remove entry from parent directory */ 624 624 ext4_inode_ref_t *parent = EXT4_NODE(pfn)->inode_ref; … … 626 626 if (rc != EOK) 627 627 return rc; 628 628 629 629 /* Decrement links count */ 630 630 ext4_inode_ref_t *child_inode_ref = EXT4_NODE(cfn)->inode_ref; 631 631 632 632 uint32_t lnk_count = 633 633 ext4_inode_get_links_count(child_inode_ref->inode); 634 634 lnk_count--; 635 635 636 636 /* If directory - handle links from parent */ 637 637 if ((lnk_count <= 1) && (ext4_is_directory(cfn))) { 638 638 assert(lnk_count == 1); 639 639 640 640 lnk_count--; 641 641 642 642 ext4_inode_ref_t *parent_inode_ref = EXT4_NODE(pfn)->inode_ref; 643 643 644 644 uint32_t parent_lnk_count = ext4_inode_get_links_count( 645 645 parent_inode_ref->inode); 646 646 647 647 parent_lnk_count--; 648 648 ext4_inode_set_links_count(parent_inode_ref->inode, parent_lnk_count); 649 649 650 650 parent->dirty = true; 651 651 } … … 659 659 * parent->dirty = true; 660 660 */ 661 661 662 662 /* 663 663 * TODO: Update timestamp for inode. … … 666 666 * (uint32_t) now); 667 667 */ 668 668 669 669 ext4_inode_set_links_count(child_inode_ref->inode, lnk_count); 670 670 child_inode_ref->dirty = true; 671 671 672 672 return EOK; 673 673 } … … 687 687 ext4_node_t *enode = EXT4_NODE(fn); 688 688 ext4_filesystem_t *fs = enode->instance->filesystem; 689 689 690 690 /* Check if node is directory */ 691 691 if (!ext4_inode_is_type(fs->superblock, enode->inode_ref->inode, … … 694 694 return EOK; 695 695 } 696 696 697 697 ext4_directory_iterator_t it; 698 698 errno_t rc = ext4_directory_iterator_init(&it, enode->inode_ref, 0); 699 699 if (rc != EOK) 700 700 return rc; 701 701 702 702 /* Find a non-empty directory entry */ 703 703 bool found = false; … … 712 712 } 713 713 } 714 714 715 715 rc = ext4_directory_iterator_next(&it); 716 716 if (rc != EOK) { … … 719 719 } 720 720 } 721 721 722 722 rc = ext4_directory_iterator_fini(&it); 723 723 if (rc != EOK) 724 724 return rc; 725 725 726 726 *has_children = found; 727 727 728 728 return EOK; 729 729 } … … 767 767 ext4_node_t *enode = EXT4_NODE(fn); 768 768 uint32_t lnkcnt = ext4_inode_get_links_count(enode->inode_ref->inode); 769 769 770 770 if (ext4_is_directory(fn)) { 771 771 if (lnkcnt > 1) … … 774 774 return 0; 775 775 } 776 776 777 777 /* For regular files return real links count */ 778 778 return lnkcnt; … … 790 790 ext4_node_t *enode = EXT4_NODE(fn); 791 791 ext4_superblock_t *sb = enode->instance->filesystem->superblock; 792 792 793 793 return ext4_inode_is_type(sb, enode->inode_ref->inode, 794 794 EXT4_INODE_MODE_DIRECTORY); … … 806 806 ext4_node_t *enode = EXT4_NODE(fn); 807 807 ext4_superblock_t *sb = enode->instance->filesystem->superblock; 808 808 809 809 return ext4_inode_is_type(sb, enode->inode_ref->inode, 810 810 EXT4_INODE_MODE_FILE); … … 928 928 { 929 929 ext4_filesystem_t *fs; 930 930 931 931 /* Allocate instance structure */ 932 932 ext4_instance_t *inst = (ext4_instance_t *) … … 934 934 if (inst == NULL) 935 935 return ENOMEM; 936 936 937 937 enum cache_mode cmode; 938 938 if (str_cmp(opts, "wtcache") == 0) … … 940 940 else 941 941 cmode = CACHE_MODE_WB; 942 942 943 943 /* Initialize instance */ 944 944 link_initialize(&inst->link); 945 945 inst->service_id = service_id; 946 946 inst->open_nodes_count = 0; 947 947 948 948 /* Initialize the filesystem */ 949 949 aoff64_t rnsize; … … 953 953 return rc; 954 954 } 955 955 956 956 /* Add instance to the list */ 957 957 fibril_mutex_lock(&instance_list_mutex); 958 958 list_append(&inst->link, &instance_list); 959 959 fibril_mutex_unlock(&instance_list_mutex); 960 960 961 961 *index = EXT4_INODE_ROOT_INDEX; 962 962 *size = rnsize; 963 963 964 964 return EOK; 965 965 } … … 980 980 if (rc != EOK) 981 981 return rc; 982 982 983 983 fibril_mutex_lock(&open_nodes_lock); 984 984 985 985 if (inst->open_nodes_count != 0) { 986 986 fibril_mutex_unlock(&open_nodes_lock); 987 987 return EBUSY; 988 988 } 989 989 990 990 /* Remove the instance from the list */ 991 991 fibril_mutex_lock(&instance_list_mutex); 992 992 list_remove(&inst->link); 993 993 fibril_mutex_unlock(&instance_list_mutex); 994 994 995 995 fibril_mutex_unlock(&open_nodes_lock); 996 996 997 997 rc = ext4_filesystem_close(inst->filesystem); 998 998 if (rc != EOK) { … … 1028 1028 return EINVAL; 1029 1029 } 1030 1030 1031 1031 ext4_instance_t *inst; 1032 1032 errno_t rc = ext4_instance_get(service_id, &inst); … … 1035 1035 return rc; 1036 1036 } 1037 1037 1038 1038 /* Load i-node */ 1039 1039 ext4_inode_ref_t *inode_ref; … … 1043 1043 return rc; 1044 1044 } 1045 1045 1046 1046 /* Read from i-node by type */ 1047 1047 if (ext4_inode_is_type(inst->filesystem->superblock, inode_ref->inode, … … 1058 1058 rc = ENOTSUP; 1059 1059 } 1060 1060 1061 1061 errno_t const rc2 = ext4_filesystem_put_inode_ref(inode_ref); 1062 1062 1063 1063 return rc == EOK ? rc2 : rc; 1064 1064 } … … 1076 1076 if ((name_size == 1) && (name[0] == '.')) 1077 1077 return true; 1078 1078 1079 1079 if ((name_size == 2) && (name[0] == '.') && (name[1] == '.')) 1080 1080 return true; 1081 1081 1082 1082 return false; 1083 1083 } … … 1104 1104 return rc; 1105 1105 } 1106 1106 1107 1107 /* 1108 1108 * Find next interesting directory entry. … … 1114 1114 if (it.current->inode == 0) 1115 1115 goto skip; 1116 1116 1117 1117 uint16_t name_size = ext4_directory_entry_ll_get_name_length( 1118 1118 inst->filesystem->superblock, it.current); 1119 1119 1120 1120 /* Skip . and .. */ 1121 1121 if (ext4_is_dots(it.current->name, name_size)) 1122 1122 goto skip; 1123 1123 1124 1124 /* 1125 1125 * The on-disk entry does not contain \0 at the end … … 1133 1133 return ENOMEM; 1134 1134 } 1135 1135 1136 1136 memcpy(buf, &it.current->name, name_size); 1137 1137 *(buf + name_size) = 0; 1138 1138 found = true; 1139 1139 1140 1140 (void) async_data_read_finalize(callid, buf, name_size + 1); 1141 1141 free(buf); 1142 1142 break; 1143 1143 1144 1144 skip: 1145 1145 rc = ext4_directory_iterator_next(&it); … … 1150 1150 } 1151 1151 } 1152 1152 1153 1153 uint64_t next; 1154 1154 if (found) { … … 1156 1156 if (rc != EOK) 1157 1157 return rc; 1158 1158 1159 1159 next = it.current_offset; 1160 1160 } 1161 1161 1162 1162 rc = ext4_directory_iterator_fini(&it); 1163 1163 if (rc != EOK) 1164 1164 return rc; 1165 1165 1166 1166 /* Prepare return values */ 1167 1167 if (found) { … … 1191 1191 ext4_superblock_t *sb = inst->filesystem->superblock; 1192 1192 uint64_t file_size = ext4_inode_get_size(sb, inode_ref->inode); 1193 1193 1194 1194 if (pos >= file_size) { 1195 1195 /* Read 0 bytes successfully */ … … 1198 1198 return EOK; 1199 1199 } 1200 1200 1201 1201 /* For now, we only read data from one block at a time */ 1202 1202 uint32_t block_size = ext4_superblock_get_block_size(sb); … … 1204 1204 uint32_t offset_in_block = pos % block_size; 1205 1205 uint32_t bytes = min(block_size - offset_in_block, size); 1206 1206 1207 1207 /* Handle end of file */ 1208 1208 if (pos + bytes > file_size) 1209 1209 bytes = file_size - pos; 1210 1210 1211 1211 /* Get the real block number */ 1212 1212 uint32_t fs_block; … … 1217 1217 return rc; 1218 1218 } 1219 1219 1220 1220 /* 1221 1221 * Check for sparse file. … … 1231 1231 return ENOMEM; 1232 1232 } 1233 1233 1234 1234 memset(buffer, 0, bytes); 1235 1235 1236 1236 rc = async_data_read_finalize(callid, buffer, bytes); 1237 1237 *rbytes = bytes; 1238 1238 1239 1239 free(buffer); 1240 1240 return rc; 1241 1241 } 1242 1242 1243 1243 /* Usual case - we need to read a block from device */ 1244 1244 block_t *block; … … 1248 1248 return rc; 1249 1249 } 1250 1250 1251 1251 assert(offset_in_block + bytes <= block_size); 1252 1252 rc = async_data_read_finalize(callid, block->data + offset_in_block, bytes); … … 1255 1255 return rc; 1256 1256 } 1257 1257 1258 1258 rc = block_put(block); 1259 1259 if (rc != EOK) 1260 1260 return rc; 1261 1261 1262 1262 *rbytes = bytes; 1263 1263 return EOK; … … 1282 1282 if (rc != EOK) 1283 1283 return rc; 1284 1284 1285 1285 ipc_callid_t callid; 1286 1286 size_t len; … … 1290 1290 goto exit; 1291 1291 } 1292 1292 1293 1293 ext4_node_t *enode = EXT4_NODE(fn); 1294 1294 ext4_filesystem_t *fs = enode->instance->filesystem; 1295 1295 1296 1296 uint32_t block_size = ext4_superblock_get_block_size(fs->superblock); 1297 1297 1298 1298 /* Prevent writing to more than one block */ 1299 1299 uint32_t bytes = min(len, block_size - (pos % block_size)); 1300 1300 1301 1301 int flags = BLOCK_FLAGS_NONE; 1302 1302 if (bytes == block_size) 1303 1303 flags = BLOCK_FLAGS_NOREAD; 1304 1304 1305 1305 uint32_t iblock = pos / block_size; 1306 1306 uint32_t fblock; 1307 1307 1308 1308 /* Load inode */ 1309 1309 ext4_inode_ref_t *inode_ref = enode->inode_ref; … … 1314 1314 goto exit; 1315 1315 } 1316 1316 1317 1317 /* Check for sparse file */ 1318 1318 if (fblock == 0) { … … 1323 1323 ext4_inode_get_size(fs->superblock, inode_ref->inode) / 1324 1324 block_size; 1325 1325 1326 1326 while (last_iblock < iblock) { 1327 1327 rc = ext4_extent_append_block(inode_ref, &last_iblock, … … 1332 1332 } 1333 1333 } 1334 1334 1335 1335 rc = ext4_extent_append_block(inode_ref, &last_iblock, 1336 1336 &fblock, false); … … 1345 1345 goto exit; 1346 1346 } 1347 1347 1348 1348 rc = ext4_filesystem_set_inode_data_block_index(inode_ref, 1349 1349 iblock, fblock); … … 1354 1354 } 1355 1355 } 1356 1356 1357 1357 flags = BLOCK_FLAGS_NOREAD; 1358 1358 inode_ref->dirty = true; 1359 1359 } 1360 1360 1361 1361 /* Load target block */ 1362 1362 block_t *write_block; … … 1366 1366 goto exit; 1367 1367 } 1368 1368 1369 1369 if (flags == BLOCK_FLAGS_NOREAD) 1370 1370 memset(write_block->data, 0, block_size); … … 1419 1419 if (rc != EOK) 1420 1420 return rc; 1421 1421 1422 1422 ext4_node_t *enode = EXT4_NODE(fn); 1423 1423 ext4_inode_ref_t *inode_ref = enode->inode_ref; 1424 1424 1425 1425 rc = ext4_filesystem_truncate_inode(inode_ref, new_size); 1426 1426 errno_t const rc2 = ext4_node_put(fn); 1427 1427 1428 1428 return rc == EOK ? rc2 : rc; 1429 1429 } … … 1456 1456 if (rc != EOK) 1457 1457 return rc; 1458 1458 1459 1459 /* Destroy the inode */ 1460 1460 return ext4_destroy_node(fn); … … 1473 1473 if (rc != EOK) 1474 1474 return rc; 1475 1475 1476 1476 ext4_node_t *enode = EXT4_NODE(fn); 1477 1477 enode->inode_ref->dirty = true; 1478 1478 1479 1479 return ext4_node_put(fn); 1480 1480 }
Note:
See TracChangeset
for help on using the changeset viewer.