Changeset 38e3c0a7 in mainline


Ignore:
Timestamp:
2024-12-22T15:35:54Z (5 months ago)
Author:
Miroslav Cimerman <mc@…>
Children:
83c8bb2
Parents:
f725787
Message:

hr: range locks

Location:
uspace/srv/bd/hr
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/bd/hr/util.c

    rf725787 r38e3c0a7  
    3434 */
    3535
     36#include <adt/list.h>
    3637#include <block.h>
    3738#include <errno.h>
     39#include <fibril_synch.h>
    3840#include <hr.h>
    3941#include <io/log.h>
     
    4648#include "var.h"
    4749
     50#define HR_RL_LIST_LOCK(vol) (fibril_mutex_lock(&vol->range_lock_list_lock))
     51#define HR_RL_LIST_UNLOCK(vol) \
     52    (fibril_mutex_unlock(&vol->range_lock_list_lock))
     53
     54static bool hr_range_lock_overlap(hr_range_lock_t *, hr_range_lock_t *);
     55
    4856extern loc_srv_t *hr_srv;
    4957
     
    128136
    129137        vol->svc_id = new_id;
    130 
    131138error:
    132139        free(fullname);
     
    258265{
    259266        size_t count = 0;
    260         for (size_t i = 0; i < vol->extent_no; i++) {
     267        for (size_t i = 0; i < vol->extent_no; i++)
    261268                if (vol->extents[i].status == status)
    262269                        count++;
    263         }
    264270
    265271        return count;
    266272}
    267273
     274hr_range_lock_t *hr_range_lock_acquire(hr_volume_t *vol, uint64_t ba,
     275    uint64_t cnt)
     276{
     277        hr_range_lock_t *rl = malloc(sizeof(hr_range_lock_t));
     278        if (rl == NULL)
     279                return NULL;
     280
     281        rl->vol = vol;
     282        rl->off = ba;
     283        rl->len = cnt;
     284
     285        rl->pending = 1;
     286        rl->ignore = false;
     287
     288        link_initialize(&rl->link);
     289        fibril_mutex_initialize(&rl->lock);
     290
     291        fibril_mutex_lock(&rl->lock);
     292
     293again:
     294        HR_RL_LIST_LOCK(vol);
     295        list_foreach(vol->range_lock_list, link, hr_range_lock_t, rlp) {
     296                if (rlp->ignore)
     297                        continue;
     298                if (hr_range_lock_overlap(rlp, rl)) {
     299                        rlp->pending++;
     300
     301                        HR_RL_LIST_UNLOCK(vol);
     302
     303                        fibril_mutex_lock(&rlp->lock);
     304
     305                        HR_RL_LIST_LOCK(vol);
     306
     307                        rlp->pending--;
     308
     309                        /*
     310                         * when ignore is set, after HR_RL_LIST_UNLOCK(),
     311                         * noone new is going to be able to start sleeping
     312                         * on the ignored range lock, only already waiting
     313                         * IOs will come through here
     314                         */
     315                        rlp->ignore = true;
     316
     317                        fibril_mutex_unlock(&rlp->lock);
     318
     319                        if (rlp->pending == 0) {
     320                                list_remove(&rlp->link);
     321                                free(rlp);
     322                        }
     323
     324                        HR_RL_LIST_UNLOCK(vol);
     325                        goto again;
     326                }
     327        }
     328
     329        list_append(&rl->link, &vol->range_lock_list);
     330
     331        HR_RL_LIST_UNLOCK(vol);
     332        return rl;
     333}
     334
     335void hr_range_lock_release(hr_range_lock_t *rl)
     336{
     337        HR_RL_LIST_LOCK(rl->vol);
     338
     339        rl->pending--;
     340
     341        fibril_mutex_unlock(&rl->lock);
     342
     343        if (rl->pending == 0) {
     344                list_remove(&rl->link);
     345                free(rl);
     346        }
     347
     348        HR_RL_LIST_UNLOCK(rl->vol);
     349}
     350
     351static bool hr_range_lock_overlap(hr_range_lock_t *rl1, hr_range_lock_t *rl2)
     352{
     353        uint64_t rl1_start = rl1->off;
     354        uint64_t rl1_end = rl1->off + rl1->len - 1;
     355        uint64_t rl2_start = rl2->off;
     356        uint64_t rl2_end = rl2->off + rl2->len - 1;
     357
     358        /* one ends before the other starts */
     359        if (rl1_end < rl2_start || rl2_end < rl1_start)
     360                return false;
     361
     362        return true;
     363}
     364
    268365/** @}
    269366 */
  • uspace/srv/bd/hr/util.h

    rf725787 r38e3c0a7  
    6161extern void hr_sync_all_extents(hr_volume_t *);
    6262extern size_t hr_count_extents(hr_volume_t *, hr_ext_status_t);
     63extern hr_range_lock_t *hr_range_lock_acquire(hr_volume_t *, uint64_t,
     64    uint64_t);
     65extern void hr_range_lock_release(hr_range_lock_t *rl);
    6366
    6467#endif
  • uspace/srv/bd/hr/var.h

    rf725787 r38e3c0a7  
    3737#define _HR_VAR_H
    3838
     39#include <adt/list.h>
    3940#include <bd_srv.h>
    4041#include <errno.h>
     42#include <fibril_synch.h>
    4143#include <hr.h>
    4244
     
    6062        link_t lvolumes;
    6163        fibril_mutex_t lock;
     64
     65        list_t range_lock_list;
     66        fibril_mutex_t range_lock_list_lock;
    6267
    6368        size_t extent_no;
     
    9095} hr_bd_op_type_t;
    9196
     97typedef struct hr_range_lock {
     98        fibril_mutex_t lock;
     99        link_t link;
     100        hr_volume_t *vol;
     101        uint64_t off;
     102        uint64_t len;
     103        size_t pending; /* protected by vol->range_lock_list_lock */
     104        bool ignore; /* protected by vol->range_lock_list_lock */
     105} hr_range_lock_t;
     106
    92107extern errno_t hr_init_devs(hr_volume_t *);
    93108extern void hr_fini_devs(hr_volume_t *);
Note: See TracChangeset for help on using the changeset viewer.