Changeset c02d098 in mainline for uspace/lib/fdisk/src/fdisk.c


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.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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}
Note: See TracChangeset for help on using the changeset viewer.