Changeset 974f9ba in mainline for uspace/srv/bd/hr/raid1.c


Ignore:
Timestamp:
2025-07-04T19:42:41Z (3 weeks ago)
Author:
Miroslav Cimerman <mc@…>
Children:
c76bf33
Parents:
6aafb48
Message:

hr: different RAID 1 read strategies

First - take first usable extent.
Closest - take extent with last seek position.
Round-robin - always switch extents.
Split - split I/O to multiple extents.

File:
1 edited

Legend:

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

    r6aafb48 r974f9ba  
    5757
    5858static void hr_raid1_vol_state_eval_forced(hr_volume_t *);
    59 static size_t hr_raid1_count_good_extents(hr_volume_t *, uint64_t, size_t,
     59static size_t hr_raid1_count_good_w_extents(hr_volume_t *, uint64_t, size_t,
    6060    uint64_t);
    6161static errno_t hr_raid1_bd_op(hr_bd_op_type_t, hr_volume_t *, aoff64_t, size_t,
     
    286286}
    287287
    288 static size_t hr_raid1_count_good_extents(hr_volume_t *vol, uint64_t ba,
     288static size_t hr_raid1_count_good_w_extents(hr_volume_t *vol, uint64_t ba,
    289289    size_t cnt, uint64_t rebuild_blk)
    290290{
     
    304304}
    305305
     306#ifdef HR_RAID1_READ_STRATEGY_SPLIT
     307static size_t hr_raid1_count_good_r_extents(hr_volume_t *vol, uint64_t ba,
     308    size_t cnt, uint64_t rebuild_blk)
     309{
     310        assert(fibril_rwlock_is_locked(&vol->extents_lock));
     311        assert(fibril_rwlock_is_locked(&vol->states_lock));
     312
     313        size_t count = 0;
     314        for (size_t i = 0; i < vol->extent_no; i++) {
     315                if (vol->extents[i].state == HR_EXT_ONLINE ||
     316                    (vol->extents[i].state == HR_EXT_REBUILD &&
     317                    rebuild_blk > ba + cnt - 1)) {
     318                        count++;
     319                }
     320        }
     321
     322        return count;
     323}
     324#endif
     325
     326#ifdef HR_RAID1_READ_STRATEGY_CLOSEST
     327static size_t get_ext(hr_volume_t *vol, uint64_t ba, size_t cnt,
     328    uint64_t rebuild_blk)
     329{
     330        uint64_t closest_e;
     331        uint64_t pos;
     332        uint64_t mdiff = UINT64_MAX;
     333        hr_ext_state_t state = vol->extents[0].state;
     334        if (state != HR_EXT_ONLINE &&
     335            (state != HR_EXT_REBUILD || ba + cnt - 1 >= rebuild_blk)) {
     336                closest_e = 1;
     337        } else {
     338                closest_e = 0;
     339                pos = atomic_load_explicit(&vol->last_ext_pos_arr[0],
     340                    memory_order_relaxed);
     341                mdiff = (pos > ba) ? pos - ba : ba - pos;
     342        }
     343
     344        for (size_t e = 1; e < vol->extent_no; e++) {
     345                state = vol->extents[e].state;
     346                if (state != HR_EXT_ONLINE &&
     347                    (state != HR_EXT_REBUILD || ba + cnt - 1 >= rebuild_blk)) {
     348                        continue;
     349                }
     350
     351                pos = atomic_load_explicit(&vol->last_ext_pos_arr[e],
     352                    memory_order_relaxed);
     353                uint64_t diff = (pos > ba) ? pos - ba : ba - pos;
     354                if (diff < mdiff) {
     355                        mdiff = diff;
     356                        closest_e = e;
     357                }
     358        }
     359
     360        return closest_e;
     361}
     362
     363#elif defined(HR_RAID1_READ_STRATEGY_ROUND_ROBIN)
     364
     365static size_t get_ext(hr_volume_t *vol, uint64_t ba, size_t cnt,
     366    uint64_t rebuild_blk)
     367{
     368        size_t last_e;
     369        size_t fail = 0;
     370
     371        while (true) {
     372                last_e = atomic_fetch_add_explicit(&vol->last_ext_used, 1,
     373                    memory_order_relaxed);
     374                last_e %= vol->extent_no;
     375
     376                hr_ext_state_t state = vol->extents[last_e].state;
     377                if (state != HR_EXT_ONLINE &&
     378                    (state != HR_EXT_REBUILD || ba + cnt - 1 >= rebuild_blk)) {
     379                        if (++fail >= vol->extent_no)
     380                                return vol->extent_no;
     381                        continue;
     382                }
     383
     384                break;
     385        }
     386
     387        return last_e;
     388}
     389
     390#elif defined(HR_RAID1_READ_STRATEGY_FIRST)
     391
     392static size_t get_ext(hr_volume_t *vol, uint64_t ba, size_t cnt,
     393    uint64_t rebuild_blk)
     394{
     395        for (size_t e = 0; e < vol->extent_no; e++) {
     396                hr_ext_state_t state = vol->extents[e].state;
     397                if (state != HR_EXT_ONLINE &&
     398                    (state != HR_EXT_REBUILD || ba + cnt - 1 >= rebuild_blk)) {
     399                        continue;
     400                }
     401
     402                return e;
     403        }
     404        return vol->extent_no;
     405}
     406
     407#else
     408
     409#if !defined(HR_RAID1_READ_STRATEGY_SPLIT) || \
     410    !defined(HR_RAID1_READ_STRATEGY_SPLIT_THRESHOLD)
     411#error "Some RAID 1 read strategy must be used"
     412#endif
     413
     414#endif
     415
     416static size_t hr_raid1_read(hr_volume_t *vol, uint64_t ba, size_t cnt,
     417    void *data_read)
     418{
     419        uint64_t rebuild_blk;
     420        size_t successful = 0;
     421
     422#if !defined(HR_RAID1_READ_STRATEGY_SPLIT)
     423        errno_t rc;
     424
     425        rebuild_blk = atomic_load_explicit(&vol->rebuild_blk,
     426            memory_order_relaxed);
     427        size_t fail = 0;
     428        while (fail < vol->extent_no) {
     429                fibril_rwlock_read_lock(&vol->states_lock);
     430                size_t best_e = get_ext(vol, ba, cnt,
     431                    rebuild_blk);
     432                fibril_rwlock_read_unlock(&vol->states_lock);
     433                if (best_e >= vol->extent_no)
     434                        break;
     435                rc = hr_read_direct(vol->extents[best_e].svc_id, ba,
     436                    cnt, data_read);
     437                if (rc != EOK) {
     438                        hr_raid1_ext_state_cb(vol, best_e, rc);
     439                        fail++;
     440                } else {
     441                        successful++;
     442                        break;
     443                }
     444        }
     445
     446#else
     447
     448retry_split:
     449        size_t good;
     450        rebuild_blk = atomic_load_explicit(&vol->rebuild_blk,
     451            memory_order_relaxed);
     452
     453        fibril_rwlock_read_lock(&vol->states_lock);
     454        good = hr_raid1_count_good_r_extents(vol, ba, cnt,
     455            rebuild_blk);
     456        fibril_rwlock_read_unlock(&vol->states_lock);
     457
     458        size_t cnt_per_ext = (cnt + good - 1) / good;
     459        if (cnt_per_ext * vol->bsize < HR_RAID1_READ_STRATEGY_SPLIT_THRESHOLD)
     460                cnt_per_ext = cnt;
     461
     462        hr_fgroup_t *group = hr_fgroup_create(vol->fge, good);
     463
     464        fibril_rwlock_read_lock(&vol->states_lock);
     465        size_t left = cnt;
     466        size_t e = 0;
     467        uint8_t *data = data_read;
     468        size_t submitted = 0;
     469        while (left > 0) {
     470                if (e >= vol->extent_no) {
     471                        fibril_rwlock_read_unlock(&vol->states_lock);
     472                        if (submitted)
     473                                (void)hr_fgroup_wait(group, NULL, NULL);
     474                        goto retry_split;
     475                }
     476
     477                hr_ext_state_t state = vol->extents[e].state;
     478                if (state != HR_EXT_ONLINE &&
     479                    (state != HR_EXT_REBUILD ||
     480                    ba + cnt - 1 >= rebuild_blk)) {
     481                        e++;
     482                        continue;
     483                }
     484
     485                hr_io_t *io = hr_fgroup_alloc(group);
     486                io->extent = e;
     487                io->data_read = data;
     488                io->ba = ba + (cnt - left);
     489                size_t cnt_to_dispatch = min(left, cnt_per_ext);
     490                io->cnt = cnt_to_dispatch;
     491                io->type = HR_BD_READ;
     492                io->vol = vol;
     493
     494                hr_fgroup_submit(group, hr_io_worker, io);
     495                submitted++;
     496
     497                data += cnt_to_dispatch * vol->bsize;
     498                left -= cnt_to_dispatch;
     499                e++;
     500        }
     501
     502        fibril_rwlock_read_unlock(&vol->states_lock);
     503
     504        (void)hr_fgroup_wait(group, &successful, NULL);
     505#endif
     506
     507        return successful;
     508}
     509
    306510static errno_t hr_raid1_bd_op(hr_bd_op_type_t type, hr_volume_t *vol,
    307511    aoff64_t ba, size_t cnt, void *data_read, const void *data_write,
     
    312516        hr_range_lock_t *rl = NULL;
    313517        errno_t rc;
    314         size_t i;
    315518        uint64_t rebuild_blk;
    316519
     
    345548        fibril_rwlock_read_lock(&vol->extents_lock);
    346549
    347         size_t successful = 0;
     550        size_t good;
     551        size_t successful;
    348552        switch (type) {
    349553        case HR_BD_READ:
    350                 rebuild_blk = atomic_load_explicit(&vol->rebuild_blk,
    351                     memory_order_relaxed);
    352 
    353                 for (i = 0; i < vol->extent_no; i++) {
    354                         fibril_rwlock_read_lock(&vol->states_lock);
    355                         hr_ext_state_t state = vol->extents[i].state;
    356                         fibril_rwlock_read_unlock(&vol->states_lock);
    357 
    358                         if (state != HR_EXT_ONLINE &&
    359                             (state != HR_EXT_REBUILD ||
    360                             ba + cnt - 1 >= rebuild_blk)) {
    361                                 continue;
    362                         }
    363 
    364                         rc = hr_read_direct(vol->extents[i].svc_id, ba, cnt,
    365                             data_read);
    366                         if (rc != EOK) {
    367                                 hr_raid1_ext_state_cb(vol, i, rc);
    368                         } else {
    369                                 successful++;
    370                                 break;
    371                         }
    372                 }
     554                successful = hr_raid1_read(vol, ba, cnt, data_read);
    373555                break;
    374556        case HR_BD_WRITE:
     
    380562                    memory_order_relaxed);
    381563
    382                 size_t good = hr_raid1_count_good_extents(vol, ba, cnt,
     564                good = hr_raid1_count_good_w_extents(vol, ba, cnt,
    383565                    rebuild_blk);
    384566
    385567                hr_fgroup_t *group = hr_fgroup_create(vol->fge, good);
    386568
    387                 for (i = 0; i < vol->extent_no; i++) {
     569                for (size_t i = 0; i < vol->extent_no; i++) {
    388570                        if (vol->extents[i].state != HR_EXT_ONLINE &&
    389571                            (vol->extents[i].state != HR_EXT_REBUILD ||
     
    402584                        io->extent = i;
    403585                        io->data_write = data_write;
    404                         io->data_read = data_read;
    405586                        io->ba = ba;
    406587                        io->cnt = cnt;
Note: See TracChangeset for help on using the changeset viewer.