// SPDX-License-Identifier: GPL-2.0-or-later /* * raid1.c : Multiple Devices driver for Linux * * Copyright (C) 1999, 2000, 2001 Ingo Molnar, Red Hat * * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman * * RAID-1 management functions. * * Better read-balancing code written by Mika Kuoppala <miku@iki.fi>, 2000 * * Fixes to reconstruction by Jakob Østergaard" <jakob@ostenfeld.dk> * Various fixes by Neil Brown <neilb@cse.unsw.edu.au> * * Changes by Peter T. Breuer <ptb@it.uc3m.es> 31/1/2003 to support * bitmapped intelligence in resync: * * - bitmap marked during normal i/o * - bitmap used to skip nondirty blocks during sync * * Additions to bitmap code, (C) 2003-2004 Paul Clements, SteelEye Technology: * - persistent bitmap code
*/
spin_lock_irqsave(&serial->serial_lock, flags); for (si = raid1_rb_iter_first(&serial->serial_rb, lo, hi);
si; si = raid1_rb_iter_next(si, lo, hi)) { if (si->start == lo && si->last == hi) {
raid1_rb_remove(si, &serial->serial_rb);
mempool_free(si, mddev->serial_info_pool);
found = 1; break;
}
} if (!found)
WARN(1, "The write IO is not recorded for serialization\n");
spin_unlock_irqrestore(&serial->serial_lock, flags);
wake_up(&serial->serial_io_wait);
}
/* * for resync bio, r1bio pointer can be retrieved from the per-bio * 'struct resync_pages'.
*/ staticinlinestruct r1bio *get_resync_r1bio(struct bio *bio)
{ return get_resync_pages(bio)->raid_bio;
}
/* * Allocate bios : 1 for reading, n-1 for writing
*/ for (j = conf->raid_disks * 2; j-- ; ) {
bio = bio_kmalloc(RESYNC_PAGES, gfp_flags); if (!bio) goto out_free_bio;
bio_init(bio, NULL, bio->bi_inline_vecs, RESYNC_PAGES, 0);
r1_bio->bios[j] = bio;
} /* * Allocate RESYNC_PAGES data pages and attach them to * the first bio. * If this is a user-requested check/repair, allocate * RESYNC_PAGES for each bio.
*/ if (test_bit(MD_RECOVERY_REQUESTED, &conf->mddev->recovery))
need_pages = conf->raid_disks * 2; else
need_pages = 1; for (j = 0; j < conf->raid_disks * 2; j++) { struct resync_pages *rp = &rps[j];
bio = r1_bio->bios[j];
if (j < need_pages) { if (resync_alloc_pages(rp, gfp_flags)) goto out_free_pages;
} else {
memcpy(rp, &rps[0], sizeof(*rp));
resync_get_all_pages(rp);
}
rp->raid_bio = r1_bio;
bio->bi_private = rp;
}
r1_bio->master_bio = NULL;
return r1_bio;
out_free_pages: while (--j >= 0)
resync_free_pages(&rps[j]);
for (i = 0; i < conf->raid_disks * 2; i++) { struct bio *bio = r1_bio->bios[i]; if (bio->bi_end_io)
rdev_dec_pending(conf->mirrors[i].rdev, r1_bio->mddev);
}
/* * raid_end_bio_io() is called when we have finished servicing a mirrored * operation and are ready to return a success/failure code to the buffer * cache layer.
*/ staticvoid call_bio_endio(struct r1bio *r1_bio)
{ struct bio *bio = r1_bio->master_bio;
if (!test_bit(R1BIO_Uptodate, &r1_bio->state))
bio->bi_status = BLK_STS_IOERR;
/* if nobody has done the final endio yet, do it now */ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) {
pr_debug("raid1: sync end %s on sectors %llu-%llu\n",
(bio_data_dir(bio) == WRITE) ? "write" : "read",
(unsignedlonglong) bio->bi_iter.bi_sector,
(unsignedlonglong) bio_end_sector(bio) - 1);
call_bio_endio(r1_bio);
}
free_r1bio(r1_bio); /* * Wake up any possible resync thread that waits for the device * to go idle. All I/Os, even write-behind writes, are done.
*/
allow_barrier(conf, sector);
}
/* * Update disk head position estimator based on IRQ completion info.
*/ staticinlinevoid update_head_pos(int disk, struct r1bio *r1_bio)
{ struct r1conf *conf = r1_bio->mddev->private;
/* * Find the disk number which triggered given bio
*/ staticint find_bio_disk(struct r1bio *r1_bio, struct bio *bio)
{ int mirror; struct r1conf *conf = r1_bio->mddev->private; int raid_disks = conf->raid_disks;
for (mirror = 0; mirror < raid_disks * 2; mirror++) if (r1_bio->bios[mirror] == bio) break;
/* * this branch is our 'one mirror IO has finished' event handler:
*/
update_head_pos(r1_bio->read_disk, r1_bio);
if (uptodate) {
set_bit(R1BIO_Uptodate, &r1_bio->state);
} elseif (test_bit(FailFast, &rdev->flags) &&
test_bit(R1BIO_FailFast, &r1_bio->state)) { /* This was a fail-fast read so we definitely
* want to retry */
;
} elseif (!raid1_should_handle_error(bio)) {
uptodate = 1;
} else { /* If all other devices have failed, we want to return * the error upwards rather than fail the last device. * Here we redefine "uptodate" to mean "Don't want to retry"
*/ unsignedlong flags;
spin_lock_irqsave(&conf->device_lock, flags); if (r1_bio->mddev->degraded == conf->raid_disks ||
(r1_bio->mddev->degraded == conf->raid_disks-1 &&
test_bit(In_sync, &rdev->flags)))
uptodate = 1;
spin_unlock_irqrestore(&conf->device_lock, flags);
}
if (uptodate) {
raid_end_bio_io(r1_bio);
rdev_dec_pending(rdev, conf->mddev);
} else { /* * oops, read error:
*/
pr_err_ratelimited("md/raid1:%s: %pg: rescheduling sector %llu\n",
mdname(conf->mddev),
rdev->bdev,
(unsignedlonglong)r1_bio->sector);
set_bit(R1BIO_ReadError, &r1_bio->state);
reschedule_retry(r1_bio); /* don't drop the reference on read_disk yet */
}
}
/* it really is the end of this request */ if (test_bit(R1BIO_BehindIO, &r1_bio->state)) {
bio_free_pages(r1_bio->behind_master_bio);
bio_put(r1_bio->behind_master_bio);
r1_bio->behind_master_bio = NULL;
}
if (test_bit(R1BIO_BehindIO, &r1_bio->state))
mddev->bitmap_ops->end_behind_write(mddev);
md_write_end(mddev);
}
staticvoid r1_bio_write_done(struct r1bio *r1_bio)
{ if (!atomic_dec_and_test(&r1_bio->remaining)) return;
if (test_bit(R1BIO_WriteError, &r1_bio->state))
reschedule_retry(r1_bio); else {
close_write(r1_bio); if (test_bit(R1BIO_MadeGood, &r1_bio->state))
reschedule_retry(r1_bio); else
raid_end_bio_io(r1_bio);
}
}
staticvoid raid1_end_write_request(struct bio *bio)
{ struct r1bio *r1_bio = bio->bi_private; int behind = test_bit(R1BIO_BehindIO, &r1_bio->state); struct r1conf *conf = r1_bio->mddev->private; struct bio *to_put = NULL; int mirror = find_bio_disk(r1_bio, bio); struct md_rdev *rdev = conf->mirrors[mirror].rdev;
sector_t lo = r1_bio->sector;
sector_t hi = r1_bio->sector + r1_bio->sectors; bool ignore_error = !raid1_should_handle_error(bio) ||
(bio->bi_status && bio_op(bio) == REQ_OP_DISCARD);
/* * 'one mirror IO has finished' event handler:
*/ if (bio->bi_status && !ignore_error) {
set_bit(WriteErrorSeen, &rdev->flags); if (!test_and_set_bit(WantReplacement, &rdev->flags))
set_bit(MD_RECOVERY_NEEDED, &
conf->mddev->recovery);
if (test_bit(FailFast, &rdev->flags) &&
(bio->bi_opf & MD_FAILFAST) && /* We never try FailFast to WriteMostly devices */
!test_bit(WriteMostly, &rdev->flags)) {
md_error(r1_bio->mddev, rdev);
}
/* * When the device is faulty, it is not necessary to * handle write error.
*/ if (!test_bit(Faulty, &rdev->flags))
set_bit(R1BIO_WriteError, &r1_bio->state); else { /* Finished with this branch */
r1_bio->bios[mirror] = NULL;
to_put = bio;
}
} else { /* * Set R1BIO_Uptodate in our master bio, so that we * will return a good error code for to the higher * levels even if IO on some other mirrored buffer * fails. * * The 'master' represents the composite IO operation * to user-side. So if something waits for IO, then it * will wait for the 'master' bio.
*/
r1_bio->bios[mirror] = NULL;
to_put = bio; /* * Do not set R1BIO_Uptodate if the current device is * rebuilding or Faulty. This is because we cannot use * such device for properly reading the data back (we could * potentially use it, if the current write would have felt * before rdev->recovery_offset, but for simplicity we don't * check this here.
*/ if (test_bit(In_sync, &rdev->flags) &&
!test_bit(Faulty, &rdev->flags))
set_bit(R1BIO_Uptodate, &r1_bio->state);
/* Maybe we can clear some bad blocks. */ if (rdev_has_badblock(rdev, r1_bio->sector, r1_bio->sectors) &&
!ignore_error) {
r1_bio->bios[mirror] = IO_MADE_GOOD;
set_bit(R1BIO_MadeGood, &r1_bio->state);
}
}
if (behind) { if (test_bit(CollisionCheck, &rdev->flags))
remove_serial(rdev, lo, hi); if (test_bit(WriteMostly, &rdev->flags))
atomic_dec(&r1_bio->behind_remaining);
/* * In behind mode, we ACK the master bio once the I/O * has safely reached all non-writemostly * disks. Setting the Returned bit ensures that this * gets done only once -- we don't ever want to return * -EIO here, instead we'll wait
*/ if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) &&
test_bit(R1BIO_Uptodate, &r1_bio->state)) { /* Maybe we can return now */ if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { struct bio *mbio = r1_bio->master_bio;
pr_debug("raid1: behind end write sectors" " %llu-%llu\n",
(unsignedlonglong) mbio->bi_iter.bi_sector,
(unsignedlonglong) bio_end_sector(mbio) - 1);
call_bio_endio(r1_bio);
}
}
} elseif (rdev->mddev->serialize_policy)
remove_serial(rdev, lo, hi); if (r1_bio->bios[mirror] == NULL)
rdev_dec_pending(rdev, conf->mddev);
/* * Let's see if all mirrored write operations have finished * already.
*/
r1_bio_write_done(r1_bio);
WARN_ON(sectors == 0); /* * len is the number of sectors from start_sector to end of the * barrier unit which start_sector belongs to.
*/
len = round_up(start_sector + 1, BARRIER_UNIT_SECTOR_SIZE) -
start_sector;
if (len > sectors)
len = sectors;
return len;
}
staticvoid update_read_sectors(struct r1conf *conf, int disk,
sector_t this_sector, int len)
{ struct raid1_info *info = &conf->mirrors[disk];
staticint choose_first_rdev(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors)
{
sector_t this_sector = r1_bio->sector; int len = r1_bio->sectors; int disk;
for (disk = 0 ; disk < conf->raid_disks * 2 ; disk++) { struct md_rdev *rdev; int read_len;
if (r1_bio->bios[disk] == IO_BLOCKED) continue;
rdev = conf->mirrors[disk].rdev; if (!rdev || test_bit(Faulty, &rdev->flags)) continue;
/* choose the first disk even if it has some bad blocks. */
read_len = raid1_check_read_range(rdev, this_sector, &len); if (read_len > 0) {
update_read_sectors(conf, disk, this_sector, read_len);
*max_sectors = read_len; return disk;
}
}
/* keep track of the disk with the most readable sectors. */
len = r1_bio->sectors;
read_len = raid1_check_read_range(rdev, this_sector, &len); if (read_len > best_len) {
best_disk = disk;
best_len = read_len;
}
}
/* there are no bad blocks, we can use this disk */
len = r1_bio->sectors;
read_len = raid1_check_read_range(rdev, this_sector, &len); if (read_len == r1_bio->sectors) {
*max_sectors = read_len;
update_read_sectors(conf, disk, this_sector, read_len); return disk;
}
/* * there are partial bad blocks, choose the rdev with largest * read length.
*/ if (read_len > bb_read_len) {
bb_disk = disk;
bb_read_len = read_len;
}
}
staticbool is_sequential(struct r1conf *conf, int disk, struct r1bio *r1_bio)
{ /* TODO: address issues with this check and concurrency. */ return conf->mirrors[disk].next_seq_sect == r1_bio->sector ||
conf->mirrors[disk].head_position == r1_bio->sector;
}
/* * If buffered sequential IO size exceeds optimal iosize, check if there is idle * disk. If yes, choose the idle disk.
*/ staticbool should_choose_next(struct r1conf *conf, int disk)
{ struct raid1_info *mirror = &conf->mirrors[disk]; int opt_iosize;
if (!test_bit(Nonrot, &mirror->rdev->flags)) returnfalse;
/* don't read from slow disk unless have to */ if (test_bit(WriteMostly, &rdev->flags)) returnfalse;
/* don't split IO for bad blocks unless have to */ if (rdev_has_badblock(rdev, r1_bio->sector, r1_bio->sectors)) returnfalse;
returntrue;
}
struct read_balance_ctl {
sector_t closest_dist; int closest_dist_disk; int min_pending; int min_pending_disk; int sequential_disk; int readable_disks;
};
/* Don't change to another disk for sequential reads */ if (is_sequential(conf, disk, r1_bio)) { if (!should_choose_next(conf, disk)) return disk;
/* * Add 'pending' to avoid choosing this disk if * there is other idle disk.
*/
pending++; /* * If there is no other idle disk, this disk * will be chosen.
*/
ctl.sequential_disk = disk;
}
/* * sequential IO size exceeds optimal iosize, however, there is no other * idle disk, so choose the sequential disk.
*/ if (ctl.sequential_disk != -1 && ctl.min_pending != 0) return ctl.sequential_disk;
/* * If all disks are rotational, choose the closest disk. If any disk is * non-rotational, choose the disk with less pending request even the * disk is rotational, which might/might not be optimal for raids with * mixed ratation/non-rotational disks depending on workload.
*/ if (ctl.min_pending_disk != -1 &&
(READ_ONCE(conf->nonrot_disks) || ctl.min_pending == 0)) return ctl.min_pending_disk; else return ctl.closest_dist_disk;
}
/* * This routine returns the disk from which the requested read should be done. * * 1) If resync is in progress, find the first usable disk and use it even if it * has some bad blocks. * * 2) Now that there is no resync, loop through all disks and skipping slow * disks and disks with bad blocks for now. Only pay attention to key disk * choice. * * 3) If we've made it this far, now look for disks with bad blocks and choose * the one with most number of sectors. * * 4) If we are all the way at the end, we have no choice but to use a disk even * if it is write mostly. * * The rdev for the device selected will have nr_pending incremented.
*/ staticint read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sectors)
{ int disk;
clear_bit(R1BIO_FailFast, &r1_bio->state);
if (raid1_should_read_first(conf->mddev, r1_bio->sector,
r1_bio->sectors)) return choose_first_rdev(conf, r1_bio, max_sectors);
disk = choose_best_rdev(conf, r1_bio); if (disk >= 0) {
*max_sectors = r1_bio->sectors;
update_read_sectors(conf, disk, r1_bio->sector,
r1_bio->sectors); return disk;
}
/* * If we are here it means we didn't find a perfectly good disk so * now spend a bit more time trying to find one with the most good * sectors.
*/
disk = choose_bb_rdev(conf, r1_bio, max_sectors); if (disk >= 0) return disk;
staticvoid wake_up_barrier(struct r1conf *conf)
{ if (wq_has_sleeper(&conf->wait_barrier))
wake_up(&conf->wait_barrier);
}
staticvoid flush_bio_list(struct r1conf *conf, struct bio *bio)
{ /* flush any pending bitmap writes to disk before proceeding w/ I/O */
raid1_prepare_flush_writes(conf->mddev);
wake_up_barrier(conf);
while (bio) { /* submit pending writes */ struct bio *next = bio->bi_next;
raid1_submit_write(bio);
bio = next;
cond_resched();
}
}
staticvoid flush_pending_writes(struct r1conf *conf)
{ /* Any writes that have been queued but are awaiting * bitmap updates get flushed here.
*/
spin_lock_irq(&conf->device_lock);
if (conf->pending_bio_list.head) { struct blk_plug plug; struct bio *bio;
bio = bio_list_get(&conf->pending_bio_list);
spin_unlock_irq(&conf->device_lock);
/* * As this is called in a wait_event() loop (see freeze_array), * current->state might be TASK_UNINTERRUPTIBLE which will * cause a warning when we prepare to wait again. As it is * rare that this path is taken, it is perfectly safe to force * us to go around the wait_event() loop again, so the warning * is a false-positive. Silence the warning by resetting * thread state
*/
__set_current_state(TASK_RUNNING);
blk_start_plug(&plug);
flush_bio_list(conf, bio);
blk_finish_plug(&plug);
} else
spin_unlock_irq(&conf->device_lock);
}
/* Barriers.... * Sometimes we need to suspend IO while we do something else, * either some resync/recovery, or reconfigure the array. * To do this we raise a 'barrier'. * The 'barrier' is a counter that can be raised multiple times * to count how many activities are happening which preclude * normal IO. * We can only raise the barrier if there is no pending IO. * i.e. if nr_pending == 0. * We choose only to raise the barrier if no-one is waiting for the * barrier to go down. This means that as soon as an IO request * is ready, no other operations which require a barrier will start * until the IO request has had a chance. * * So: regular IO calls 'wait_barrier'. When that returns there * is no backgroup IO happening, It must arrange to call * allow_barrier when it has finished its IO. * backgroup IO calls must call raise_barrier. Once that returns * there is no normal IO happeing. It must arrange to call * lower_barrier when the particular background IO completes. * * If resync/recovery is interrupted, returns -EINTR; * Otherwise, returns 0.
*/ staticint raise_barrier(struct r1conf *conf, sector_t sector_nr)
{ int idx = sector_to_idx(sector_nr);
spin_lock_irq(&conf->resync_lock);
/* Wait until no block IO is waiting */
wait_event_lock_irq(conf->wait_barrier,
!atomic_read(&conf->nr_waiting[idx]),
conf->resync_lock);
/* block any new IO from starting */
atomic_inc(&conf->barrier[idx]); /* * In raise_barrier() we firstly increase conf->barrier[idx] then * check conf->nr_pending[idx]. In _wait_barrier() we firstly * increase conf->nr_pending[idx] then check conf->barrier[idx]. * A memory barrier here to make sure conf->nr_pending[idx] won't * be fetched before conf->barrier[idx] is increased. Otherwise * there will be a race between raise_barrier() and _wait_barrier().
*/
smp_mb__after_atomic();
/* For these conditions we must wait: * A: while the array is in frozen state * B: while conf->nr_pending[idx] is not 0, meaning regular I/O * existing in corresponding I/O barrier bucket. * C: while conf->barrier[idx] >= RESYNC_DEPTH, meaning reaches * max resync count which allowed on current I/O barrier bucket.
*/
wait_event_lock_irq(conf->wait_barrier,
(!conf->array_frozen &&
!atomic_read(&conf->nr_pending[idx]) &&
atomic_read(&conf->barrier[idx]) < RESYNC_DEPTH) ||
test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery),
conf->resync_lock);
if (test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) {
atomic_dec(&conf->barrier[idx]);
spin_unlock_irq(&conf->resync_lock);
wake_up(&conf->wait_barrier); return -EINTR;
}
staticbool _wait_barrier(struct r1conf *conf, int idx, bool nowait)
{ bool ret = true;
/* * We need to increase conf->nr_pending[idx] very early here, * then raise_barrier() can be blocked when it waits for * conf->nr_pending[idx] to be 0. Then we can avoid holding * conf->resync_lock when there is no barrier raised in same * barrier unit bucket. Also if the array is frozen, I/O * should be blocked until array is unfrozen.
*/
atomic_inc(&conf->nr_pending[idx]); /* * In _wait_barrier() we firstly increase conf->nr_pending[idx], then * check conf->barrier[idx]. In raise_barrier() we firstly increase * conf->barrier[idx], then check conf->nr_pending[idx]. A memory * barrier is necessary here to make sure conf->barrier[idx] won't be * fetched before conf->nr_pending[idx] is increased. Otherwise there * will be a race between _wait_barrier() and raise_barrier().
*/
smp_mb__after_atomic();
/* * Don't worry about checking two atomic_t variables at same time * here. If during we check conf->barrier[idx], the array is * frozen (conf->array_frozen is 1), and chonf->barrier[idx] is * 0, it is safe to return and make the I/O continue. Because the * array is frozen, all I/O returned here will eventually complete * or be queued, no race will happen. See code comment in * frozen_array().
*/ if (!READ_ONCE(conf->array_frozen) &&
!atomic_read(&conf->barrier[idx])) return ret;
/* * After holding conf->resync_lock, conf->nr_pending[idx] * should be decreased before waiting for barrier to drop. * Otherwise, we may encounter a race condition because * raise_barrer() might be waiting for conf->nr_pending[idx] * to be 0 at same time.
*/
spin_lock_irq(&conf->resync_lock);
atomic_inc(&conf->nr_waiting[idx]);
atomic_dec(&conf->nr_pending[idx]); /* * In case freeze_array() is waiting for * get_unqueued_pending() == extra
*/
wake_up_barrier(conf); /* Wait for the barrier in same barrier unit bucket to drop. */
/* Return false when nowait flag is set */ if (nowait) {
ret = false;
} else {
wait_event_lock_irq(conf->wait_barrier,
!conf->array_frozen &&
!atomic_read(&conf->barrier[idx]),
conf->resync_lock);
atomic_inc(&conf->nr_pending[idx]);
}
staticbool wait_read_barrier(struct r1conf *conf, sector_t sector_nr, bool nowait)
{ int idx = sector_to_idx(sector_nr); bool ret = true;
/* * Very similar to _wait_barrier(). The difference is, for read * I/O we don't need wait for sync I/O, but if the whole array * is frozen, the read I/O still has to wait until the array is * unfrozen. Since there is no ordering requirement with * conf->barrier[idx] here, memory barrier is unnecessary as well.
*/
atomic_inc(&conf->nr_pending[idx]);
if (!READ_ONCE(conf->array_frozen)) return ret;
spin_lock_irq(&conf->resync_lock);
atomic_inc(&conf->nr_waiting[idx]);
atomic_dec(&conf->nr_pending[idx]); /* * In case freeze_array() is waiting for * get_unqueued_pending() == extra
*/
wake_up_barrier(conf); /* Wait for array to be unfrozen */
/* Return false when nowait flag is set */ if (nowait) { /* Return false when nowait flag is set */
ret = false;
} else {
wait_event_lock_irq(conf->wait_barrier,
!conf->array_frozen,
conf->resync_lock);
atomic_inc(&conf->nr_pending[idx]);
}
/* conf->resync_lock should be held */ staticint get_unqueued_pending(struct r1conf *conf)
{ int idx, ret;
ret = atomic_read(&conf->nr_sync_pending); for (idx = 0; idx < BARRIER_BUCKETS_NR; idx++)
ret += atomic_read(&conf->nr_pending[idx]) -
atomic_read(&conf->nr_queued[idx]);
return ret;
}
staticvoid freeze_array(struct r1conf *conf, int extra)
{ /* Stop sync I/O and normal I/O and wait for everything to * go quiet. * This is called in two situations: * 1) management command handlers (reshape, remove disk, quiesce). * 2) one normal I/O request failed.
* After array_frozen is set to 1, new sync IO will be blocked at * raise_barrier(), and new normal I/O will blocked at _wait_barrier() * or wait_read_barrier(). The flying I/Os will either complete or be * queued. When everything goes quite, there are only queued I/Os left.
* Every flying I/O contributes to a conf->nr_pending[idx], idx is the * barrier bucket index which this I/O request hits. When all sync and * normal I/O are queued, sum of all conf->nr_pending[] will match sum * of all conf->nr_queued[]. But normal I/O failure is an exception, * in handle_read_error(), we may call freeze_array() before trying to * fix the read error. In this case, the error read I/O is not queued, * so get_unqueued_pending() == 1. * * Therefore before this function returns, we need to wait until * get_unqueued_pendings(conf) gets equal to extra. For * normal I/O context, extra is 1, in rested situations extra is 0.
*/
spin_lock_irq(&conf->resync_lock);
conf->array_frozen = 1;
mddev_add_trace_msg(conf->mddev, "raid1 wait freeze");
wait_event_lock_irq_cmd(
conf->wait_barrier,
get_unqueued_pending(conf) == extra,
conf->resync_lock,
flush_pending_writes(conf));
spin_unlock_irq(&conf->resync_lock);
} staticvoid unfreeze_array(struct r1conf *conf)
{ /* reverse the effect of the freeze */
spin_lock_irq(&conf->resync_lock);
conf->array_frozen = 0;
spin_unlock_irq(&conf->resync_lock);
wake_up(&conf->wait_barrier);
}
staticvoid alloc_behind_master_bio(struct r1bio *r1_bio, struct bio *bio)
{ int size = bio->bi_iter.bi_size; unsigned vcnt = (size + PAGE_SIZE - 1) >> PAGE_SHIFT; int i = 0; struct bio *behind_bio = NULL;
staticvoid raid1_read_request(struct mddev *mddev, struct bio *bio, int max_read_sectors, struct r1bio *r1_bio)
{ struct r1conf *conf = mddev->private; struct raid1_info *mirror; struct bio *read_bio; int max_sectors; int rdisk, error; bool r1bio_existed = !!r1_bio;
/* * If r1_bio is set, we are blocking the raid1d thread * so there is a tiny risk of deadlock. So ask for * emergency memory if needed.
*/
gfp_t gfp = r1_bio ? (GFP_NOIO | __GFP_HIGH) : GFP_NOIO;
/* * Still need barrier for READ in case that whole * array is frozen.
*/ if (!wait_read_barrier(conf, bio->bi_iter.bi_sector,
bio->bi_opf & REQ_NOWAIT)) {
bio_wouldblock_error(bio); return;
}
/* * make_request() can abort the operation when read-ahead is being * used and no empty request is available.
*/
rdisk = read_balance(conf, r1_bio, &max_sectors); if (rdisk < 0) { /* couldn't find anywhere to read from */ if (r1bio_existed)
pr_crit_ratelimited("md/raid1:%s: %pg: unrecoverable I/O read error for block %llu\n",
mdname(mddev),
conf->mirrors[r1_bio->read_disk].rdev->bdev,
r1_bio->sector);
raid_end_bio_io(r1_bio); return;
}
mirror = conf->mirrors + rdisk;
if (r1bio_existed)
pr_info_ratelimited("md/raid1:%s: redirecting sector %llu to other mirror: %pg\n",
mdname(mddev),
(unsignedlonglong)r1_bio->sector,
mirror->rdev->bdev);
if (test_bit(WriteMostly, &mirror->rdev->flags)) { /* * Reading from a write-mostly device must take care not to * over-take any writes that are 'behind'
*/
mddev_add_trace_msg(mddev, "raid1 wait behind writes");
mddev->bitmap_ops->wait_behind_writes(mddev);
}
if (max_sectors < bio_sectors(bio)) { struct bio *split = bio_split(bio, max_sectors,
gfp, &conf->bio_split);
if (IS_ERR(split)) {
error = PTR_ERR(split); goto err_handle;
}
staticbool wait_blocked_rdev(struct mddev *mddev, struct bio *bio)
{ struct r1conf *conf = mddev->private; int disks = conf->raid_disks * 2; int i;
retry: for (i = 0; i < disks; i++) { struct md_rdev *rdev = conf->mirrors[i].rdev;
if (!rdev) continue;
/* don't write here until the bad block is acknowledged */ if (test_bit(WriteErrorSeen, &rdev->flags) &&
rdev_has_badblock(rdev, bio->bi_iter.bi_sector,
bio_sectors(bio)) < 0)
set_bit(BlockedBadBlocks, &rdev->flags);
if (rdev_blocked(rdev)) { if (bio->bi_opf & REQ_NOWAIT) returnfalse;
staticvoid raid1_write_request(struct mddev *mddev, struct bio *bio, int max_write_sectors)
{ struct r1conf *conf = mddev->private; struct r1bio *r1_bio; int i, disks, k, error; unsignedlong flags; int first_clone; int max_sectors; bool write_behind = false; bool is_discard = (bio_op(bio) == REQ_OP_DISCARD);
if (mddev_is_clustered(mddev) &&
mddev->cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector, bio_end_sector(bio))) {
DEFINE_WAIT(w); if (bio->bi_opf & REQ_NOWAIT) {
bio_wouldblock_error(bio); return;
} for (;;) {
prepare_to_wait(&conf->wait_barrier,
&w, TASK_IDLE); if (!mddev->cluster_ops->area_resyncing(mddev, WRITE,
bio->bi_iter.bi_sector,
bio_end_sector(bio))) break;
schedule();
}
finish_wait(&conf->wait_barrier, &w);
}
/* * Register the new request and wait if the reconstruction * thread has put up a bar for new requests. * Continue immediately if no resync is active currently.
*/ if (!wait_barrier(conf, bio->bi_iter.bi_sector,
bio->bi_opf & REQ_NOWAIT)) {
bio_wouldblock_error(bio); return;
}
if (!wait_blocked_rdev(mddev, bio)) {
bio_wouldblock_error(bio); return;
}
/* first select target devices under rcu_lock and * inc refcount on their rdev. Record them by setting * bios[x] to bio * If there are known/acknowledged bad blocks on any device on * which we have seen a write error, we want to avoid writing those * blocks. * This potentially requires several writes to write around * the bad blocks. Each set of writes gets it's own r1bio * with a set of bios attached.
*/
disks = conf->raid_disks * 2;
max_sectors = r1_bio->sectors; for (i = 0; i < disks; i++) { struct md_rdev *rdev = conf->mirrors[i].rdev;
/* * The write-behind io is only attempted on drives marked as * write-mostly, which means we could allocate write behind * bio later.
*/ if (!is_discard && rdev && test_bit(WriteMostly, &rdev->flags))
write_behind = true;
r1_bio->bios[i] = NULL; if (!rdev || test_bit(Faulty, &rdev->flags)) continue;
atomic_inc(&rdev->nr_pending); if (test_bit(WriteErrorSeen, &rdev->flags)) {
sector_t first_bad;
sector_t bad_sectors; int is_bad;
is_bad = is_badblock(rdev, r1_bio->sector, max_sectors,
&first_bad, &bad_sectors); if (is_bad && first_bad <= r1_bio->sector) { /* Cannot write here at all */
bad_sectors -= (r1_bio->sector - first_bad); if (bad_sectors < max_sectors) /* mustn't write more than bad_sectors * to other devices yet
*/
max_sectors = bad_sectors;
rdev_dec_pending(rdev, mddev); continue;
} if (is_bad) { int good_sectors;
/* * We cannot atomically write this, so just * error in that case. It could be possible to * atomically write other mirrors, but the * complexity of supporting that is not worth * the benefit.
*/ if (bio->bi_opf & REQ_ATOMIC) {
error = -EIO; goto err_handle;
}
/* * When using a bitmap, we may call alloc_behind_master_bio below. * alloc_behind_master_bio allocates a copy of the data payload a page * at a time and thus needs a new bio that can fit the whole payload * this bio in page sized chunks.
*/ if (write_behind && mddev->bitmap)
max_sectors = min_t(int, max_sectors,
BIO_MAX_VECS * (PAGE_SIZE >> 9)); if (max_sectors < bio_sectors(bio)) { struct bio *split = bio_split(bio, max_sectors,
GFP_NOIO, &conf->bio_split);
if (IS_ERR(split)) {
error = PTR_ERR(split); goto err_handle;
}
for (i = 0; i < disks; i++) { struct bio *mbio = NULL; struct md_rdev *rdev = conf->mirrors[i].rdev; if (!r1_bio->bios[i]) continue;
if (first_clone) { unsignedlong max_write_behind =
mddev->bitmap_info.max_write_behind; struct md_bitmap_stats stats; int err;
/* do behind I/O ? * Not if there are too many, or cannot * allocate memory, or a reader on WriteMostly
* is waiting for behind writes to flush */
err = mddev->bitmap_ops->get_stats(mddev->bitmap, &stats); if (!err && write_behind && !stats.behind_wait &&
stats.behind_writes < max_write_behind)
alloc_behind_master_bio(r1_bio, bio);
if (test_bit(R1BIO_BehindIO, &r1_bio->state))
mddev->bitmap_ops->start_behind_write(mddev);
first_clone = 0;
}
if (r1_bio->behind_master_bio) {
mbio = bio_alloc_clone(rdev->bdev,
r1_bio->behind_master_bio,
GFP_NOIO, &mddev->bio_set); if (test_bit(CollisionCheck, &rdev->flags))
wait_for_serialization(rdev, r1_bio); if (test_bit(WriteMostly, &rdev->flags))
atomic_inc(&r1_bio->behind_remaining);
} else {
mbio = bio_alloc_clone(rdev->bdev, bio, GFP_NOIO,
&mddev->bio_set);
if (mddev->serialize_policy)
wait_for_serialization(rdev, r1_bio);
}
/* In case raid1d snuck in to freeze_array */
wake_up_barrier(conf); return;
err_handle: for (k = 0; k < i; k++) { if (r1_bio->bios[k]) {
rdev_dec_pending(conf->mirrors[k].rdev, mddev);
r1_bio->bios[k] = NULL;
}
}
staticbool raid1_make_request(struct mddev *mddev, struct bio *bio)
{
sector_t sectors;
if (unlikely(bio->bi_opf & REQ_PREFLUSH)
&& md_flush_request(mddev, bio)) returntrue;
/* * There is a limit to the maximum size, but * the read/write handler might find a lower limit * due to bad blocks. To avoid multiple splits, * we pass the maximum number of sectors down * and let the lower level perform the split.
*/
sectors = align_to_barrier_unit_end(
bio->bi_iter.bi_sector, bio_sectors(bio));
/** * raid1_error() - RAID1 error handler. * @mddev: affected md device. * @rdev: member device to fail. * * The routine acknowledges &rdev failure and determines new @mddev state. * If it failed, then: * - &MD_BROKEN flag is set in &mddev->flags. * - recovery is disabled. * Otherwise, it must be degraded: * - recovery is interrupted. * - &mddev->degraded is bumped. * * @rdev is marked as &Faulty excluding case when array is failed and * &mddev->fail_last_dev is off.
*/ staticvoid raid1_error(struct mddev *mddev, struct md_rdev *rdev)
{ struct r1conf *conf = mddev->private; unsignedlong flags;
staticint raid1_spare_active(struct mddev *mddev)
{ int i; struct r1conf *conf = mddev->private; int count = 0; unsignedlong flags;
/* * Find all failed disks within the RAID1 configuration * and mark them readable. * Called under mddev lock, so rcu protection not needed. * device_lock used to avoid races with raid1_end_read_request * which expects 'In_sync' flags and ->degraded to be consistent.
*/
spin_lock_irqsave(&conf->device_lock, flags); for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = conf->mirrors[i].rdev; struct md_rdev *repl = conf->mirrors[conf->raid_disks + i].rdev; if (repl
&& !test_bit(Candidate, &repl->flags)
&& repl->recovery_offset == MaxSector
&& !test_bit(Faulty, &repl->flags)
&& !test_and_set_bit(In_sync, &repl->flags)) { /* replacement has just become active */ if (!rdev ||
!test_and_clear_bit(In_sync, &rdev->flags))
count++; if (rdev) { /* Replaced device not technically * faulty, but we need to be sure * it gets removed and never re-added
*/
set_bit(Faulty, &rdev->flags);
sysfs_notify_dirent_safe(
rdev->sysfs_state);
}
} if (rdev
&& rdev->recovery_offset == MaxSector
&& !test_bit(Faulty, &rdev->flags)
&& !test_and_set_bit(In_sync, &rdev->flags)) {
count++;
sysfs_notify_dirent_safe(rdev->sysfs_state);
}
}
mddev->degraded -= count;
spin_unlock_irqrestore(&conf->device_lock, flags);
if (!rdev || test_bit(In_sync, &rdev->flags) ||
atomic_read(&rdev->nr_pending)) returnfalse;
/* Only remove non-faulty devices if recovery is not possible. */ if (!test_bit(Faulty, &rdev->flags) &&
rdev->mddev->recovery_disabled != conf->recovery_disabled &&
rdev->mddev->degraded < conf->raid_disks) returnfalse;
if (test_and_clear_bit(Nonrot, &rdev->flags))
WRITE_ONCE(conf->nonrot_disks, conf->nonrot_disks - 1);
WRITE_ONCE(info->rdev, NULL); returntrue;
}
staticint raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
{ struct r1conf *conf = mddev->private; int err = -EEXIST; int mirror = 0, repl_slot = -1; struct raid1_info *p; int first = 0; int last = conf->raid_disks - 1;
if (mddev->recovery_disabled == conf->recovery_disabled) return -EBUSY;
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
/* * find the disk ... but prefer rdev->saved_raid_disk * if possible.
*/ if (rdev->saved_raid_disk >= 0 &&
rdev->saved_raid_disk >= first &&
rdev->saved_raid_disk < conf->raid_disks &&
conf->mirrors[rdev->saved_raid_disk].rdev == NULL)
first = last = rdev->saved_raid_disk;
for (mirror = first; mirror <= last; mirror++) {
p = conf->mirrors + mirror; if (!p->rdev) {
err = mddev_stack_new_rdev(mddev, rdev); if (err) return err;
raid1_add_conf(conf, rdev, mirror, false); /* As all devices are equivalent, we don't need a full recovery * if this was recently any drive of the array
*/ if (rdev->saved_raid_disk < 0)
conf->fullsync = 1; break;
} if (test_bit(WantReplacement, &p->rdev->flags) &&
p[conf->raid_disks].rdev == NULL && repl_slot < 0)
repl_slot = mirror;
}
if (err && repl_slot >= 0) { /* Add this device as a replacement */
clear_bit(In_sync, &rdev->flags);
set_bit(Replacement, &rdev->flags);
raid1_add_conf(conf, rdev, repl_slot, true);
err = 0;
conf->fullsync = 1;
}
print_conf(conf); return err;
}
staticint raid1_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
{ struct r1conf *conf = mddev->private; int err = 0; int number = rdev->raid_disk; struct raid1_info *p = conf->mirrors + number;
if (unlikely(number >= conf->raid_disks)) goto abort;
if (rdev != p->rdev) {
number += conf->raid_disks;
p = conf->mirrors + number;
}
print_conf(conf); if (rdev == p->rdev) { if (!raid1_remove_conf(conf, number)) {
err = -EBUSY; goto abort;
}
if (number < conf->raid_disks &&
conf->mirrors[conf->raid_disks + number].rdev) { /* We just removed a device that is being replaced. * Move down the replacement. We drain all IO before * doing this to avoid confusion.
*/ struct md_rdev *repl =
conf->mirrors[conf->raid_disks + number].rdev;
freeze_array(conf, 0); if (atomic_read(&repl->nr_pending)) { /* It means that some queued IO of retry_list * hold repl. Thus, we cannot set replacement * as NULL, avoiding rdev NULL pointer * dereference in sync_request_write and * handle_write_finished.
*/
err = -EBUSY;
unfreeze_array(conf); goto abort;
}
clear_bit(Replacement, &repl->flags);
WRITE_ONCE(p->rdev, repl);
conf->mirrors[conf->raid_disks + number].rdev = NULL;
unfreeze_array(conf);
}
staticvoid end_sync_read(struct bio *bio)
{ struct r1bio *r1_bio = get_resync_r1bio(bio);
update_head_pos(r1_bio->read_disk, r1_bio);
/* * we have read a block, now it needs to be re-written, * or re-read if the read failed. * We don't do much here, just schedule handling by raid1d
*/ if (!bio->bi_status)
set_bit(R1BIO_Uptodate, &r1_bio->state);
if (atomic_dec_and_test(&r1_bio->remaining))
reschedule_retry(r1_bio);
}
staticvoid abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
{
sector_t sync_blocks = 0;
sector_t s = r1_bio->sector; long sectors_to_go = r1_bio->sectors;
/* make sure these bits don't get cleared. */ do {
mddev->bitmap_ops->end_sync(mddev, s, &sync_blocks);
s += sync_blocks;
sectors_to_go -= sync_blocks;
} while (sectors_to_go > 0);
}
staticvoid put_sync_write_buf(struct r1bio *r1_bio, int uptodate)
{ if (atomic_dec_and_test(&r1_bio->remaining)) { struct mddev *mddev = r1_bio->mddev; int s = r1_bio->sectors;
staticint r1_sync_page_io(struct md_rdev *rdev, sector_t sector, int sectors, struct page *page, blk_opf_t rw)
{ if (sync_page_io(rdev, sector, sectors << 9, page, rw, false)) /* success */ return 1; if (rw == REQ_OP_WRITE) {
set_bit(WriteErrorSeen, &rdev->flags); if (!test_and_set_bit(WantReplacement,
&rdev->flags))
set_bit(MD_RECOVERY_NEEDED, &
rdev->mddev->recovery);
} /* need to record an error - either for the block or the device */ if (!rdev_set_badblocks(rdev, sector, sectors, 0))
md_error(rdev->mddev, rdev); return 0;
}
staticint fix_sync_read_error(struct r1bio *r1_bio)
{ /* Try some synchronous reads of other devices to get * good data, much like with normal read errors. Only * read into the pages we already have so we don't * need to re-issue the read request. * We don't need to freeze the array, because being in an * active sync request, there is no normal IO, and * no overlapping syncs. * We don't need to check is_badblock() again as we * made sure that anything with a bad block in range * will have bi_end_io clear.
*/ struct mddev *mddev = r1_bio->mddev; struct r1conf *conf = mddev->private; struct bio *bio = r1_bio->bios[r1_bio->read_disk]; struct page **pages = get_resync_pages(bio)->pages;
sector_t sect = r1_bio->sector; int sectors = r1_bio->sectors; int idx = 0; struct md_rdev *rdev;
rdev = conf->mirrors[r1_bio->read_disk].rdev; if (test_bit(FailFast, &rdev->flags)) { /* Don't try recovering from here - just fail it
* ... unless it is the last working device of course */
md_error(mddev, rdev); if (test_bit(Faulty, &rdev->flags)) /* Don't try to read from here, but make sure * put_buf does it's thing
*/
bio->bi_end_io = end_sync_write;
}
while(sectors) { int s = sectors; int d = r1_bio->read_disk; int success = 0; int start;
if (s > (PAGE_SIZE>>9))
s = PAGE_SIZE >> 9; do { if (r1_bio->bios[d]->bi_end_io == end_sync_read) { /* No rcu protection needed here devices * can only be removed when no resync is * active, and resync is currently active
*/
rdev = conf->mirrors[d].rdev; if (sync_page_io(rdev, sect, s<<9,
pages[idx],
REQ_OP_READ, false)) {
success = 1; break;
}
}
d++; if (d == conf->raid_disks * 2)
d = 0;
} while (!success && d != r1_bio->read_disk);
if (!success) { int abort = 0; /* Cannot read from anywhere, this block is lost. * Record a bad block on each device. If that doesn't * work just disable and interrupt the recovery. * Don't fail devices as that won't really help.
*/
pr_crit_ratelimited("md/raid1:%s: %pg: unrecoverable I/O read error for block %llu\n",
mdname(mddev), bio->bi_bdev,
(unsignedlonglong)r1_bio->sector); for (d = 0; d < conf->raid_disks * 2; d++) {
rdev = conf->mirrors[d].rdev; if (!rdev || test_bit(Faulty, &rdev->flags)) continue; if (!rdev_set_badblocks(rdev, sect, s, 0))
abort = 1;
} if (abort) return 0;
start = d; /* write it back and re-read */ while (d != r1_bio->read_disk) { if (d == 0)
d = conf->raid_disks * 2;
d--; if (r1_bio->bios[d]->bi_end_io != end_sync_read) continue;
rdev = conf->mirrors[d].rdev; if (r1_sync_page_io(rdev, sect, s,
pages[idx],
REQ_OP_WRITE) == 0) {
r1_bio->bios[d]->bi_end_io = NULL;
rdev_dec_pending(rdev, mddev);
}
}
d = start; while (d != r1_bio->read_disk) { if (d == 0)
d = conf->raid_disks * 2;
d--; if (r1_bio->bios[d]->bi_end_io != end_sync_read) continue;
rdev = conf->mirrors[d].rdev; if (r1_sync_page_io(rdev, sect, s,
pages[idx],
REQ_OP_READ) != 0)
atomic_add(s, &rdev->corrected_errors);
}
sectors -= s;
sect += s;
idx ++;
}
set_bit(R1BIO_Uptodate, &r1_bio->state);
bio->bi_status = 0; return 1;
}
staticvoid process_checks(struct r1bio *r1_bio)
{ /* We have read all readable devices. If we haven't * got the block, then there is no hope left. * If we have, then we want to do a comparison * and skip the write if everything is the same. * If any blocks failed to read, then we need to * attempt an over-write
*/ struct mddev *mddev = r1_bio->mddev; struct r1conf *conf = mddev->private; int primary; int i; int vcnt;
/* Fix variable parts of all bios */
vcnt = (r1_bio->sectors + PAGE_SIZE / 512 - 1) >> (PAGE_SHIFT - 9); for (i = 0; i < conf->raid_disks * 2; i++) {
blk_status_t status; struct bio *b = r1_bio->bios[i]; struct resync_pages *rp = get_resync_pages(b); if (b->bi_end_io != end_sync_read) continue; /* fixup the bio for reuse, but preserve errno */
status = b->bi_status;
bio_reset(b, conf->mirrors[i].rdev->bdev, REQ_OP_READ);
b->bi_status = status;
b->bi_iter.bi_sector = r1_bio->sector +
conf->mirrors[i].rdev->data_offset;
b->bi_end_io = end_sync_read;
rp->raid_bio = r1_bio;
b->bi_private = rp;
/* initialize bvec table again */
md_bio_reset_resync_pages(b, rp, r1_bio->sectors << 9);
} for (primary = 0; primary < conf->raid_disks * 2; primary++) if (r1_bio->bios[primary]->bi_end_io == end_sync_read &&
!r1_bio->bios[primary]->bi_status) {
r1_bio->bios[primary]->bi_end_io = NULL;
rdev_dec_pending(conf->mirrors[primary].rdev, mddev); break;
}
r1_bio->read_disk = primary; for (i = 0; i < conf->raid_disks * 2; i++) { int j = 0; struct bio *pbio = r1_bio->bios[primary]; struct bio *sbio = r1_bio->bios[i];
blk_status_t status = sbio->bi_status; struct page **ppages = get_resync_pages(pbio)->pages; struct page **spages = get_resync_pages(sbio)->pages; struct bio_vec *bi; int page_len[RESYNC_PAGES] = { 0 }; struct bvec_iter_all iter_all;
if (sbio->bi_end_io != end_sync_read) continue; /* Now we can 'fixup' the error value */
sbio->bi_status = 0;
if (!status) { for (j = vcnt; j-- ; ) { if (memcmp(page_address(ppages[j]),
page_address(spages[j]),
page_len[j])) break;
}
} else
j = 0; if (j >= 0)
atomic64_add(r1_bio->sectors, &mddev->resync_mismatches); if (j < 0 || (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)
&& !status)) { /* No need to write to this device. */
sbio->bi_end_io = NULL;
rdev_dec_pending(conf->mirrors[i].rdev, mddev); continue;
}
bio_copy_data(sbio, pbio);
}
}
staticvoid sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
{ struct r1conf *conf = mddev->private; int i; int disks = conf->raid_disks * 2; struct bio *wbio;
if (!test_bit(R1BIO_Uptodate, &r1_bio->state)) { /* * ouch - failed to read all of that. * No need to fix read error for check/repair * because all member disks are read.
*/ if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery) ||
!fix_sync_read_error(r1_bio)) {
conf->recovery_disabled = mddev->recovery_disabled;
set_bit(MD_RECOVERY_INTR, &mddev->recovery);
md_done_sync(mddev, r1_bio->sectors, 0);
put_buf(r1_bio); return;
}
}
if (test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery))
process_checks(r1_bio);
/* * schedule writes
*/
atomic_set(&r1_bio->remaining, 1); for (i = 0; i < disks ; i++) {
wbio = r1_bio->bios[i]; if (wbio->bi_end_io == NULL ||
(wbio->bi_end_io == end_sync_read &&
(i == r1_bio->read_disk ||
!test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
--> --------------------
--> maximum size reached
--> --------------------
Messung V0.5
¤ Dauer der Verarbeitung: 0.22 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.