Changeset 99c23405 in mainline


Ignore:
Timestamp:
2015-07-04T15:18:06Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
603c1d1f
Parents:
6bc542b
Message:

Persistent partition table modification when creating or deleting partition.

Location:
uspace
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/fdisk/src/fdisk.c

    r6bc542b r99c23405  
    671671                if (part->index > nidx)
    672672                        break;
    673                 nidx = part->index;
     673                nidx = part->index + 1;
    674674                link = list_next(link, &dev->parts_idx);
    675675        }
  • uspace/lib/label/include/types/liblabel.h

    r6bc542b r99c23405  
    9494        /** Number of blocks */
    9595        aoff64_t nblocks;
     96        /** Partition type */
     97        uint64_t ptype;
    9698};
    9799
     
    108110};
    109111
     112typedef struct {
     113        uint64_t ptable_ba[2];
     114        size_t esize;
     115} label_gpt_t;
     116
     117typedef struct {
     118} label_mbr_t;
     119
    110120/** Label instance */
    111121struct label {
     
    114124        /** Label type */
    115125        label_type_t ltype;
     126        /** Block device service ID */
     127        service_id_t svcid;
    116128        /** Partitions */
    117129        list_t parts; /* of label_part_t */
     
    120132        /** Number of blocks that can be allocated */
    121133        aoff64_t anblocks;
     134        /** Number of primary partition entries */
     135        int pri_entries;
     136        /** Block size */
     137        size_t block_size;
     138        union {
     139                label_gpt_t gpt;
     140                label_mbr_t mbr;
     141        } lt;
    122142};
    123143
  • uspace/lib/label/src/gpt.c

    r6bc542b r99c23405  
    5454static int gpt_part_destroy(label_part_t *);
    5555
     56static void gpt_unused_pte(gpt_entry_t *);
     57static int gpt_part_to_pte(label_part_t *, gpt_entry_t *);
    5658static int gpt_pte_to_part(label_t *, gpt_entry_t *, int);
     59static int gpt_pte_update(label_t *, gpt_entry_t *, int);
    5760
    5861const uint8_t efi_signature[8] = {
     
    7780{
    7881        label_t *label = NULL;
    79         gpt_header_t *gpt_hdr = NULL;
     82        gpt_header_t *gpt_hdr[2];
    8083        gpt_entry_t *eptr;
    8184        uint8_t *etable = NULL;
     
    8487        uint32_t esize;
    8588        uint32_t bcnt;
    86         uint64_t ba;
     89        uint64_t ptba[2];
     90        uint64_t h1ba;
    8791        uint32_t entry;
    8892        uint64_t ba_min, ba_max;
    89         int i;
     93        int i, j;
    9094        int rc;
    9195
     96        gpt_hdr[0] = NULL;
     97        gpt_hdr[1] = NULL;
     98
    9299        rc = block_get_bsize(sid, &bsize);
    93100        if (rc != EOK) {
     
    101108        }
    102109
    103         gpt_hdr = calloc(1, bsize);
    104         if (gpt_hdr == NULL) {
     110        gpt_hdr[0] = calloc(1, bsize);
     111        if (gpt_hdr[0] == NULL) {
    105112                rc = ENOMEM;
    106113                goto error;
    107114        }
    108115
    109         rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr);
     116        gpt_hdr[1] = calloc(1, bsize);
     117        if (gpt_hdr[1] == NULL) {
     118                rc = ENOMEM;
     119                goto error;
     120        }
     121
     122        rc = block_read_direct(sid, GPT_HDR_BA, 1, gpt_hdr[0]);
     123        if (rc != EOK) {
     124                rc = EIO;
     125                goto error;
     126        }
     127
     128        h1ba = uint64_t_le2host(gpt_hdr[0]->alternate_lba);
     129
     130        rc = block_read_direct(sid, h1ba, 1, gpt_hdr[1]);
    110131        if (rc != EOK) {
    111132                rc = EIO;
     
    119140        list_initialize(&label->parts);
    120141
    121         for (i = 0; i < 8; ++i) {
    122                 if (gpt_hdr->efi_signature[i] != efi_signature[i]) {
    123                         rc = EINVAL;
    124                         goto error;
     142        for (j = 0; j < 2; j++) {
     143                for (i = 0; i < 8; ++i) {
     144                        if (gpt_hdr[j]->efi_signature[i] != efi_signature[i]) {
     145                                rc = EINVAL;
     146                                goto error;
     147                        }
    125148                }
    126149        }
    127150
    128         num_entries = uint32_t_le2host(gpt_hdr->num_entries);
    129         esize = uint32_t_le2host(gpt_hdr->entry_size);
     151        num_entries = uint32_t_le2host(gpt_hdr[0]->num_entries);
     152        esize = uint32_t_le2host(gpt_hdr[0]->entry_size);
    130153        bcnt = (num_entries + esize - 1) / esize;
    131         ba = uint64_t_le2host(gpt_hdr->entry_lba);
    132         ba_min = uint64_t_le2host(gpt_hdr->first_usable_lba);
    133         ba_max = uint64_t_le2host(gpt_hdr->last_usable_lba);
     154        ptba[0] = uint64_t_le2host(gpt_hdr[0]->entry_lba);
     155        ptba[1] = uint64_t_le2host(gpt_hdr[1]->entry_lba);
     156        ba_min = uint64_t_le2host(gpt_hdr[0]->first_usable_lba);
     157        ba_max = uint64_t_le2host(gpt_hdr[0]->last_usable_lba);
    134158
    135159        if (num_entries < 1) {
     
    154178        }
    155179
    156         rc = block_read_direct(sid, ba, bcnt, etable);
     180        rc = block_read_direct(sid, ptba[0], bcnt, etable);
    157181        if (rc != EOK) {
    158182                rc = EIO;
     
    169193        free(etable);
    170194        etable = NULL;
    171         free(gpt_hdr);
    172         gpt_hdr = NULL;
     195        free(gpt_hdr[0]);
     196        gpt_hdr[0] = NULL;
     197        free(gpt_hdr[1]);
     198        gpt_hdr[1] = NULL;
    173199
    174200        label->ops = &gpt_label_ops;
    175201        label->ltype = lt_gpt;
     202        label->svcid = sid;
    176203        label->ablock0 = ba_min;
    177204        label->anblocks = ba_max - ba_min + 1;
     205        label->pri_entries = num_entries;
     206        label->block_size = bsize;
     207
     208        label->lt.gpt.ptable_ba[0] = ptba[0];
     209        label->lt.gpt.ptable_ba[1] = ptba[1];
     210        label->lt.gpt.esize = esize;
     211
    178212        *rlabel = label;
    179213        return EOK;
    180214error:
    181215        free(etable);
    182         free(gpt_hdr);
     216        free(gpt_hdr[0]);
     217        free(gpt_hdr[1]);
    183218        free(label);
    184219        return rc;
     
    243278{
    244279        label_part_t *part;
     280        gpt_entry_t pte;
     281        int rc;
    245282
    246283        part = calloc(1, sizeof(label_part_t));
    247         if (part == NULL)
    248                 return ENOMEM;
     284        if (part == NULL) {
     285                rc = ENOMEM;
     286                goto error;
     287        }
    249288
    250289        /* XXX Verify index, block0, nblocks */
    251290
     291        if (pspec->index < 1 || pspec->index > label->pri_entries) {
     292                rc = EINVAL;
     293                goto error;
     294        }
     295
     296        /* XXX Check if index is used */
     297
     298        part->label = label;
    252299        part->index = pspec->index;
    253300        part->block0 = pspec->block0;
    254301        part->nblocks = pspec->nblocks;
    255 
    256         /* XXX Modify partition table */
    257 
    258         part->label = label;
     302        part->ptype = pspec->ptype;
     303
     304        /* Prepare partition table entry */
     305        rc = gpt_part_to_pte(part, &pte);
     306        if (rc != EOK) {
     307                rc = EINVAL;
     308                goto error;
     309        }
     310
     311        /* Modify partition tables */
     312        rc = gpt_pte_update(label, &pte, pspec->index - 1);
     313        if (rc != EOK) {
     314                rc = EIO;
     315                goto error;
     316        }
     317
    259318        list_append(&part->llabel, &label->parts);
    260319
    261320        *rpart = part;
    262321        return EOK;
     322error:
     323        free(part);
     324        return rc;
    263325}
    264326
    265327static int gpt_part_destroy(label_part_t *part)
    266328{
    267         return ENOTSUP;
     329        gpt_entry_t pte;
     330        int rc;
     331
     332        /* Prepare unused partition table entry */
     333        gpt_unused_pte(&pte);
     334
     335        /* Modify partition tables */
     336        rc = gpt_pte_update(part->label, &pte, part->index - 1);
     337        if (rc != EOK)
     338                return EIO;
     339
     340        list_remove(&part->llabel);
     341        free(part);
     342        return EOK;
     343}
     344
     345static void gpt_unused_pte(gpt_entry_t *pte)
     346{
     347        memset(pte, 0, sizeof(gpt_entry_t));
     348}
     349
     350static int gpt_part_to_pte(label_part_t *part, gpt_entry_t *pte)
     351{
     352        uint64_t eblock;
     353
     354        eblock = part->block0 + part->nblocks - 1;
     355        if (eblock < part->block0)
     356                return EINVAL;
     357
     358        memset(pte, 0, sizeof(gpt_entry_t));
     359        pte->part_type[0] = 0x12;
     360        pte->part_id[0] = 0x34;
     361        pte->start_lba = host2uint64_t_le(part->block0);
     362        pte->end_lba = host2uint64_t_le(eblock);
     363//      pte->attributes
     364//      pte->part_name
     365        return EOK;
    268366}
    269367
     
    301399}
    302400
     401/** Update partition table entry at specified index.
     402 *
     403 * Replace partition entry at index @a index with the contents of
     404 * @a pte.
     405 */
     406static int gpt_pte_update(label_t *label, gpt_entry_t *pte, int index)
     407{
     408        size_t pos;
     409        size_t offs;
     410        uint64_t ba;
     411        uint8_t *buf;
     412        gpt_entry_t *e;
     413        int i;
     414        int rc;
     415
     416        pos = index * label->lt.gpt.esize;
     417        offs = pos % label->block_size;
     418
     419        buf = calloc(1, label->block_size);
     420        if (buf == NULL)
     421                return ENOMEM;
     422
     423        /* For both partition tables: read, modify, write */
     424        for (i = 0; i < 2; i++) {
     425                ba = label->lt.gpt.ptable_ba[i] +
     426                    pos / label->block_size;
     427
     428                rc = block_read_direct(label->svcid, ba, 1, buf);
     429                if (rc != EOK) {
     430                        rc = EIO;
     431                        goto error;
     432                }
     433
     434                /* Replace single entry */
     435                e = (gpt_entry_t *)(&buf[offs]);
     436                *e = *pte;
     437
     438                rc = block_write_direct(label->svcid, ba, 1, buf);
     439                if (rc != EOK) {
     440                        rc = EIO;
     441                        goto error;
     442                }
     443        }
     444
     445        free(buf);
     446        return EOK;
     447error:
     448        free(buf);
     449        return rc;
     450}
     451
    303452/** @}
    304453 */
  • uspace/lib/label/src/mbr.c

    r6bc542b r99c23405  
    5454static int mbr_part_destroy(label_part_t *);
    5555
     56static void mbr_unused_pte(mbr_pte_t *);
     57static int mbr_part_to_pte(label_part_t *, mbr_pte_t *);
    5658static int mbr_pte_to_part(label_t *, mbr_pte_t *, int);
     59static int mbr_pte_update(label_t *, mbr_pte_t *, int);
    5760
    5861label_ops_t mbr_label_ops = {
     
    141144        label->ablock0 = mbr_ablock0;
    142145        label->anblocks = nblocks - mbr_ablock0;
     146        label->pri_entries = mbr_nprimary;
    143147        *rlabel = label;
    144148        return EOK;
     
    207211{
    208212        label_part_t *part;
     213        mbr_pte_t pte;
     214        int rc;
    209215
    210216        part = calloc(1, sizeof(label_part_t));
     
    212218                return ENOMEM;
    213219
     220        /* XXX Verify index, block0, nblocks */
     221
     222        if (pspec->index < 1 || pspec->index > label->pri_entries) {
     223                rc = EINVAL;
     224                goto error;
     225        }
     226
     227        /* XXX Check if index is used */
     228
     229        part->label = label;
    214230        part->index = pspec->index;
    215231        part->block0 = pspec->block0;
    216232        part->nblocks = pspec->nblocks;
    217 
    218         part->label = label;
     233        part->ptype = pspec->ptype;
     234
     235        rc = mbr_part_to_pte(part, &pte);
     236        if (rc != EOK) {
     237                rc = EINVAL;
     238                goto error;
     239        }
     240
     241        rc = mbr_pte_update(label, &pte, pspec->index - 1);
     242        if (rc != EOK) {
     243                rc = EIO;
     244                goto error;
     245        }
     246
     247        list_append(&part->llabel, &label->parts);
    219248
    220249        *rpart = part;
    221250        return EOK;
     251error:
     252        free(part);
     253        return rc;
    222254}
    223255
    224256static int mbr_part_destroy(label_part_t *part)
    225257{
    226         return ENOTSUP;
     258        mbr_pte_t pte;
     259        int rc;
     260
     261        /* Prepare unused partition table entry */
     262        mbr_unused_pte(&pte);
     263
     264        /* Modify partition table */
     265        rc = mbr_pte_update(part->label, &pte, part->index - 1);
     266        if (rc != EOK)
     267                return EIO;
     268
     269        list_remove(&part->llabel);
     270        free(part);
     271        return EOK;
     272}
     273
     274static void mbr_unused_pte(mbr_pte_t *pte)
     275{
     276        memset(pte, 0, sizeof(mbr_pte_t));
     277}
     278
     279static int mbr_part_to_pte(label_part_t *part, mbr_pte_t *pte)
     280{
     281        if ((part->block0 >> 32) != 0)
     282                return EINVAL;
     283        if ((part->nblocks >> 32) != 0)
     284                return EINVAL;
     285        if ((part->ptype >> 8) != 0)
     286                return EINVAL;
     287
     288        memset(pte, 0, sizeof(mbr_pte_t));
     289        pte->ptype = part->ptype;
     290        pte->first_lba = host2uint32_t_le(part->block0);
     291        pte->length = host2uint32_t_le(part->nblocks);
     292        return EOK;
    227293}
    228294
     
    260326}
    261327
     328/** Update partition table entry at specified index.
     329 *
     330 * Replace partition entry at index @a index with the contents of
     331 * @a pte.
     332 */
     333static int mbr_pte_update(label_t *label, mbr_pte_t *pte, int index)
     334{
     335        mbr_br_block_t *br;
     336        int rc;
     337
     338        br = calloc(1, label->block_size);
     339        if (br == NULL)
     340                return ENOMEM;
     341
     342        rc = block_read_direct(label->svcid, mbr_ba, 1, br);
     343        if (rc != EOK) {
     344                rc = EIO;
     345                goto error;
     346        }
     347
     348        br->pte[index] = *pte;
     349
     350        rc = block_write_direct(label->svcid, mbr_ba, 1, br);
     351        if (rc != EOK) {
     352                rc = EIO;
     353                goto error;
     354        }
     355
     356        free(br);
     357        return EOK;
     358error:
     359        free(br);
     360        return rc;
     361}
     362
    262363/** @}
    263364 */
  • uspace/srv/bd/vbd/disk.c

    r6bc542b r99c23405  
    112112}
    113113
     114/** Add partition to our inventory based on liblabel partition structure */
    114115static int vbds_part_add(vbds_disk_t *disk, label_part_t *lpart,
    115116    vbds_part_t **rpart)
     
    119120        label_part_info_t lpinfo;
    120121        char *name;
    121         int pno;
    122122        int rc;
    123123
     
    132132
    133133        /* XXX Proper service name */
    134         pno = list_count(&disk->parts);
    135         rc = asprintf(&name, "%sp%u", disk->svc_name, pno);
     134        rc = asprintf(&name, "%sp%u", disk->svc_name, lpart->index);
    136135        if (rc < 0) {
    137136                log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
     
    166165        if (rpart != NULL)
    167166                *rpart = part;
     167        return EOK;
     168}
     169
     170/** Remove partition from our inventory leaving only the underlying liblabel
     171 * partition structure.
     172 */
     173static int vbds_part_remove(vbds_part_t *part, label_part_t **rlpart)
     174{
     175        label_part_t *lpart;
     176        int rc;
     177
     178        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_remove(%p)", part);
     179
     180        lpart = part->lpart;
     181
     182        if (part->open_cnt > 0)
     183                return EBUSY;
     184
     185        rc = loc_service_unregister((service_id_t)part->id);
     186        if (rc != EOK)
     187                return EIO;
     188
     189        list_remove(&part->ldisk);
     190        list_remove(&part->lparts);
     191        free(part);
     192
     193        if (rlpart != NULL)
     194                *rlpart = lpart;
    168195        return EOK;
    169196}
     
    442469{
    443470        vbds_part_t *part;
     471        vbds_disk_t *disk;
     472        label_part_t *lpart;
    444473        int rc;
    445474
     
    448477                return rc;
    449478
    450         rc = label_part_destroy(part->lpart);
    451         if (rc != EOK)
    452                 return rc;
    453 
    454         list_remove(&part->ldisk);
    455         list_remove(&part->lparts);
    456         free(part);
     479        disk = part->disk;
     480
     481        rc = vbds_part_remove(part, &lpart);
     482        if (rc != EOK)
     483                return rc;
     484
     485        rc = label_part_destroy(lpart);
     486        if (rc != EOK) {
     487                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting partition");
     488
     489                /* Try rolling back */
     490                rc = vbds_part_add(disk, lpart, NULL);
     491                if (rc != EOK)
     492                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed rolling back.");
     493
     494                return EIO;
     495        }
     496
    457497        return EOK;
    458498}
Note: See TracChangeset for help on using the changeset viewer.