Changeset 78d50bd in mainline for uspace/srv/bd/vbd/disk.c


Ignore:
Timestamp:
2015-06-29T18:47:07Z (9 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
3faa03d
Parents:
28ed0d9
Message:

Implement partition block device interface in VBD based on data from liblabel.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/vbd/disk.c

    r28ed0d9 r78d50bd  
    3535
    3636#include <adt/list.h>
     37#include <bd_srv.h>
     38#include <block.h>
    3739#include <errno.h>
    3840#include <io/log.h>
     41#include <loc.h>
     42#include <stdio.h>
    3943#include <stdlib.h>
    4044#include <task.h>
     
    4448
    4549static list_t vbds_disks; /* of vbds_disk_t */
     50static list_t vbds_parts; /* of vbds_part_t */
     51
     52static int vbds_bd_open(bd_srvs_t *, bd_srv_t *);
     53static int vbds_bd_close(bd_srv_t *);
     54static int vbds_bd_read_blocks(bd_srv_t *, aoff64_t, size_t, void *, size_t);
     55static int vbds_bd_sync_cache(bd_srv_t *, aoff64_t, size_t);
     56static int vbds_bd_write_blocks(bd_srv_t *, aoff64_t, size_t, const void *,
     57    size_t);
     58static int vbds_bd_get_block_size(bd_srv_t *, size_t *);
     59static int vbds_bd_get_num_blocks(bd_srv_t *, aoff64_t *);
     60
     61static int vbds_bsa_translate(vbds_part_t *, aoff64_t, size_t, aoff64_t *);
     62
     63static bd_ops_t vbds_bd_ops = {
     64        .open = vbds_bd_open,
     65        .close = vbds_bd_close,
     66        .read_blocks = vbds_bd_read_blocks,
     67        .sync_cache = vbds_bd_sync_cache,
     68        .write_blocks = vbds_bd_write_blocks,
     69        .get_block_size = vbds_bd_get_block_size,
     70        .get_num_blocks = vbds_bd_get_num_blocks
     71};
     72
     73static vbds_part_t *bd_srv_part(bd_srv_t *bd)
     74{
     75        return (vbds_part_t *)bd->srvs->sarg;
     76}
    4677
    4778void vbds_disks_init(void)
    4879{
    4980        list_initialize(&vbds_disks);
     81        list_initialize(&vbds_parts);
    5082}
    5183
     
    6294}
    6395
     96static int vbds_part_by_id(vbds_part_id_t partid, vbds_part_t **rpart)
     97{
     98        list_foreach(vbds_parts, lparts, vbds_part_t, part) {
     99                if (part->id == partid) {
     100                        *rpart = part;
     101                        return EOK;
     102                }
     103        }
     104
     105        return ENOENT;
     106}
     107
    64108static int vbds_part_add(vbds_disk_t *disk, label_part_t *lpart)
    65109{
    66110        vbds_part_t *part;
    67 
    68         log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_add(%p, %p)",
    69             disk, lpart);
     111        service_id_t psid;
     112        label_part_info_t lpinfo;
     113        char *name;
     114        int pno;
     115        int rc;
     116
     117        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_part_add(%s, %p)",
     118            disk->svc_name, lpart);
    70119
    71120        part = calloc(1, sizeof(vbds_part_t));
     
    75124        }
    76125
     126        /* XXX Proper service name */
     127        pno = list_count(&disk->parts);
     128        rc = asprintf(&name, "%sp%u", disk->svc_name, pno);
     129        if (rc < 0) {
     130                log_msg(LOG_DEFAULT, LVL_ERROR, "Out of memory.");
     131                return ENOMEM;
     132        }
     133
     134        rc = loc_service_register(name, &psid);
     135        if (rc != EOK) {
     136                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering "
     137                    "service %s.", name);
     138                free(name);
     139                free(part);
     140                return EIO;
     141        }
     142
     143        free(name);
     144        label_part_get_info(lpart, &lpinfo);
     145
    77146        part->lpart = lpart;
    78147        part->disk = disk;
     148        part->block0 = lpinfo.block0;
     149        part->nblocks = lpinfo.nblocks;
     150
     151        bd_srvs_init(&part->bds);
     152        part->bds.ops = &vbds_bd_ops;
     153        part->bds.sarg = part;
     154
    79155        list_append(&part->ldisk, &disk->parts);
     156        list_append(&part->lparts, &vbds_parts);
    80157
    81158        return EOK;
     
    86163        label_t *label;
    87164        label_part_t *part;
    88         vbds_disk_t *disk;
     165        vbds_disk_t *disk = NULL;
     166        bool block_inited = false;
     167        size_t block_size;
    89168        int rc;
    90169
     
    100179                return ENOMEM;
    101180
     181        rc = loc_service_get_name(sid, &disk->svc_name);
     182        if (rc != EOK) {
     183                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting disk service name.");
     184                rc = EIO;
     185                goto error;
     186        }
     187
     188        rc = block_init(EXCHANGE_SERIALIZE, sid, 2048);
     189        if (rc != EOK) {
     190                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed opening block device %s.",
     191                    disk->svc_name);
     192                rc = EIO;
     193                goto error;
     194        }
     195
     196        rc = block_get_bsize(sid, &block_size);
     197        if (rc != EOK) {
     198                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed getting block size of %s.",
     199                    disk->svc_name);
     200                rc = EIO;
     201                goto error;
     202        }
     203
     204        block_inited = true;
     205
    102206        rc = label_open(sid, &label);
    103         if (rc != EOK)
    104                 goto error;
     207        if (rc != EOK) {
     208                rc = EIO;
     209                goto error;
     210        }
    105211
    106212        disk->svc_id = sid;
    107213        disk->label = label;
     214        disk->block_size = block_size;
     215
    108216        list_initialize(&disk->parts);
    109217        list_append(&disk->ldisks, &vbds_disks);
     
    113221                rc = vbds_part_add(disk, part);
    114222                if (rc != EOK) {
    115                         log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding partition.");
     223                        log_msg(LOG_DEFAULT, LVL_ERROR, "Failed adding partitio "
     224                            "(disk %s)", disk->svc_name);
    116225                }
    117226
     
    121230        return EOK;
    122231error:
     232        label_close(label);
     233        if (block_inited)
     234                block_fini(sid);
     235        if (disk != NULL)
     236                free(disk->svc_name);
    123237        free(disk);
    124238        return rc;
     
    181295int vbds_label_delete(service_id_t sid)
    182296{
    183         return EOK;
    184297        vbds_disk_t *disk;
    185298        int rc;
     
    202315}
    203316
    204 int vbds_part_get_info(vbds_part_id_t part, vbds_part_info_t *pinfo)
    205 {
    206         return EOK;
    207 }
    208 
    209 int vbds_part_create(service_id_t disk, vbds_part_id_t *rpart)
    210 {
    211         return EOK;
    212 }
    213 
    214 int vbds_part_delete(vbds_part_id_t part)
    215 {
     317int vbds_part_get_info(vbds_part_id_t partid, vbds_part_info_t *pinfo)
     318{
     319        vbds_part_t *part;
     320        int rc;
     321
     322        rc = vbds_part_by_id(partid, &part);
     323        if (rc != EOK)
     324                return rc;
     325
     326        return EOK;
     327}
     328
     329int vbds_part_create(service_id_t sid, vbds_part_id_t *rpart)
     330{
     331        vbds_disk_t *disk;
     332        vbds_part_t *part;
     333        label_part_spec_t pspec;
     334        label_part_t *lpart;
     335        int rc;
     336
     337        part = calloc(1, sizeof(vbds_part_t));
     338        if (part == NULL)
     339                return ENOMEM;
     340
     341        rc = vbds_disk_by_svcid(sid, &disk);
     342        if (rc != EOK) {
     343                log_msg(LOG_DEFAULT, LVL_NOTE, "Partition %zu not found",
     344                    sid);
     345                goto error;
     346        }
     347
     348        label_pspec_init(&pspec);
     349        rc = label_part_create(disk->label, &pspec, &lpart);
     350        if (rc != EOK) {
     351                log_msg(LOG_DEFAULT, LVL_ERROR, "Error creating partition.");
     352                goto error;
     353        }
     354
     355        rc = vbds_part_add(disk, lpart);
     356        if (rc != EOK) {
     357                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed while creating "
     358                    "partition.");
     359                rc = label_part_destroy(lpart);
     360                if (rc != EOK)
     361                        log_msg(LOG_DEFAULT, LVL_ERROR,
     362                            "Cannot roll back partition creation.");
     363                rc = EIO;
     364                goto error;
     365        }
     366
     367        return EOK;
     368error:
     369        free(part);
     370        return rc;
     371}
     372
     373int vbds_part_delete(vbds_part_id_t partid)
     374{
     375        vbds_part_t *part;
     376        int rc;
     377
     378        rc = vbds_part_by_id(partid, &part);
     379        if (rc != EOK)
     380                return rc;
     381
     382        rc = label_part_destroy(part->lpart);
     383        if (rc != EOK)
     384                return rc;
     385
     386        list_remove(&part->ldisk);
     387        list_remove(&part->lparts);
     388        free(part);
     389        return EOK;
     390}
     391
     392static int vbds_bd_open(bd_srvs_t *bds, bd_srv_t *bd)
     393{
     394        vbds_part_t *part = bd_srv_part(bd);
     395
     396        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_open()");
     397        part->open_cnt++;
     398        return EOK;
     399}
     400
     401static int vbds_bd_close(bd_srv_t *bd)
     402{
     403        vbds_part_t *part = bd_srv_part(bd);
     404
     405        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_close()");
     406        part->open_cnt--;
     407        return EOK;
     408}
     409
     410static int vbds_bd_read_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
     411    void *buf, size_t size)
     412{
     413        vbds_part_t *part = bd_srv_part(bd);
     414        aoff64_t gba;
     415
     416        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_read_blocks()");
     417
     418        if (cnt * part->disk->block_size < size)
     419                return EINVAL;
     420
     421        if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     422                return ELIMIT;
     423
     424        return block_read_direct(part->disk->svc_id, gba, cnt, buf);
     425}
     426
     427static int vbds_bd_sync_cache(bd_srv_t *bd, aoff64_t ba, size_t cnt)
     428{
     429        vbds_part_t *part = bd_srv_part(bd);
     430        aoff64_t gba;
     431
     432        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_sync_cache()");
     433
     434        /* XXX Allow full-disk sync? */
     435        if (ba != 0 || cnt != 0) {
     436                if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     437                        return ELIMIT;
     438        } else {
     439                gba = 0;
     440        }
     441
     442        return block_sync_cache(part->disk->svc_id, gba, cnt);
     443}
     444
     445static int vbds_bd_write_blocks(bd_srv_t *bd, aoff64_t ba, size_t cnt,
     446    const void *buf, size_t size)
     447{
     448        vbds_part_t *part = bd_srv_part(bd);
     449        aoff64_t gba;
     450
     451        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_write_blocks()");
     452
     453        if (cnt * part->disk->block_size < size)
     454                return EINVAL;
     455
     456        if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     457                return ELIMIT;
     458
     459        return block_write_direct(part->disk->svc_id, gba, cnt, buf);
     460}
     461
     462static int vbds_bd_get_block_size(bd_srv_t *bd, size_t *rsize)
     463{
     464        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_get_block_size()");
     465        return EOK;
     466}
     467
     468static int vbds_bd_get_num_blocks(bd_srv_t *bd, aoff64_t *rnb)
     469{
     470        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_bd_get_num_blocks()");
     471        return EOK;
     472}
     473
     474void vbds_bd_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     475{
     476        vbds_part_t *part;
     477        int rc;
     478        service_id_t partid;
     479
     480        partid = IPC_GET_ARG1(*icall);
     481
     482        rc = vbds_part_by_id(partid, &part);
     483        if (rc != EOK) {
     484                async_answer_0(iid, EINVAL);
     485                return;
     486        }
     487
     488        bd_conn(iid, icall, &part->bds);
     489}
     490
     491/** Translate block segment address with range checking. */
     492static int vbds_bsa_translate(vbds_part_t *part, aoff64_t ba, size_t cnt,
     493    aoff64_t *gba)
     494{
     495        if (ba + cnt > part->nblocks)
     496                return ELIMIT;
     497
     498        *gba = part->block0 + ba;
    216499        return EOK;
    217500}
Note: See TracChangeset for help on using the changeset viewer.