Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset e11c527 in mainline


Ignore:
Timestamp:
2016-02-18T14:31:00Z (5 years ago)
Author:
Jiri Svoboda <jiri@…>
Branches:
master
Children:
53e3950
Parents:
8e670dd
Message:

When disk disappears, VBD should be able to force removal of partitions, even if they are open.

Location:
uspace/srv/bd/vbd
Files:
2 edited

Legend:

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

    r8e670dd re11c527  
    11/*
    2  * Copyright (c) 2015 Jiri Svoboda
     2 * Copyright (c) 2016 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    5050static fibril_mutex_t vbds_disks_lock;
    5151static list_t vbds_disks; /* of vbds_disk_t */
     52static fibril_mutex_t vbds_parts_lock;
    5253static list_t vbds_parts; /* of vbds_part_t */
    5354
     
    5556
    5657static int vbds_disk_parts_add(vbds_disk_t *, label_t *);
    57 static int vbds_disk_parts_remove(vbds_disk_t *);
     58static int vbds_disk_parts_remove(vbds_disk_t *, vbds_rem_flag_t);
    5859
    5960static int vbds_bd_open(bd_srvs_t *, bd_srv_t *);
     
    120121        fibril_mutex_initialize(&vbds_disks_lock);
    121122        list_initialize(&vbds_disks);
     123        fibril_mutex_initialize(&vbds_parts_lock);
    122124        list_initialize(&vbds_parts);
    123125
     
    222224}
    223225
     226static void vbds_part_add_ref(vbds_part_t *part)
     227{
     228        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_part_add_ref");
     229        atomic_inc(&part->refcnt);
     230}
     231
     232static void vbds_part_del_ref(vbds_part_t *part)
     233{
     234        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_part_del_ref");
     235        if (atomic_predec(&part->refcnt) == 0) {
     236                log_msg(LOG_DEFAULT, LVL_DEBUG2, " - free part");
     237                free(part);
     238        }
     239}
     240
    224241static int vbds_part_by_pid(vbds_part_id_t partid, vbds_part_t **rpart)
    225242{
    226243        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_by_pid(%zu)", partid);
     244
     245        fibril_mutex_lock(&vbds_parts_lock);
    227246
    228247        list_foreach(vbds_parts, lparts, vbds_part_t, part) {
     
    230249                if (part->pid == partid) {
    231250                        log_msg(LOG_DEFAULT, LVL_DEBUG, "Found match.");
     251                        vbds_part_add_ref(part);
     252                        fibril_mutex_unlock(&vbds_parts_lock);
    232253                        *rpart = part;
    233254                        return EOK;
     
    235256        }
    236257
     258        fibril_mutex_unlock(&vbds_parts_lock);
    237259        log_msg(LOG_DEFAULT, LVL_DEBUG, "No match.");
    238260        return ENOENT;
     
    242264{
    243265        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_by_svcid(%zu)", svcid);
     266
     267        fibril_mutex_lock(&vbds_parts_lock);
    244268
    245269        list_foreach(vbds_parts, lparts, vbds_part_t, part) {
     
    247271                if (part->svc_id == svcid) {
    248272                        log_msg(LOG_DEFAULT, LVL_DEBUG, "Found match.");
     273                        vbds_part_add_ref(part);
     274                        fibril_mutex_unlock(&vbds_parts_lock);
    249275                        *rpart = part;
    250276                        return EOK;
     
    252278        }
    253279
     280        fibril_mutex_unlock(&vbds_parts_lock);
    254281        log_msg(LOG_DEFAULT, LVL_DEBUG, "No match.");
    255282        return ENOENT;
     
    275302                return ENOMEM;
    276303        }
     304
     305        fibril_rwlock_initialize(&part->lock);
    277306
    278307        part->lpart = lpart;
     
    282311        part->block0 = lpinfo.block0;
    283312        part->nblocks = lpinfo.nblocks;
     313        atomic_set(&part->refcnt, 1);
    284314
    285315        bd_srvs_init(&part->bds);
     
    289319        if (lpinfo.pkind != lpk_extended) {
    290320                rc = vbds_part_svc_register(part);
    291                 if (rc != EOK)
     321                if (rc != EOK) {
     322                        free(part);
    292323                        return EIO;
     324                }
    293325        }
    294326
    295327        list_append(&part->ldisk, &disk->parts);
     328        fibril_mutex_lock(&vbds_parts_lock);
    296329        list_append(&part->lparts, &vbds_parts);
     330        fibril_mutex_unlock(&vbds_parts_lock);
    297331
    298332        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_add -> %p", part);
     
    305339/** Remove partition from our inventory leaving only the underlying liblabel
    306340 * partition structure.
     341 *
     342 * @param part Partition
     343 * @param flag If set to @c vrf_force, force removal even if partition is in use
     344 * @param rlpart Place to store pointer to liblabel partition
    307345 */
    308 static int vbds_part_remove(vbds_part_t *part, label_part_t **rlpart)
     346static int vbds_part_remove(vbds_part_t *part, vbds_rem_flag_t flag,
     347    label_part_t **rlpart)
    309348{
    310349        label_part_t *lpart;
     
    313352        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_remove(%p)", part);
    314353
     354        fibril_rwlock_write_lock(&part->lock);
    315355        lpart = part->lpart;
    316356
    317         if (part->open_cnt > 0) {
     357        if ((flag & vrf_force) == 0 && part->open_cnt > 0) {
     358                fibril_rwlock_write_unlock(&part->lock);
    318359                log_msg(LOG_DEFAULT, LVL_DEBUG, "part->open_cnt = %d",
    319360                    part->open_cnt);
     
    323364        if (part->svc_id != 0) {
    324365                rc = vbds_part_svc_unregister(part);
    325                 if (rc != EOK)
     366                if (rc != EOK) {
     367                        fibril_rwlock_write_unlock(&part->lock);
    326368                        return EIO;
     369                }
    327370        }
    328371
    329372        list_remove(&part->ldisk);
     373        fibril_mutex_lock(&vbds_parts_lock);
    330374        list_remove(&part->lparts);
    331         free(part);
     375        fibril_mutex_unlock(&vbds_parts_lock);
     376
     377        vbds_part_del_ref(part);
     378        part->lpart = NULL;
     379        fibril_rwlock_write_unlock(&part->lock);
    332380
    333381        if (rlpart != NULL)
     
    360408/** Remove all disk partitions from our inventory leaving only the underlying
    361409 * liblabel partition structures. */
    362 static int vbds_disk_parts_remove(vbds_disk_t *disk)
     410static int vbds_disk_parts_remove(vbds_disk_t *disk, vbds_rem_flag_t flag)
    363411{
    364412        link_t *link;
     
    369417        while (link != NULL) {
    370418                part = list_get_instance(link, vbds_part_t, ldisk);
    371                 rc = vbds_part_remove(part, NULL);
     419                rc = vbds_part_remove(part, flag, NULL);
    372420                if (rc != EOK)
    373421                        return rc;
     
    486534                return rc;
    487535
    488         rc = vbds_disk_parts_remove(disk);
     536        rc = vbds_disk_parts_remove(disk, vrf_force);
    489537        if (rc != EOK) {
    490538                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed removing disk.");
     
    612660
    613661        /* Close dummy label first */
    614         rc = vbds_disk_parts_remove(disk);
     662        rc = vbds_disk_parts_remove(disk, vrf_none);
    615663        if (rc != EOK) {
    616664                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed removing disk.");
     
    661709                return rc;
    662710
    663         rc = vbds_disk_parts_remove(disk);
     711        rc = vbds_disk_parts_remove(disk, vrf_none);
    664712        if (rc != EOK) {
    665713                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting label.");
     
    696744        if (rc != EOK)
    697745                return rc;
     746
     747        fibril_rwlock_read_lock(&part->lock);
     748        if (part->lpart == NULL) {
     749                fibril_rwlock_read_unlock(&part->lock);
     750                return ENOENT;
     751        }
    698752
    699753        label_part_get_info(part->lpart, &lpinfo);
     
    704758        pinfo->nblocks = lpinfo.nblocks;
    705759        pinfo->svc_id = part->svc_id;
     760        vbds_part_del_ref(part);
     761        fibril_rwlock_read_unlock(&part->lock);
     762
    706763        return EOK;
    707764}
     
    783840        disk = part->disk;
    784841
    785         rc = vbds_part_remove(part, &lpart);
     842        rc = vbds_part_remove(part, vrf_none, &lpart);
    786843        if (rc != EOK)
    787844                return rc;
    788845
    789846        rc = label_part_destroy(lpart);
     847        vbds_part_del_ref(part);
    790848        if (rc != EOK) {
    791849                log_msg(LOG_DEFAULT, LVL_ERROR, "Failed deleting partition");
     
    837895
    838896        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_open()");
     897        fibril_rwlock_write_lock(&part->lock);
    839898        part->open_cnt++;
     899        fibril_rwlock_write_unlock(&part->lock);
    840900        return EOK;
    841901}
     
    846906
    847907        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_close()");
     908
     909        /* Grabbing writer lock also forces all I/O to complete */
     910
     911        fibril_rwlock_write_lock(&part->lock);
    848912        part->open_cnt--;
     913        fibril_rwlock_write_unlock(&part->lock);
    849914        return EOK;
    850915}
     
    855920        vbds_part_t *part = bd_srv_part(bd);
    856921        aoff64_t gba;
     922        int rc;
    857923
    858924        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_read_blocks()");
    859 
    860         if (cnt * part->disk->block_size < size)
     925        fibril_rwlock_read_lock(&part->lock);
     926
     927        if (cnt * part->disk->block_size < size) {
     928                fibril_rwlock_read_unlock(&part->lock);
    861929                return EINVAL;
    862 
    863         if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     930        }
     931
     932        if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
     933                fibril_rwlock_read_unlock(&part->lock);
    864934                return ELIMIT;
    865 
    866         return block_read_direct(part->disk->svc_id, gba, cnt, buf);
     935        }
     936
     937        rc = block_read_direct(part->disk->svc_id, gba, cnt, buf);
     938        fibril_rwlock_read_unlock(&part->lock);
     939
     940        return rc;
    867941}
    868942
     
    871945        vbds_part_t *part = bd_srv_part(bd);
    872946        aoff64_t gba;
     947        int rc;
    873948
    874949        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_sync_cache()");
     950        fibril_rwlock_read_lock(&part->lock);
    875951
    876952        /* XXX Allow full-disk sync? */
    877953        if (ba != 0 || cnt != 0) {
    878                 if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     954                if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
     955                        fibril_rwlock_read_unlock(&part->lock);
    879956                        return ELIMIT;
     957                }
    880958        } else {
    881959                gba = 0;
    882960        }
    883961
    884         return block_sync_cache(part->disk->svc_id, gba, cnt);
     962        rc = block_sync_cache(part->disk->svc_id, gba, cnt);
     963        fibril_rwlock_read_unlock(&part->lock);
     964        return rc;
    885965}
    886966
     
    890970        vbds_part_t *part = bd_srv_part(bd);
    891971        aoff64_t gba;
     972        int rc;
    892973
    893974        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_write_blocks()");
    894 
    895         if (cnt * part->disk->block_size < size)
     975        fibril_rwlock_read_lock(&part->lock);
     976
     977        if (cnt * part->disk->block_size < size) {
     978                fibril_rwlock_read_unlock(&part->lock);
    896979                return EINVAL;
    897 
    898         if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK)
     980        }
     981
     982        if (vbds_bsa_translate(part, ba, cnt, &gba) != EOK) {
     983                fibril_rwlock_read_unlock(&part->lock);
    899984                return ELIMIT;
    900 
    901         return block_write_direct(part->disk->svc_id, gba, cnt, buf);
     985        }
     986
     987        rc = block_write_direct(part->disk->svc_id, gba, cnt, buf);
     988        fibril_rwlock_read_unlock(&part->lock);
     989        return rc;
    902990}
    903991
     
    907995
    908996        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_get_block_size()");
     997
     998        fibril_rwlock_read_lock(&part->lock);
    909999        *rsize = part->disk->block_size;
     1000        fibril_rwlock_read_unlock(&part->lock);
     1001
    9101002        return EOK;
    9111003}
     
    9161008
    9171009        log_msg(LOG_DEFAULT, LVL_DEBUG2, "vbds_bd_get_num_blocks()");
     1010
     1011        fibril_rwlock_read_lock(&part->lock);
    9181012        *rnb = part->nblocks;
     1013        fibril_rwlock_read_unlock(&part->lock);
     1014
    9191015        return EOK;
    9201016}
     
    9421038        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_bd_conn() - call bd_conn");
    9431039        bd_conn(iid, icall, &part->bds);
     1040        vbds_part_del_ref(part);
    9441041}
    9451042
     
    10281125        log_msg(LOG_DEFAULT, LVL_DEBUG, "vbds_part_indices_update()");
    10291126
     1127        fibril_mutex_lock(&vbds_parts_lock);
     1128
    10301129        /* First unregister services for partitions whose index has changed */
    10311130        list_foreach(disk->parts, ldisk, vbds_part_t, part) {
     1131                fibril_rwlock_write_lock(&part->lock);
    10321132                if (part->svc_id != 0 && part->lpart->index != part->reg_idx) {
    10331133                        rc = vbds_part_svc_unregister(part);
    10341134                        if (rc != EOK) {
     1135                                fibril_rwlock_write_unlock(&part->lock);
     1136                                fibril_mutex_unlock(&vbds_parts_lock);
    10351137                                log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
    10361138                                    "un-registering partition.");
     
    10381140                        }
    10391141                }
     1142
     1143                fibril_rwlock_write_unlock(&part->lock);
    10401144        }
    10411145
    10421146        /* Now re-register those services under the new indices */
    10431147        list_foreach(disk->parts, ldisk, vbds_part_t, part) {
     1148                fibril_rwlock_write_lock(&part->lock);
    10441149                label_part_get_info(part->lpart, &lpinfo);
    10451150                if (part->svc_id == 0 && lpinfo.pkind != lpk_extended) {
    10461151                        rc = vbds_part_svc_register(part);
    10471152                        if (rc != EOK) {
     1153                                fibril_rwlock_write_unlock(&part->lock);
     1154                                fibril_mutex_unlock(&vbds_parts_lock);
    10481155                                log_msg(LOG_DEFAULT, LVL_ERROR, "Error "
    10491156                                    "re-registering partition.");
     
    10511158                        }
    10521159                }
    1053         }
     1160
     1161                fibril_rwlock_write_unlock(&part->lock);
     1162        }
     1163
     1164        fibril_mutex_unlock(&vbds_parts_lock);
    10541165
    10551166        return EOK;
  • uspace/srv/bd/vbd/types/vbd.h

    r8e670dd re11c527  
    11/*
    2  * Copyright (c) 2015 Jiri Svoboda
     2 * Copyright (c) 2016 Jiri Svoboda
    33 * All rights reserved.
    44 *
     
    3939
    4040#include <adt/list.h>
     41#include <atomic.h>
    4142#include <bd_srv.h>
    4243#include <label.h>
     
    4849typedef sysarg_t vbds_part_id_t;
    4950
     51typedef enum {
     52        /** No flags */
     53        vrf_none = 0,
     54        /** Force removal */
     55        vrf_force = 0x1
     56} vbds_rem_flag_t;
     57
    5058/** Partition */
    5159typedef struct {
     60        /** Reader held during I/O */
     61        fibril_rwlock_t lock;
    5262        /** Disk this partition belongs to */
    5363        struct vbds_disk *disk;
     
    7282        /** Number of blocks */
    7383        aoff64_t nblocks;
     84        /** Reference count */
     85        atomic_t refcnt;
    7486} vbds_part_t;
    7587
Note: See TracChangeset for help on using the changeset viewer.