Changeset c02d098 in mainline for uspace/lib/label/src/mbr.c
- Timestamp:
- 2015-07-29T20:35:40Z (9 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 100b1d1
- Parents:
- c43db5f
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/label/src/mbr.c
rc43db5f rc02d098 44 44 45 45 static int mbr_open(service_id_t, label_t **); 46 static int mbr_open_ext(label_t *); 46 47 static int mbr_create(service_id_t, label_t **); 47 48 static void mbr_close(label_t *); … … 57 58 static int mbr_part_to_pte(label_part_t *, mbr_pte_t *); 58 59 static int mbr_pte_to_part(label_t *, mbr_pte_t *, int); 60 static int mbr_pte_to_log_part(label_t *, uint64_t, mbr_pte_t *); 61 static void mbr_log_part_to_ptes(label_part_t *, mbr_pte_t *, mbr_pte_t *); 59 62 static int mbr_pte_update(label_t *, mbr_pte_t *, int); 63 static int mbr_log_part_insert(label_t *, label_part_t *); 64 static int mbr_ebr_create(label_t *, label_part_t *); 65 static int mbr_ebr_delete(label_t *, label_part_t *); 66 static int mbr_ebr_update_next(label_t *, label_part_t *); 67 static void mbr_update_log_indices(label_t *); 60 68 61 69 label_ops_t mbr_label_ops = { … … 132 140 } 133 141 134 label->ext_part_idx = -1; 142 143 label->ext_part = NULL; 135 144 for (entry = 0; entry < mbr_nprimary; entry++) { 136 145 eptr = &mbr->pte[entry]; … … 150 159 label->anblocks = nblocks - mbr_ablock0; 151 160 label->pri_entries = mbr_nprimary; 161 162 if (label->ext_part != NULL) { 163 /* Open extended partition */ 164 rc = mbr_open_ext(label); 165 if (rc != EOK) 166 goto error; 167 } 168 152 169 *rlabel = label; 153 170 return EOK; 154 171 error: 155 172 free(mbr); 156 free(label); 173 mbr_close(label); 174 return rc; 175 } 176 177 /** Open extended partition */ 178 static int mbr_open_ext(label_t *label) 179 { 180 mbr_br_block_t *ebr = NULL; 181 mbr_pte_t *ethis; 182 mbr_pte_t *enext; 183 uint64_t ebr_b0; 184 uint64_t ebr_nblocks_min; 185 uint64_t ebr_nblocks_max; 186 uint64_t pebr_b0; 187 uint64_t pebr_nblocks; 188 uint64_t pb0; 189 uint64_t pnblocks; 190 uint64_t ep_b0; 191 int rc; 192 193 ebr = calloc(1, label->block_size); 194 if (ebr == NULL) { 195 rc = ENOMEM; 196 goto error; 197 } 198 199 /* First block of extended partition */ 200 ep_b0 = label->ext_part->block0; 201 202 /* First block of current EBR */ 203 ebr_b0 = label->ext_part->block0; 204 205 /* 206 * We don't have bounds for the first EBR, so for purpose of 207 * verification let's say it contains at least one block and 208 * at most all blocks from the extended partition. 209 */ 210 ebr_nblocks_min = 1; 211 ebr_nblocks_max = label->ext_part->nblocks; 212 213 while (true) { 214 /* Read EBR */ 215 rc = block_read_direct(label->svc_id, ebr_b0, 1, ebr); 216 if (rc != EOK) { 217 rc = EIO; 218 goto error; 219 } 220 221 ethis = &ebr->pte[mbr_ebr_pte_this]; 222 enext = &ebr->pte[mbr_ebr_pte_next]; 223 224 pb0 = ebr_b0 + uint32_t_le2host(ethis->first_lba); 225 pnblocks = uint32_t_le2host(ethis->length); 226 227 if (ethis->ptype == mbr_pt_unused || pnblocks == 0) 228 break; 229 230 /* Verify partition lies within the range of EBR */ 231 if (pb0 + pnblocks > ebr_b0 + ebr_nblocks_max) { 232 rc = EIO; 233 goto error; 234 } 235 236 /* Create partition structure */ 237 rc = mbr_pte_to_log_part(label, ebr_b0, ethis); 238 if (rc != EOK) { 239 rc= EIO; 240 goto error; 241 } 242 243 /* Save previous EBR range */ 244 pebr_b0 = ebr_b0; 245 pebr_nblocks = ebr_nblocks_min; 246 247 /* Proceed to next EBR */ 248 ebr_b0 = ep_b0 + uint32_t_le2host(enext->first_lba); 249 ebr_nblocks_min = uint32_t_le2host(enext->length); 250 ebr_nblocks_max = ebr_nblocks_min; 251 252 if (enext->ptype == mbr_pt_unused || ebr_nblocks_min == 0) 253 break; 254 255 /* Verify next EBR does not overlap this EBR */ 256 if (ebr_b0 < pebr_b0 + pebr_nblocks) { 257 rc = EIO; 258 goto error; 259 } 260 261 /* Verify next EBR does not extend beyond end of label */ 262 if (ebr_b0 + ebr_nblocks_max > label->ablock0 + label->anblocks) { 263 rc = EIO; 264 goto error; 265 } 266 } 267 268 free(ebr); 269 return EOK; 270 error: 271 /* Note that logical partitions need to be deleted by caller */ 272 free(ebr); 157 273 return rc; 158 274 } … … 215 331 label->anblocks = nblocks - mbr_ablock0; 216 332 label->pri_entries = mbr_nprimary; 217 label->ext_part _idx = -1;333 label->ext_part = NULL; 218 334 219 335 *rlabel = label; … … 228 344 { 229 345 label_part_t *part; 346 347 if (label == NULL) 348 return; 230 349 231 350 part = mbr_part_first(label); … … 291 410 linfo->flags |= lf_can_create_pri; 292 411 /* Can create extended if there is a free slot and no extended */ 293 if ((linfo->flags & lf_can_create_pri) != 0 && label->ext_part _idx < 0)412 if ((linfo->flags & lf_can_create_pri) != 0 && label->ext_part == NULL) 294 413 linfo->flags |= lf_can_create_ext; 295 414 /* Can create logical if there is an extended partition */ 296 if (label->ext_part _idx >= 0)415 if (label->ext_part != NULL) 297 416 linfo->flags |= lf_can_create_log; 298 417 … … 323 442 324 443 return list_get_instance(link, label_part_t, lparts); 444 } 445 446 static label_part_t *mbr_log_part_first(label_t *label) 447 { 448 link_t *link; 449 450 link = list_first(&label->log_parts); 451 if (link == NULL) 452 return NULL; 453 454 return list_get_instance(link, label_part_t, llog); 455 } 456 457 static label_part_t *mbr_log_part_next(label_part_t *part) 458 { 459 link_t *link; 460 461 link = list_next(&part->llog, &part->label->log_parts); 462 if (link == NULL) 463 return NULL; 464 465 return list_get_instance(link, label_part_t, llog); 466 } 467 468 static label_part_t *mbr_log_part_prev(label_part_t *part) 469 { 470 link_t *link; 471 472 link = list_prev(&part->llog, &part->label->log_parts); 473 if (link == NULL) 474 return NULL; 475 476 return list_get_instance(link, label_part_t, llog); 325 477 } 326 478 … … 346 498 { 347 499 label_part_t *part; 500 label_part_t *prev; 501 label_part_t *next; 348 502 mbr_pte_t pte; 349 503 int rc; … … 360 514 part->block0 = pspec->block0; 361 515 part->nblocks = pspec->nblocks; 516 part->hdr_blocks = pspec->hdr_blocks; 362 517 363 518 switch (pspec->pkind) { … … 371 526 goto error; 372 527 } 373 if (label->ext_part _idx >= 0) {528 if (label->ext_part != NULL) { 374 529 rc = EEXISTS; 375 530 goto error; … … 377 532 break; 378 533 case lpk_logical: 534 log_msg(LOG_DEFAULT, LVL_NOTE, "check index"); 379 535 part->ptype = pspec->ptype; 380 536 if (pspec->index != 0) { … … 394 550 } 395 551 552 if (pspec->hdr_blocks != 0) { 553 rc = EINVAL; 554 goto error; 555 } 556 396 557 rc = mbr_part_to_pte(part, &pte); 397 558 if (rc != EOK) { … … 410 571 411 572 if (pspec->pkind == lpk_extended) 412 label->ext_part _idx = pspec->index - 1;573 label->ext_part = part; 413 574 } else { 414 575 /* Logical partition */ 415 rc = ENOTSUP; 416 goto error; 417 } 418 576 577 log_msg(LOG_DEFAULT, LVL_NOTE, "call mbr_log_part_insert"); 578 rc = mbr_log_part_insert(label, part); 579 if (rc != EOK) 580 goto error; 581 582 log_msg(LOG_DEFAULT, LVL_NOTE, "call mbr_ebr_create"); 583 /* Create EBR for new partition */ 584 rc = mbr_ebr_create(label, part); 585 if (rc != EOK) 586 goto error; 587 588 prev = mbr_log_part_prev(part); 589 if (prev != NULL) { 590 log_msg(LOG_DEFAULT, LVL_NOTE, "update next"); 591 /* Update 'next' PTE in EBR of previous partition */ 592 rc = mbr_ebr_update_next(label, prev); 593 if (rc != EOK) { 594 log_msg(LOG_DEFAULT, LVL_NOTE, "failed to update next"); 595 goto error; 596 } 597 } else { 598 log_msg(LOG_DEFAULT, LVL_NOTE, "relocate first EBR"); 599 /* New partition is now the first one */ 600 next = mbr_log_part_next(part); 601 if (next != NULL) { 602 /* 603 * Create new, relocated EBR for the former 604 * first partition 605 */ 606 next->hdr_blocks = pspec->hdr_blocks; 607 rc = mbr_ebr_create(label, next); 608 if (rc != EOK) 609 goto error; 610 } 611 } 612 613 /* This also sets index for the new partition. */ 614 mbr_update_log_indices(label); 615 } 616 617 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_part_create success"); 419 618 *rpart = part; 420 619 return EOK; … … 427 626 { 428 627 mbr_pte_t pte; 628 label_part_t *prev; 429 629 int rc; 430 630 431 /* Prepare unused partition table entry */ 432 mbr_unused_pte(&pte); 433 434 /* Modify partition table */ 435 rc = mbr_pte_update(part->label, &pte, part->index - 1); 436 if (rc != EOK) 437 return EIO; 438 439 /* If it was the extended partition, clear ext. part. index */ 440 if (part->index - 1 == part->label->ext_part_idx) 441 part->label->ext_part_idx = -1; 631 if (link_used(&part->lpri)) { 632 /* Primary/extended partition */ 633 634 /* Prepare unused partition table entry */ 635 mbr_unused_pte(&pte); 636 637 /* Modify partition table */ 638 rc = mbr_pte_update(part->label, &pte, part->index - 1); 639 if (rc != EOK) 640 return EIO; 641 642 /* If it was the extended partition, clear ext. part. pointer */ 643 if (part == part->label->ext_part) 644 part->label->ext_part = NULL; 645 646 list_remove(&part->lpri); 647 } else { 648 /* Logical partition */ 649 650 prev = mbr_log_part_prev(part); 651 if (prev != NULL) { 652 /* Update next link in previous EBR */ 653 list_remove(&part->llog); 654 655 rc = mbr_ebr_update_next(part->label, prev); 656 if (rc != EOK) { 657 /* Roll back */ 658 list_insert_after(&part->llog, &prev->llog); 659 return EIO; 660 } 661 } else { 662 list_remove(&part->llog); 663 } 664 665 /* Delete EBR */ 666 mbr_ebr_delete(part->label, part); 667 } 442 668 443 669 list_remove(&part->lparts); 444 if (link_used(&part->lpri))445 list_remove(&part->lpri);446 if (link_used(&part->llog))447 list_remove(&part->llog);448 670 free(part); 449 671 return EOK; … … 507 729 508 730 if (pte->ptype == mbr_pt_extended) 509 label->ext_part_idx = index - 1; 510 return EOK; 731 label->ext_part = part; 732 return EOK; 733 } 734 735 static int mbr_pte_to_log_part(label_t *label, uint64_t ebr_b0, 736 mbr_pte_t *pte) 737 { 738 label_part_t *part; 739 uint32_t block0; 740 uint32_t nblocks; 741 size_t nlparts; 742 743 block0 = ebr_b0 + uint32_t_le2host(pte->first_lba); 744 nblocks = uint32_t_le2host(pte->length); 745 746 if (pte->ptype == mbr_pt_unused || nblocks == 0) 747 return EOK; 748 749 part = calloc(1, sizeof(label_part_t)); 750 if (part == NULL) 751 return ENOMEM; 752 753 nlparts = list_count(&label->log_parts); 754 755 part->ptype = pte->ptype; 756 part->index = mbr_nprimary + 1 + nlparts; 757 part->block0 = block0; 758 part->nblocks = nblocks; 759 760 part->label = label; 761 list_append(&part->lparts, &label->parts); 762 list_append(&part->llog, &label->log_parts); 763 764 return EOK; 765 } 766 #include <stdio.h> 767 static void mbr_log_part_to_ptes(label_part_t *part, mbr_pte_t *pthis, 768 mbr_pte_t *pnext) 769 { 770 label_part_t *next; 771 uint64_t ep_b0; 772 uint64_t totsize; 773 774 /* First block of extended partition */ 775 ep_b0 = part->label->ext_part->block0; 776 777 assert(link_used(&part->llog)); 778 assert(part->block0 >= ep_b0); 779 printf("part->hdr_blocks = %" PRIu64 "\n", part->hdr_blocks); 780 printf("part->block0 = %" PRIu64 "\n", part->block0); 781 printf("ep_b0 = %" PRIu64 "\n", ep_b0); 782 assert(part->hdr_blocks <= part->block0 - ep_b0); 783 784 /* 'This' EBR entry */ 785 if (pthis != NULL) { 786 memset(pthis, 0, sizeof(mbr_pte_t)); 787 pthis->ptype = part->ptype; 788 pthis->first_lba = host2uint32_t_le(part->hdr_blocks); 789 pthis->length = host2uint32_t_le(part->nblocks); 790 } 791 792 /* 'Next' EBR entry */ 793 if (pnext != NULL) { 794 next = mbr_part_next(part); 795 796 memset(pnext, 0, sizeof(mbr_pte_t)); 797 if (next != NULL) { 798 /* Total size of EBR + partition */ 799 totsize = next->hdr_blocks + next->nblocks; 800 801 pnext->ptype = mbr_pt_extended; 802 pnext->first_lba = host2uint32_t_le(next->block0 - 803 next->hdr_blocks - ep_b0); 804 pnext->length = host2uint32_t_le(totsize); 805 } 806 } 511 807 } 512 808 … … 546 842 } 547 843 844 /** Insert logical partition into logical partition list. */ 845 static int mbr_log_part_insert(label_t *label, label_part_t *part) 846 { 847 label_part_t *cur; 848 849 cur = mbr_log_part_first(label); 850 while (cur != NULL) { 851 if (cur->block0 + cur->nblocks > part->block0) 852 break; 853 cur = mbr_log_part_next(part); 854 } 855 856 if (cur != NULL) 857 list_insert_before(&part->llog, &cur->llog); 858 else 859 list_append(&part->llog, &label->log_parts); 860 861 return EOK; 862 } 863 864 /** Create EBR for partition. */ 865 static int mbr_ebr_create(label_t *label, label_part_t *part) 866 { 867 mbr_br_block_t *br; 868 uint64_t ba; 869 int rc; 870 871 br = calloc(1, label->block_size); 872 if (br == NULL) 873 return ENOMEM; 874 875 mbr_log_part_to_ptes(part, &br->pte[mbr_ebr_pte_this], 876 &br->pte[mbr_ebr_pte_next]); 877 br->signature = host2uint16_t_le(mbr_br_signature); 878 879 ba = part->block0 - part->hdr_blocks; 880 881 log_msg(LOG_DEFAULT, LVL_NOTE, "Write EBR to ba=%" PRIu64, ba); 882 rc = block_write_direct(label->svc_id, ba, 1, br); 883 if (rc != EOK) { 884 rc = EIO; 885 goto error; 886 } 887 888 free(br); 889 return EOK; 890 error: 891 free(br); 892 return rc; 893 } 894 895 static int mbr_ebr_delete(label_t *label, label_part_t *part) 896 { 897 mbr_br_block_t *br; 898 uint64_t ba; 899 int rc; 900 901 br = calloc(1, label->block_size); 902 if (br == NULL) 903 return ENOMEM; 904 905 ba = part->block0 - part->hdr_blocks; 906 907 rc = block_write_direct(label->svc_id, ba, 1, br); 908 if (rc != EOK) { 909 rc = EIO; 910 goto error; 911 } 912 913 free(br); 914 return EOK; 915 error: 916 free(br); 917 return rc; 918 } 919 920 /** Update 'next' PTE in EBR of partition. */ 921 static int mbr_ebr_update_next(label_t *label, label_part_t *part) 922 { 923 mbr_br_block_t *br; 924 uint64_t ba; 925 uint16_t sgn; 926 int rc; 927 928 ba = part->block0 - part->hdr_blocks; 929 930 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_ebr_update_next ba=%" PRIu64, 931 ba); 932 933 br = calloc(1, label->block_size); 934 if (br == NULL) 935 return ENOMEM; 936 937 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_ebr_update_next read ba=%" PRIu64, 938 ba); 939 940 rc = block_read_direct(label->svc_id, ba, 1, br); 941 if (rc != EOK) { 942 rc = EIO; 943 goto error; 944 } 945 946 /* Verify boot record signature */ 947 sgn = uint16_t_le2host(br->signature); 948 if (sgn != mbr_br_signature) { 949 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_ebr_update_next signature error"); 950 rc = EIO; 951 goto error; 952 } 953 954 mbr_log_part_to_ptes(part, NULL, &br->pte[mbr_ebr_pte_next]); 955 956 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_ebr_update_next write ba=%" PRIu64, 957 ba); 958 959 rc = block_write_direct(label->svc_id, ba, 1, br); 960 if (rc != EOK) { 961 rc = EIO; 962 goto error; 963 } 964 965 log_msg(LOG_DEFAULT, LVL_NOTE, "mbr_ebr_update_next success"); 966 967 free(br); 968 return EOK; 969 error: 970 free(br); 971 return rc; 972 } 973 974 /** Update indices of logical partitions. 975 * 976 * Logical partition indices are unstable, i.e. they can change during 977 * the lifetime of a logical partition. Since the index corresponds to the 978 * position of the partition in order of block address, anytime a partition 979 * is created or deleted, indices of all partitions at higher addresses 980 * change. 981 */ 982 static void mbr_update_log_indices(label_t *label) 983 { 984 label_part_t *part; 985 int idx; 986 987 idx = mbr_nprimary + 1; 988 989 part = mbr_log_part_first(label); 990 while (part != NULL) { 991 part->index = idx++; 992 part = mbr_log_part_next(part); 993 } 994 } 995 548 996 /** @} 549 997 */
Note:
See TracChangeset
for help on using the changeset viewer.