Changeset 78d50bd in mainline


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.

Location:
uspace
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/fdisk/fdisk.c

    r28ed0d9 r78d50bd  
    343343
    344344        tinput_destroy(tinput);
     345        tinput = NULL;
    345346
    346347        rc = fdsk_select_fstype(&fstype);
  • uspace/lib/block/block.c

    r28ed0d9 r78d50bd  
    789789}
    790790
     791/** Synchronize blocks to persistent storage.
     792 *
     793 * @param service_id    Service ID of the block device.
     794 * @param ba            Address of first block (physical).
     795 * @param cnt           Number of blocks.
     796 *
     797 * @return              EOK on success or negative error code on failure.
     798 */
     799int block_sync_cache(service_id_t service_id, aoff64_t ba, size_t cnt)
     800{
     801        devcon_t *devcon;
     802
     803        devcon = devcon_search(service_id);
     804        assert(devcon);
     805
     806        return bd_sync_cache(devcon->bd, ba, cnt);
     807}
     808
    791809/** Get device block size.
    792810 *
  • uspace/lib/block/block.h

    r28ed0d9 r78d50bd  
    120120extern int block_read_bytes_direct(service_id_t, aoff64_t, size_t, void *);
    121121extern int block_write_direct(service_id_t, aoff64_t, size_t, const void *);
     122extern int block_sync_cache(service_id_t, aoff64_t, size_t);
    122123
    123124#endif
  • uspace/lib/label/include/label.h

    r28ed0d9 r78d50bd  
    4949extern label_part_t *label_part_first(label_t *);
    5050extern label_part_t *label_part_next(label_part_t *);
     51extern void label_part_get_info(label_part_t *, label_part_info_t *);
    5152
    5253extern int label_part_create(label_t *, label_part_spec_t *,
  • uspace/lib/label/include/types/liblabel.h

    r28ed0d9 r78d50bd  
    3939#include <adt/list.h>
    4040#include <types/label.h>
     41#include <sys/types.h>
    4142#include <vol.h>
    4243
     
    4849} label_info_t;
    4950
     51typedef struct {
     52        /** Address of first block */
     53        aoff64_t block0;
     54        /** Number of blocks */
     55        aoff64_t nblocks;
     56} label_part_info_t;
     57
    5058/** Partition */
    5159typedef struct {
    5260        /** Containing label */
    5361        struct label *label;
    54         /** Link to fdisk_dev_t.parts */
    55         link_t ldev;
    56         /** Capacity */
    57 //      fdisk_cap_t capacity;
    58         /** File system type */
    59 //      fdisk_fstype_t fstype;
     62        /** Link to label_t.parts */
     63        link_t llabel;
    6064} label_part_t;
    6165
    6266/** Specification of new partition */
    6367typedef struct {
    64         /** Desired capacity */
    65 //      fdisk_cap_t capacity;
    66         /** File system type */
    67 //      fdisk_fstype_t fstype;
    6868} label_part_spec_t;
    6969
    7070/** Label instance */
    7171typedef struct label {
     72        /** Partitions */
     73        list_t parts; /* of label_part_t */
    7274} label_t;
    7375
  • uspace/lib/label/src/label.c

    r28ed0d9 r78d50bd  
    3434 */
    3535
     36#include <adt/list.h>
    3637#include <errno.h>
    3738#include <label.h>
     
    4748                return ENOMEM;
    4849
     50        list_initialize(&label->parts);
    4951        *rlabel = label;
    5052        return EOK;
     
    5961                return ENOMEM;
    6062
     63        list_initialize(&label->parts);
    6164        *rlabel = label;
    6265        return EOK;
     
    6568void label_close(label_t *label)
    6669{
     70        if (label == NULL)
     71                return;
     72
    6773        free(label);
    6874}
     
    8389label_part_t *label_part_first(label_t *label)
    8490{
    85         return NULL;
     91        link_t *link;
     92
     93        link = list_first(&label->parts);
     94        if (link == NULL)
     95                return NULL;
     96
     97        return list_get_instance(link, label_part_t, llabel);
    8698}
    8799
    88 label_part_t *label_part_next(label_part_t *oart)
     100label_part_t *label_part_next(label_part_t *part)
    89101{
    90         return NULL;
     102        link_t *link;
     103
     104        link = list_next(&part->llabel, &part->label->parts);
     105        if (link == NULL)
     106                return NULL;
     107
     108        return list_get_instance(link, label_part_t, llabel);
    91109}
    92110
     111void label_part_get_info(label_part_t *part, label_part_info_t *pinfo)
     112{
     113        pinfo->block0 = 0;
     114        pinfo->nblocks = 0;
     115}
    93116
    94117int label_part_create(label_t *label, label_part_spec_t *pspec,
    95118    label_part_t **rpart)
    96119{
    97         return ENOTSUP;
     120        label_part_t *part;
     121
     122        part = calloc(1, sizeof(label_part_t));
     123        if (part == NULL)
     124                return ENOMEM;
     125
     126        part->label = label;
     127        list_append(&part->llabel, &label->parts);
     128        *rpart = part;
     129        return EOK;
    98130}
    99131
    100132int label_part_destroy(label_part_t *part)
    101133{
     134        list_remove(&part->llabel);
     135        free(part);
    102136        return EOK;
    103137}
  • uspace/srv/bd/vbd/Makefile

    r28ed0d9 r78d50bd  
    3434
    3535EXTRA_CFLAGS = \
    36         -I$(LIBLABEL_PREFIX)/include
     36        -I$(LIBLABEL_PREFIX)/include \
     37        -I$(LIBBLOCK_PREFIX)
    3738
    3839BINARY = vbd
  • 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}
  • uspace/srv/bd/vbd/disk.h

    r28ed0d9 r78d50bd  
    5050extern int vbds_part_create(service_id_t, vbds_part_id_t *);
    5151extern int vbds_part_delete(vbds_part_id_t);
     52extern void vbds_bd_conn(ipc_callid_t, ipc_call_t *, void *);
    5253
    5354#endif
  • uspace/srv/bd/vbd/types/vbd.h

    r28ed0d9 r78d50bd  
    3939
    4040#include <adt/list.h>
     41#include <bd_srv.h>
    4142#include <label.h>
    4243#include <loc.h>
    4344#include <types/label.h>
     45
     46typedef sysarg_t vbds_part_id_t;
    4447
    4548/** Disk info */
     
    5760        /** Link to vbds_disk_t.parts */
    5861        link_t ldisk;
     62        /** Link to vbds_parts */
     63        link_t lparts;
     64        /** Partition ID */
     65        vbds_part_id_t id;
    5966        /** Label partition */
    6067        label_part_t *lpart;
     68        /** Block device service */
     69        bd_srvs_t bds;
     70        /** Number of times the device is open */
     71        int open_cnt;
     72        /** Address of first block */
     73        aoff64_t block0;
     74        /** Number of blocks */
     75        aoff64_t nblocks;
    6176} vbds_part_t;
    6277
     
    6782        /** Service ID */
    6883        service_id_t svc_id;
     84        /** Disk service name */
     85        char *svc_name;
    6986        /** Label */
    7087        label_t *label;
    7188        /** Partitions */
    7289        list_t parts; /* of vbds_part_t */
     90        /** Block size */
     91        size_t block_size;
    7392} vbds_disk_t;
    7493
     
    7695} vbds_part_info_t;
    7796
    78 typedef sysarg_t vbds_part_id_t;
    79 
    8097#endif
    8198
  • uspace/srv/bd/vbd/vbd.c

    r28ed0d9 r78d50bd  
    5151static void vbds_client_conn(ipc_callid_t, ipc_call_t *, void *);
    5252
     53static service_id_t ctl_sid;
     54
    5355static int vbds_init(void)
    5456{
     
    6668        }
    6769
    68         service_id_t sid;
    69         rc = loc_service_register(SERVICE_NAME_VBD, &sid);
     70        rc = loc_service_register(SERVICE_NAME_VBD, &ctl_sid);
    7071        if (rc != EOK) {
    7172                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed registering service (%d).", rc);
     
    191192}
    192193
    193 static void vbds_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     194static void vbds_ctl_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
    194195{
    195196        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_client_conn()");
     
    243244}
    244245
     246static void vbds_client_conn(ipc_callid_t iid, ipc_call_t *icall, void *arg)
     247{
     248        service_id_t sid;
     249
     250        log_msg(LOG_DEFAULT, LVL_NOTE, "vbds_client_conn()");
     251
     252        sid = (service_id_t)IPC_GET_ARG1(*icall);
     253
     254        if (sid == ctl_sid)
     255                vbds_ctl_conn(iid, icall, arg);
     256        else
     257                vbds_bd_conn(iid, icall, arg);
     258}
     259
    245260int main(int argc, char *argv[])
    246261{
Note: See TracChangeset for help on using the changeset viewer.