Implement the calculation of partial parity for a stripe and PPL write logging functionality. The description of PPL is added to the documentation. More details can be found in the comments in raid5-ppl.c. Attach a page for holding the partial parity data to stripe_head. Allocate it only if mddev has the MD_HAS_PPL flag set. Partial parity is the xor of not modified data chunks of a stripe and is calculated as follows: - reconstruct-write case: xor data from all not updated disks in a stripe - read-modify-write case: xor old data and parity from all updated disks in a stripe Implement it using the async_tx API and integrate into raid_run_ops(). It must be called when we still have access to old data, so do it when STRIPE_OP_BIODRAIN is set, but before ops_run_prexor5(). The result is stored into sh->ppl_page. Partial parity is not meaningful for full stripe write and is not stored in the log or used for recovery, so don't attempt to calculate it when stripe has STRIPE_FULL_WRITE. Put the PPL metadata structures to md_p.h because userspace tools (mdadm) will also need to read/write PPL. Warn about using PPL with enabled disk volatile write-back cache for now. It can be removed once disk cache flushing before writing PPL is implemented.
Showing the changes to include/uapi/linux (1 of 7 files). Show all
Unified · Split
| @@ -398,4 +398,31 @@ struct r5l_meta_block { · 397 unmodified lines | ||
| 398 | 398 | |
| 399 | 399 | #define R5LOG_VERSION 0x1 |
| 400 | 400 | #define R5LOG_MAGIC 0x6433c509 |
| 401 | + | |
| 402 | +struct ppl_header_entry { | |
| 403 | + __le64 data_sector; /* raid sector of the new data */ | |
| 404 | + __le32 pp_size; /* length of partial parity */ | |
| 405 | + __le32 data_size; /* length of data */ | |
| 406 | + __le32 parity_disk; /* member disk containing parity */ | |
| 407 | + __le32 checksum; /* checksum of partial parity data for this | |
| 408 | + * entry (~crc32c) */ | |
| 409 | +} __attribute__ ((__packed__)); | |
| 410 | + | |
| 411 | +#define PPL_HEADER_SIZE 4096 | |
| 412 | +#define PPL_HDR_RESERVED 512 | |
| 413 | +#define PPL_HDR_ENTRY_SPACE \ | |
| 414 | + (PPL_HEADER_SIZE - PPL_HDR_RESERVED - 4 * sizeof(u32) - sizeof(u64)) | |
| 415 | +#define PPL_HDR_MAX_ENTRIES \ | |
| 416 | + (PPL_HDR_ENTRY_SPACE / sizeof(struct ppl_header_entry)) | |
| 417 | + | |
| 418 | +struct ppl_header { | |
| 419 | + __u8 reserved[PPL_HDR_RESERVED];/* reserved space, fill with 0xff */ | |
| 420 | + __le32 signature; /* signature (family number of volume) */ | |
| 421 | + __le32 padding; /* zero pad */ | |
| 422 | + __le64 generation; /* generation number of the header */ | |
| 423 | + __le32 entries_count; /* number of entries in entry array */ | |
| 424 | + __le32 checksum; /* checksum of the header (~crc32c) */ | |
| 425 | + struct ppl_header_entry entries[PPL_HDR_MAX_ENTRIES]; | |
| 426 | +} __attribute__ ((__packed__)); | |
| 427 | + | |
| 401 | 428 | #endif |