#define DEFAULT_STRIPE_SIZE 4096 struct stripe_head { struct hlist_node hash; struct list_head lru; /* inactive_list or handle_list */ struct llist_node release_list; struct r5conf *raid_conf; short generation; /* increments with every
* reshape */
sector_t sector; /* sector of this row */ short pd_idx; /* parity disk index */ short qd_idx; /* 'Q' disk index for raid6 */ short ddf_layout;/* use DDF ordering to calculate Q */ short hash_lock_index; unsignedlong state; /* state flags */
atomic_t count; /* nr of active thread/requests */ int bm_seq; /* sequence number for bitmap flushes */ int disks; /* disks in stripe */ int overwrite_disks; /* total overwrite disks in stripe, *thisisonlycheckedwhenstripe *hasSTRIPE_BATCH_READY
*/ enum check_states check_state; enum reconstruct_states reconstruct_state;
spinlock_t stripe_lock; int cpu; struct r5worker_group *group;
struct stripe_head *batch_head; /* protected by stripe lock */
spinlock_t batch_lock; /* only header's lock is useful */ struct list_head batch_list; /* protected by head's batch lock*/
union { struct r5l_io_unit *log_io; struct ppl_io_unit *ppl_io;
};
struct list_head log_list;
sector_t log_start; /* first meta block on the journal */ struct list_head r5c; /* for r5c_cache->stripe_in_journal */
struct page *ppl_page; /* partial parity of this stripe */ /** *structstripe_operations *@target-STRIPE_OP_COMPUTE_BLKtarget *@target2-2ndcomputetargetintheraid6case *@zero_sum_result-PandQverificationflags *@request-asyncservicerequestflagsforraid_run_ops
*/ struct stripe_operations { int target, target2; enum sum_check_flags zero_sum_result;
} ops;
#if PAGE_SIZE != DEFAULT_STRIPE_SIZE /* These pages will be used by bios in dev[i] */ struct page **pages; int nr_pages; /* page array size */ int stripes_per_page; #endif struct r5dev { /* rreq and rvec are used for the replacement device when *writingdatatobothdevices.
*/ struct bio req, rreq; struct bio_vec vec, rvec; struct page *page, *orig_page; unsignedint offset; /* offset of the page */ struct bio *toread, *read, *towrite, *written;
sector_t sector; /* sector of this page */ unsignedlong flags;
u32 log_checksum; unsignedshort write_hint;
} dev[]; /* allocated depending of RAID geometry ("disks" member) */
};
/* stripe_head_state - collects and tracks the dynamic state of a stripe_head *forhandle_stripe.
*/ struct stripe_head_state { /* 'syncing' means that we need to read all devices, either *tocheck/correctparity,ortoreconstructamissingdevice. *'replacing'meanswearereplacingoneormoredrivesand *thesourceisvalidatthispointsowedon'tneedto *readalldevices,justthereplacementtargets.
*/ int syncing, expanding, expanded, replacing; int locked, uptodate, to_read, to_write, failed, written; int to_fill, compute, req_compute, non_overwrite; int injournal, just_cached; int failed_num[2]; int p_failed, q_failed; int dec_preread_active; unsignedlong ops_request;
struct md_rdev *blocked_rdev; int handle_bad_blocks; int log_failed; int waiting_extra_page;
};
/* Flags for struct r5dev.flags */ enum r5dev_flags {
R5_UPTODATE, /* page contains current data */
R5_LOCKED, /* IO has been submitted on "req" */
R5_DOUBLE_LOCKED,/* Cannot clear R5_LOCKED until 2 writes complete */
R5_OVERWRITE, /* towrite covers whole page */ /* and some that are internal to handle_stripe */
R5_Insync, /* rdev && rdev->in_sync at start */
R5_Wantread, /* want to schedule a read */
R5_Wantwrite,
R5_Overlap, /* There is a pending overlapping request
* on this block */
R5_ReadNoMerge, /* prevent bio from merging in block-layer */
R5_ReadError, /* seen a read error here recently */
R5_ReWrite, /* have tried to over-write the readerror */
R5_Expanded, /* This block now has post-expand data */
R5_Wantcompute, /* compute_block in progress treat as *uptodate
*/
R5_Wantfill, /* dev->toread contains a bio that needs *filling
*/
R5_Wantdrain, /* dev->towrite needs to be drained */
R5_WantFUA, /* Write should be FUA */
R5_SyncIO, /* The IO is sync */
R5_WriteError, /* got a write error - need to record it */
R5_MadeGood, /* A bad block has been fixed by writing to it */
R5_ReadRepl, /* Will/did read from replacement rather than orig */
R5_MadeGoodRepl,/* A bad block on the replacement device has been
* fixed by writing to it */
R5_NeedReplace, /* This device has a replacement which is not
* up-to-date at this stripe. */
R5_WantReplace, /* We need to update the replacement, we have read *datain,andnowisagoodtimetowriteitout.
*/
R5_Discard, /* Discard the stripe */
R5_SkipCopy, /* Don't copy data from bio to stripe cache */
R5_InJournal, /* data being written is in the journal device. *ifR5_InJournalissetforparitypd_idx,allthe *dataandparitybeingwrittenareinthejournal *device
*/
R5_OrigPageUPTDODATE, /* with write back cache, we read old data into *dev->orig_pageforprexor.Whenthisflagis *set,orig_pagecontainslatestdatainthe *raiddisk.
*/
};
/* *Stripestate
*/ enum {
STRIPE_ACTIVE,
STRIPE_HANDLE,
STRIPE_SYNC_REQUESTED,
STRIPE_SYNCING,
STRIPE_INSYNC,
STRIPE_REPLACED,
STRIPE_PREREAD_ACTIVE,
STRIPE_DELAYED,
STRIPE_BIT_DELAY,
STRIPE_EXPANDING,
STRIPE_EXPAND_SOURCE,
STRIPE_EXPAND_READY,
STRIPE_IO_STARTED, /* do not count towards 'bypass_count' */
STRIPE_FULL_WRITE, /* all blocks are set to be overwritten */
STRIPE_BIOFILL_RUN,
STRIPE_COMPUTE_RUN,
STRIPE_ON_UNPLUG_LIST,
STRIPE_DISCARD,
STRIPE_ON_RELEASE_LIST,
STRIPE_BATCH_READY,
STRIPE_BATCH_ERR,
STRIPE_LOG_TRAPPED, /* trapped into log (see raid5-cache.c) *thisbitisusedintwoscenarios: * *1.write-outphase *setinfirstentryofr5l_write_stripe *clearinsecondentryofr5l_write_stripe *usedtobypasslogicinhandle_stripe * *2.cachingphase *setinr5c_try_caching_write() *clearwhenjournalwriteisdone *usedtoinitiater5c_cache_data() *alsousedtobypasslogicinhandle_stripe
*/
STRIPE_R5C_CACHING, /* the stripe is in caching phase *seemoredetailintheraid5-cache.c
*/
STRIPE_R5C_PARTIAL_STRIPE, /* in r5c cache (to-be/being handled or *inconf->r5c_partial_stripe_list)
*/
STRIPE_R5C_FULL_STRIPE, /* in r5c cache (to-be/being handled or *inconf->r5c_full_stripe_list)
*/
STRIPE_R5C_PREFLUSH, /* need to flush journal device */
};
/* Note: disk_info.rdev can be set to NULL asynchronously by raid5_remove_disk. *Therearethreesafewaystoaccessdisk_info.rdev. *1/whenholdingmddev->reconfig_mutex *2/whenresync/recovery/reshapeisknowntobehappening-i.e.incodethat *iscalledaspartofperformingresync/recovery/reshape. *3/whileholdingrcu_read_lock(),usercu_dereferencetogetthepointer *andifitisnon-NULL,incrementrdev->nr_pendingbeforedroppingtheRCU *lock. *When.rdevissettoNULL,thenr_pendingcountcheckedagainandif *ithasbeenincremented,thepointerisputbackin.rdev.
*/
struct disk_info { struct md_rdev *rdev; struct md_rdev *replacement; struct page *extra_page; /* extra page to use in prexor */
};
enum r5_cache_state {
R5_INACTIVE_BLOCKED, /* release of inactive stripes blocked, *waitingfor25%tobefree
*/
R5_ALLOC_MORE, /* It might help to allocate another *stripe.
*/
R5_DID_ALLOC, /* A stripe was allocated, don't allocate *moreuntilatleastonehasbeen *released.Thisavoidsflooding *thecache.
*/
R5C_LOG_TIGHT, /* log device space tight, need to *prioritizestripesatlast_checkpoint
*/
R5C_LOG_CRITICAL, /* log device is running out of space, *onlyprocessstripesthatarealready *occupyingthelog
*/
R5C_EXTRA_PAGE_IN_USE, /* a stripe is using disk_info.extra_page *forprexor
*/
};
struct raid5_percpu { struct page *spare_page; /* Used when checking P/Q in raid6 */ void *scribble; /* space for constructing buffer *listsandperformingaddress *conversions
*/ int scribble_obj_size;
local_lock_t lock;
};
struct r5conf { struct hlist_head *stripe_hashtbl; /* only protect corresponding hash list and inactive_list */
spinlock_t hash_locks[NR_STRIPE_HASH_LOCKS]; struct mddev *mddev; int chunk_sectors; int level, algorithm, rmw_level; int max_degraded; int raid_disks; int max_nr_stripes; int min_nr_stripes; #if PAGE_SIZE != DEFAULT_STRIPE_SIZE unsignedlong stripe_size; unsignedint stripe_shift; unsignedlong stripe_sectors; #endif
/* reshape_progress is the leading edge of a 'reshape' *IthasvalueMaxSectorwhennoreshapeishappening *Ifdelta_disks<0,itisthelastsectorwestartedworkon, *elseisitthenextsectortoworkon.
*/
sector_t reshape_progress; /* reshape_safe is the trailing edge of a reshape. We know that *before(orafter)thisaddress,allreshapehascompleted.
*/
sector_t reshape_safe; int previous_raid_disks; int prev_chunk_sectors; int prev_algo; short generation; /* increments with every reshape */
seqcount_spinlock_t gen_lock; /* lock against generation changes */ unsignedlong reshape_checkpoint; /* Time we last updated
* metadata */ longlong min_offset_diff; /* minimum difference between *data_offsetand *new_data_offsetacrossall *devices.Maybenegative, *butisclosesttozero.
*/
struct list_head handle_list; /* stripes needing handling */ struct list_head loprio_list; /* low priority stripes */ struct list_head hold_list; /* preread ready stripes */ struct list_head delayed_list; /* stripes that have plugged requests */ struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */ struct bio *retry_read_aligned; /* currently retrying aligned bios */ unsignedint retry_read_offset; /* sector offset into retry_read_aligned */ struct bio *retry_read_aligned_list; /* aligned bios retry list */
atomic_t preread_active_stripes; /* stripes with scheduled io */
atomic_t active_aligned_reads;
atomic_t pending_full_writes; /* full write backlog */ int bypass_count; /* bypassed prereads */ int bypass_threshold; /* preread nice */ int skip_copy; /* Don't copy data from bio to stripe cache */ struct list_head *last_hold; /* detect hold_list promotions */
atomic_t reshape_stripes; /* stripes with pending writes for reshape */ /* unfortunately we need two cache names as we temporarily have *twocaches.
*/ int active_name; char cache_name[2][48]; struct kmem_cache *slab_cache; /* for allocating stripes */ struct mutex cache_size_mutex; /* Protect changes to cache size */
int seq_flush, seq_write; int quiesce;
int fullsync; /* set to 1 if a full sync is needed, *(freshdeviceadded). *Clearedwhenasynccompletes.
*/ int recovery_disabled; /* per cpu variables */ struct raid5_percpu __percpu *percpu; int scribble_disks; int scribble_sectors; struct hlist_node node;
atomic_t empty_inactive_list_nr; struct llist_head released_stripes;
wait_queue_head_t wait_for_quiescent;
wait_queue_head_t wait_for_stripe;
wait_queue_head_t wait_for_reshape; unsignedlong cache_state; struct shrinker *shrinker; int pool_size; /* number of disks in stripeheads in pool */
spinlock_t device_lock; struct disk_info *disks; struct bio_set bio_split;
/* When taking over an array from a different personality, we store *thenewthreadhereuntilwefullyactivatethearray.
*/ struct md_thread __rcu *thread; struct list_head temp_inactive_list[NR_STRIPE_HASH_LOCKS]; struct r5worker_group *worker_groups; int group_cnt; int worker_cnt_per_group; struct r5l_log *log; void *log_private;
/* bio's attached to a stripe+device for I/O are linked together in bi_sector *orderwithoutoverlap.Theremaybeseveralbio'sperstripe+device,and *abiocouldspanseveraldevices. *Whenwalkingthislistforaparticularstripe+device,wemustneverproceed *beyondabiothatextendspastthisdevice,asthenextbiomightnolonger *bevalid. *Thisfunctionisusedtodeterminethe'next'biointhelist,giventhe *sectorofthecurrentstripe+device
*/ staticinlinestruct bio *r5_next_bio(struct r5conf *conf, struct bio *bio, sector_t sector)
{ if (bio_end_sector(bio) < sector + RAID5_STRIPE_SECTORS(conf)) return bio->bi_next; else return NULL;
}
/* *Oursupportedalgorithms
*/ #define ALGORITHM_LEFT_ASYMMETRIC 0/* Rotating Parity N with Data Restart */ #define ALGORITHM_RIGHT_ASYMMETRIC 1/* Rotating Parity 0 with Data Restart */ #define ALGORITHM_LEFT_SYMMETRIC 2/* Rotating Parity N with Data Continuation */ #define ALGORITHM_RIGHT_SYMMETRIC 3/* Rotating Parity 0 with Data Continuation */
/* Define non-rotating (raid4) algorithms. These allow *conversionofraid4toraid5.
*/ #define ALGORITHM_PARITY_0 4/* P or P,Q are initial devices */ #define ALGORITHM_PARITY_N 5/* P or P,Q are final devices. */
/* DDF RAID6 layouts differ from md/raid6 layouts in two ways. *Firstly,theexactpositioningoftheparityblockisslightly *differentbetweenthe'LEFT_*'modesofmdandthe"_N_*"modes *ofDDF. *Secondly,ororderofdatablocksoverwhichtheQsyndromeiscomputed *isdifferent. *ConsequentlywehavedifferentlayoutsforDDF/raid6thanmd/raid6. *TheselayoutsarefromtheDDFv1.2spec. *InterestinglyDDFv1.2-Errata-AdoesnotspecifyN_CONTINUEbut *leavesRLQ=3as'VendorSpecific'
*/
void md_raid5_kick_device(struct r5conf *conf); int raid5_set_cache_size(struct mddev *mddev, int size);
sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous); void raid5_release_stripe(struct stripe_head *sh);
sector_t raid5_compute_sector(struct r5conf *conf, sector_t r_sector, int previous, int *dd_idx, struct stripe_head *sh);
struct stripe_request_ctx; /* get stripe from previous generation (when reshaping) */ #define R5_GAS_PREVIOUS (1 << 0) /* do not block waiting for a free stripe */ #define R5_GAS_NOBLOCK (1 << 1) /* do not block waiting for quiesce to be released */ #define R5_GAS_NOQUIESCE (1 << 2) struct stripe_head *raid5_get_active_stripe(struct r5conf *conf, struct stripe_request_ctx *ctx, sector_t sector, unsignedint flags);
int raid5_calc_degraded(struct r5conf *conf); int r5c_journal_mode_set(struct mddev *mddev, int journal_mode); #endif
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.35 Sekunden
(vorverarbeitet am 2026-09-29)
¤
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.