Changeset c02d098 in mainline


Ignore:
Timestamp:
2015-07-29T20:35:40Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
100b1d1
Parents:
c43db5f
Message:

Most of logical partition support.

Location:
uspace
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/c/include/vbd.h

    rc43db5f rc02d098  
    6969        /** Number of blocks */
    7070        aoff64_t nblocks;
     71        /** Number of header blocks (EBR for logical partitions) */
     72        aoff64_t hdr_blocks;
    7173        /** Partition kind */
    7274        label_pkind_t pkind;
  • uspace/lib/fdisk/include/types/fdisk.h

    rc43db5f rc02d098  
    106106        /** Service ID */
    107107        service_id_t sid;
    108         /** Partitions sorted by index */
    109         list_t parts_idx; /* of fdisk_part_t */
    110         /** Partitions sorted by block address */
    111         list_t parts_ba;
     108        /** All partitions */
     109        list_t parts;
     110        /** Primary partitions sorted by index */
     111        list_t pri_idx; /* of fdisk_part_t */
     112        /** Primary partitions sorted by block address */
     113        list_t pri_ba;
     114        /** Logical partitions sorted by block address */
     115        list_t log_ba;
     116        /** Extended partition or NULL */
     117        struct fdisk_part *ext_part;
    112118        /** Disk info */
    113119        vbd_disk_info_t dinfo;
     120        /** Alignment in blocks */
     121        uint64_t align;
    114122} fdisk_dev_t;
    115123
     
    124132
    125133/** Partition */
    126 typedef struct {
     134typedef struct fdisk_part {
    127135        /** Containing device */
    128136        fdisk_dev_t *dev;
    129         /** Link to fdisk_dev_t.parts_idx */
    130         link_t ldev_idx;
    131         /** Link to fdisk_dev_t.parts_ba */
    132         link_t ldev_ba;
     137        /** Link to fdisk_dev_t.parts */
     138        link_t lparts;
     139        /** Link to fdisk_dev_t.pri_idx */
     140        link_t lpri_idx;
     141        /** Link to fdisk_dev_t.pri_ba */
     142        link_t lpri_ba;
     143        /** Link to fdisk_dev_t.log_ba */
     144        link_t llog_ba;
    133145        /** Capacity */
    134146        fdisk_cap_t capacity;
  • uspace/lib/fdisk/src/fdisk.c

    rc43db5f rc02d098  
    6060static int fdisk_part_spec_prepare(fdisk_dev_t *, fdisk_part_spec_t *,
    6161    vbd_part_spec_t *);
     62static void fdisk_pri_part_insert_lists(fdisk_dev_t *, fdisk_part_t *);
     63static void fdisk_log_part_insert_lists(fdisk_dev_t *, fdisk_part_t *);
     64static int fdisk_update_dev_info(fdisk_dev_t *);
    6265
    6366static void fdisk_dev_info_delete(fdisk_dev_info_t *info)
     
    252255    fdisk_part_t **rpart)
    253256{
    254         fdisk_part_t *part, *p;
     257        fdisk_part_t *part;
    255258        vbd_part_info_t pinfo;
    256         link_t *link;
    257259        int rc;
    258260
     
    273275        part->pkind = pinfo.pkind;
    274276
    275         /* Insert to list by block address */
    276         link = list_first(&dev->parts_ba);
    277         while (link != NULL) {
    278                 p = list_get_instance(link, fdisk_part_t, ldev_ba);
    279                 if (p->block0 > part->block0) {
    280                         list_insert_before(&part->ldev_ba, &p->ldev_ba);
    281                         break;
    282                 }
    283 
    284                 link = list_next(link, &dev->parts_ba);
    285         }
    286 
    287         if (link == NULL)
    288                 list_append(&part->ldev_ba, &dev->parts_ba);
    289 
    290         /* Insert to list by index */
    291         link = list_first(&dev->parts_idx);
    292         while (link != NULL) {
    293                 p = list_get_instance(link, fdisk_part_t, ldev_idx);
    294                 if (p->index > part->index) {
    295                         list_insert_before(&part->ldev_idx, &p->ldev_idx);
    296                         break;
    297                 }
    298 
    299                 link = list_next(link, &dev->parts_idx);
    300         }
    301 
    302         if (link == NULL)
    303                 list_append(&part->ldev_idx, &dev->parts_idx);
     277        switch (part->pkind) {
     278        case lpk_primary:
     279        case lpk_extended:
     280                fdisk_pri_part_insert_lists(dev, part);
     281                break;
     282        case lpk_logical:
     283                fdisk_log_part_insert_lists(dev, part);
     284                break;
     285        }
     286
     287        list_append(&part->lparts, &dev->parts);
     288
     289        if (part->pkind == lpk_extended)
     290                dev->ext_part = part;
    304291
    305292        part->capacity.cunit = cu_byte;
     
    315302}
    316303
     304static void fdisk_pri_part_insert_lists(fdisk_dev_t *dev, fdisk_part_t *part)
     305{
     306        link_t *link;
     307        fdisk_part_t *p;
     308
     309        /* Insert to list by block address */
     310        link = list_first(&dev->pri_ba);
     311        while (link != NULL) {
     312                p = list_get_instance(link, fdisk_part_t, lpri_ba);
     313                if (p->block0 > part->block0) {
     314                        list_insert_before(&part->lpri_ba, &p->lpri_ba);
     315                        break;
     316                }
     317
     318                link = list_next(link, &dev->pri_ba);
     319        }
     320
     321        if (link == NULL)
     322                list_append(&part->lpri_ba, &dev->pri_ba);
     323
     324        /* Insert to list by index */
     325        link = list_first(&dev->pri_idx);
     326        while (link != NULL) {
     327                p = list_get_instance(link, fdisk_part_t, lpri_idx);
     328                if (p->index > part->index) {
     329                        list_insert_before(&part->lpri_idx, &p->lpri_idx);
     330                        break;
     331                }
     332
     333                link = list_next(link, &dev->pri_idx);
     334        }
     335
     336        if (link == NULL)
     337                list_append(&part->lpri_idx, &dev->pri_idx);
     338}
     339
     340static void fdisk_log_part_insert_lists(fdisk_dev_t *dev, fdisk_part_t *part)
     341{
     342        link_t *link;
     343        fdisk_part_t *p;
     344
     345        /* Insert to list by block address */
     346        link = list_first(&dev->log_ba);
     347        while (link != NULL) {
     348                p = list_get_instance(link, fdisk_part_t, llog_ba);
     349                if (p->block0 > part->block0) {
     350                        list_insert_before(&part->llog_ba, &p->llog_ba);
     351                        break;
     352                }
     353
     354                link = list_next(link, &dev->log_ba);
     355        }
     356
     357        if (link == NULL)
     358                list_append(&part->llog_ba, &dev->log_ba);
     359}
    317360
    318361int fdisk_dev_open(fdisk_t *fdisk, service_id_t sid, fdisk_dev_t **rdev)
     
    330373        dev->fdisk = fdisk;
    331374        dev->sid = sid;
    332         list_initialize(&dev->parts_idx);
    333         list_initialize(&dev->parts_ba);
     375        list_initialize(&dev->parts);
     376        list_initialize(&dev->pri_idx);
     377        list_initialize(&dev->pri_ba);
     378        list_initialize(&dev->log_ba);
    334379
    335380        rc = vol_disk_info(fdisk->vol, sid, &vinfo);
     
    345390
    346391        printf("get label info\n");
    347         rc = vbd_disk_info(fdisk->vbd, sid, &dev->dinfo);
     392        rc = fdisk_update_dev_info(dev);
    348393        if (rc != EOK) {
    349394                printf("failed\n");
     
    451496int fdisk_label_create(fdisk_dev_t *dev, label_type_t ltype)
    452497{
    453         return vol_label_create(dev->fdisk->vol, dev->sid, ltype);
     498        int rc;
     499
     500        rc = vol_label_create(dev->fdisk->vol, dev->sid, ltype);
     501        if (rc != EOK)
     502                return rc;
     503
     504        rc = fdisk_update_dev_info(dev);
     505        if (rc != EOK)
     506                return rc;
     507
     508        return EOK;
    454509}
    455510
     
    477532        link_t *link;
    478533
    479         link = list_first(&dev->parts_ba);
     534        link = list_first(&dev->parts);
    480535        if (link == NULL)
    481536                return NULL;
    482537
    483         return list_get_instance(link, fdisk_part_t, ldev_ba);
     538        return list_get_instance(link, fdisk_part_t, lparts);
    484539}
    485540
     
    488543        link_t *link;
    489544
    490         link = list_next(&part->ldev_ba, &part->dev->parts_ba);
     545        link = list_next(&part->lparts, &part->dev->parts);
    491546        if (link == NULL)
    492547                return NULL;
    493548
    494         return list_get_instance(link, fdisk_part_t, ldev_ba);
     549        return list_get_instance(link, fdisk_part_t, lparts);
    495550}
    496551
     
    552607                return EIO;
    553608
    554         list_remove(&part->ldev_ba);
    555         list_remove(&part->ldev_idx);
     609        list_remove(&part->lparts);
     610        if (link_used(&part->lpri_ba))
     611                list_remove(&part->lpri_ba);
     612        if (link_used(&part->lpri_idx))
     613                list_remove(&part->lpri_idx);
     614        if (link_used(&part->llog_ba))
     615                list_remove(&part->llog_ba);
    556616        free(part);
    557617        return EOK;
     
    707767        int nidx;
    708768
    709         link = list_first(&dev->parts_idx);
     769        link = list_first(&dev->pri_idx);
    710770        nidx = 1;
    711771        while (link != NULL) {
    712                 part = list_get_instance(link, fdisk_part_t, ldev_idx);
     772                part = list_get_instance(link, fdisk_part_t, lpri_idx);
    713773                if (part->index > nidx)
    714774                        break;
    715775                nidx = part->index + 1;
    716                 link = list_next(link, &dev->parts_idx);
     776                link = list_next(link, &dev->pri_idx);
    717777        }
    718778
     
    737797        int nba;
    738798
    739         link = list_first(&dev->parts_ba);
     799        link = list_first(&dev->pri_ba);
    740800        nba = dev->dinfo.ablock0;
    741801        while (link != NULL) {
    742                 part = list_get_instance(link, fdisk_part_t, ldev_ba);
     802                part = list_get_instance(link, fdisk_part_t, lpri_ba);
    743803                if (part->block0 - nba >= nblocks)
    744804                        break;
    745805                nba = part->block0 + part->nblocks;
    746                 link = list_next(link, &dev->parts_ba);
     806                link = list_next(link, &dev->pri_ba);
    747807        }
    748808
     
    764824}
    765825
     826/** Get free range of blocks in extended partition.
     827 *
     828 * Get free range of blocks in extended partition that can accomodate
     829 * a partition of at least the specified size plus the header (EBR + padding).
     830 * Returns the header size in blocks, the start and length of the partition.
     831 */
     832static int fdisk_part_get_log_free_range(fdisk_dev_t *dev, aoff64_t nblocks,
     833    aoff64_t *rhdrb, aoff64_t *rblock0, aoff64_t *rnblocks)
     834{
     835        link_t *link;
     836        fdisk_part_t *part;
     837        uint64_t avail;
     838        uint64_t hdrb;
     839        int nba;
     840
     841        /* Number of header blocks */
     842        hdrb = max(1, dev->align);
     843
     844        link = list_first(&dev->log_ba);
     845        nba = dev->ext_part->block0;
     846        while (link != NULL) {
     847                part = list_get_instance(link, fdisk_part_t, llog_ba);
     848                if (part->block0 - nba >= nblocks)
     849                        break;
     850                nba = part->block0 + part->nblocks;
     851                link = list_next(link, &dev->log_ba);
     852        }
     853
     854        if (link != NULL) {
     855                /* Free range before a partition */
     856                avail = part->block0 - nba;
     857        } else {
     858                /* Free range at the end */
     859                avail = dev->ext_part->block0 + dev->ext_part->nblocks - nba;
     860
     861                /* Verify that the range is large enough */
     862                if (avail < hdrb + nblocks)
     863                        return ELIMIT;
     864        }
     865
     866        *rhdrb = hdrb;
     867        *rblock0 = nba + hdrb;
     868        *rnblocks = avail;
     869        return EOK;
     870}
     871
    766872/** Prepare new partition specification for VBD. */
    767873static int fdisk_part_spec_prepare(fdisk_dev_t *dev, fdisk_part_spec_t *pspec,
     
    770876        uint64_t cbytes;
    771877        aoff64_t req_blocks;
     878        aoff64_t fhdr;
    772879        aoff64_t fblock0;
    773880        aoff64_t fnblocks;
     
    778885
    779886//      pspec->fstype
    780         printf("fdisk_part_spec_prepare()\n");
     887        printf("fdisk_part_spec_prepare() - dev=%p pspec=%p vpspec=%p\n", dev, pspec,
     888            vpspec);
     889        printf("fdisk_part_spec_prepare() - block size\n");
    781890        block_size = dev->dinfo.block_size;
     891        printf("fdisk_part_spec_prepare() - cbytes\n");
    782892        cbytes = pspec->capacity.value;
     893        printf("fdisk_part_spec_prepare() - cunit\n");
    783894        for (i = 0; i < pspec->capacity.cunit; i++)
    784895                cbytes = cbytes * 1000;
    785896
     897        printf("fdisk_part_spec_prepare() - req_blocks block_size=%zu\n",
     898            block_size);
    786899        req_blocks = (cbytes + block_size - 1) / block_size;
    787900
    788         rc = fdisk_part_get_free_idx(dev, &index);
     901        printf("fdisk_part_spec_prepare() - switch\n");
     902        switch (pspec->pkind) {
     903        case lpk_primary:
     904        case lpk_extended:
     905                printf("fdisk_part_spec_prepare() - pri/ext\n");
     906                rc = fdisk_part_get_free_idx(dev, &index);
     907                if (rc != EOK)
     908                        return EIO;
     909
     910                printf("fdisk_part_spec_prepare() - get free range\n");
     911                rc = fdisk_part_get_free_range(dev, req_blocks, &fblock0, &fnblocks);
     912                if (rc != EOK)
     913                        return EIO;
     914
     915                printf("fdisk_part_spec_prepare() - memset\n");
     916                memset(vpspec, 0, sizeof(vbd_part_spec_t));
     917                vpspec->index = index;
     918                vpspec->block0 = fblock0;
     919                vpspec->nblocks = req_blocks;
     920                vpspec->pkind = pspec->pkind;
     921                if (pspec->pkind != lpk_extended)
     922                        vpspec->ptype = 42;
     923                break;
     924        case lpk_logical:
     925                printf("fdisk_part_spec_prepare() - log\n");
     926                rc = fdisk_part_get_log_free_range(dev, req_blocks, &fhdr,
     927                    &fblock0, &fnblocks);
     928                if (rc != EOK)
     929                        return EIO;
     930
     931                memset(vpspec, 0, sizeof(vbd_part_spec_t));
     932                vpspec->hdr_blocks = fhdr;
     933                vpspec->block0 = fblock0;
     934                vpspec->nblocks = req_blocks;
     935                vpspec->pkind = lpk_logical;
     936                vpspec->ptype = 42;
     937                break;
     938        }
     939
     940        return EOK;
     941}
     942
     943static int fdisk_update_dev_info(fdisk_dev_t *dev)
     944{
     945        int rc;
     946        size_t align_bytes;
     947
     948        rc = vbd_disk_info(dev->fdisk->vbd, dev->sid, &dev->dinfo);
    789949        if (rc != EOK)
    790950                return EIO;
    791951
    792         rc = fdisk_part_get_free_range(dev, req_blocks, &fblock0, &fnblocks);
    793         if (rc != EOK)
    794                 return EIO;
    795 
    796         memset(vpspec, 0, sizeof(vbd_part_spec_t));
    797         vpspec->index = index;
    798         vpspec->block0 = fblock0;
    799         vpspec->nblocks = req_blocks;
    800         vpspec->pkind = pspec->pkind;
    801         if (pspec->pkind != lpk_extended)
    802                 vpspec->ptype = 42;
    803 
     952        align_bytes = 512; //1024 * 1024; /* 1 MiB */ /* XXX */
     953        dev->align = align_bytes / dev->dinfo.block_size;
     954        if (dev->align < 1)
     955                dev->align = 1;
    804956        return EOK;
    805957}
  • uspace/lib/label/include/std/mbr.h

    rc43db5f rc02d098  
    4949
    5050        /** Boot record signature */
    51         mbr_br_signature = 0xAA55
     51        mbr_br_signature = 0xAA55,
     52
     53        /** EBR PTE slot describing partition corresponding to this EBR */
     54        mbr_ebr_pte_this = 0,
     55        /** EBR PTE slot describing the next EBR */
     56        mbr_ebr_pte_next = 1
    5257};
    5358
  • uspace/lib/label/include/types/liblabel.h

    rc43db5f rc02d098  
    9999        /** Index */
    100100        int index;
     101        /** Number of EBR blocks preceding a logical partition */
     102        aoff64_t hdr_blocks;
    101103        /** First block */
    102104        aoff64_t block0;
     
    117119        /** Number of blocks */
    118120        aoff64_t nblocks;
     121        /** Number of header blocks (EBR for logical partitions) */
     122        aoff64_t hdr_blocks;
    119123        /** Partition kind */
    120124        label_pkind_t pkind;
     
    155159        /** Number of primary partition entries */
    156160        int pri_entries;
    157         /** Index of extended partition or -1 if there is none */
    158         int ext_part_idx;
     161        /** Extended partition or NULL if there is none */
     162        label_part_t *ext_part;
    159163        /** Block size */
    160164        size_t block_size;
  • uspace/lib/label/src/gpt.c

    rc43db5f rc02d098  
    302302        label->pri_entries = num_entries;
    303303        label->block_size = bsize;
    304         label->ext_part_idx = -1;
    305304
    306305        label->lt.gpt.hdr_ba[0] = gpt_hdr_ba;
     
    449448        label->pri_entries = num_entries;
    450449        label->block_size = bsize;
    451         label->ext_part_idx = -1;
    452450
    453451        label->lt.gpt.hdr_ba[0] = hdr_ba[0];
  • uspace/lib/label/src/mbr.c

    rc43db5f rc02d098  
    4444
    4545static int mbr_open(service_id_t, label_t **);
     46static int mbr_open_ext(label_t *);
    4647static int mbr_create(service_id_t, label_t **);
    4748static void mbr_close(label_t *);
     
    5758static int mbr_part_to_pte(label_part_t *, mbr_pte_t *);
    5859static int mbr_pte_to_part(label_t *, mbr_pte_t *, int);
     60static int mbr_pte_to_log_part(label_t *, uint64_t, mbr_pte_t *);
     61static void mbr_log_part_to_ptes(label_part_t *, mbr_pte_t *, mbr_pte_t *);
    5962static int mbr_pte_update(label_t *, mbr_pte_t *, int);
     63static int mbr_log_part_insert(label_t *, label_part_t *);
     64static int mbr_ebr_create(label_t *, label_part_t *);
     65static int mbr_ebr_delete(label_t *, label_part_t *);
     66static int mbr_ebr_update_next(label_t *, label_part_t *);
     67static void mbr_update_log_indices(label_t *);
    6068
    6169label_ops_t mbr_label_ops = {
     
    132140        }
    133141
    134         label->ext_part_idx = -1;
     142
     143        label->ext_part = NULL;
    135144        for (entry = 0; entry < mbr_nprimary; entry++) {
    136145                eptr = &mbr->pte[entry];
     
    150159        label->anblocks = nblocks - mbr_ablock0;
    151160        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
    152169        *rlabel = label;
    153170        return EOK;
    154171error:
    155172        free(mbr);
    156         free(label);
     173        mbr_close(label);
     174        return rc;
     175}
     176
     177/** Open extended partition */
     178static 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;
     270error:
     271        /* Note that logical partitions need to be deleted by caller */
     272        free(ebr);
    157273        return rc;
    158274}
     
    215331        label->anblocks = nblocks - mbr_ablock0;
    216332        label->pri_entries = mbr_nprimary;
    217         label->ext_part_idx = -1;
     333        label->ext_part = NULL;
    218334
    219335        *rlabel = label;
     
    228344{
    229345        label_part_t *part;
     346
     347        if (label == NULL)
     348                return;
    230349
    231350        part = mbr_part_first(label);
     
    291410                linfo->flags |= lf_can_create_pri;
    292411        /* 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)
    294413                linfo->flags |= lf_can_create_ext;
    295414        /* Can create logical if there is an extended partition */
    296         if (label->ext_part_idx >= 0)
     415        if (label->ext_part != NULL)
    297416                linfo->flags |= lf_can_create_log;
    298417
     
    323442
    324443        return list_get_instance(link, label_part_t, lparts);
     444}
     445
     446static 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
     457static 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
     468static 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);
    325477}
    326478
     
    346498{
    347499        label_part_t *part;
     500        label_part_t *prev;
     501        label_part_t *next;
    348502        mbr_pte_t pte;
    349503        int rc;
     
    360514        part->block0 = pspec->block0;
    361515        part->nblocks = pspec->nblocks;
     516        part->hdr_blocks = pspec->hdr_blocks;
    362517
    363518        switch (pspec->pkind) {
     
    371526                        goto error;
    372527                }
    373                 if (label->ext_part_idx >= 0) {
     528                if (label->ext_part != NULL) {
    374529                        rc = EEXISTS;
    375530                        goto error;
     
    377532                break;
    378533        case lpk_logical:
     534                log_msg(LOG_DEFAULT, LVL_NOTE, "check index");
    379535                part->ptype = pspec->ptype;
    380536                if (pspec->index != 0) {
     
    394550                }
    395551
     552                if (pspec->hdr_blocks != 0) {
     553                        rc = EINVAL;
     554                        goto error;
     555                }
     556
    396557                rc = mbr_part_to_pte(part, &pte);
    397558                if (rc != EOK) {
     
    410571
    411572                if (pspec->pkind == lpk_extended)
    412                         label->ext_part_idx = pspec->index - 1;
     573                        label->ext_part = part;
    413574        } else {
    414575                /* 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");
    419618        *rpart = part;
    420619        return EOK;
     
    427626{
    428627        mbr_pte_t pte;
     628        label_part_t *prev;
    429629        int rc;
    430630
    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        }
    442668
    443669        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);
    448670        free(part);
    449671        return EOK;
     
    507729
    508730        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
     735static 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>
     767static 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        }
    511807}
    512808
     
    546842}
    547843
     844/** Insert logical partition into logical partition list. */
     845static 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. */
     865static 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;
     890error:
     891        free(br);
     892        return rc;
     893}
     894
     895static 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;
     915error:
     916        free(br);
     917        return rc;
     918}
     919
     920/** Update 'next' PTE in EBR of partition. */
     921static 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;
     969error:
     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 */
     982static 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
    548996/** @}
    549997 */
  • uspace/srv/bd/vbd/disk.c

    rc43db5f rc02d098  
    346346        info->anblocks = linfo.anblocks;
    347347        info->block_size = disk->block_size;
     348        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_disk_info - block_size=%zu",
     349            info->block_size);
    348350        return EOK;
    349351}
     
    438440        disk->label = label;
    439441        disk->block_size = block_size;
     442        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_label_create: block_size=%zu",
     443            block_size);
    440444        list_initialize(&disk->parts);
    441445
     
    519523        lpspec.block0 = pspec->block0;
    520524        lpspec.nblocks = pspec->nblocks;
     525        lpspec.hdr_blocks = pspec->hdr_blocks;
    521526        lpspec.pkind = pspec->pkind;
    522527        lpspec.ptype = pspec->ptype;
Note: See TracChangeset for help on using the changeset viewer.