mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-25 18:40:19 -04:00
Quiesce scrub read-ahead before autosave and distinguish read/write barriers
This commit is contained in:
parent
fba3f74538
commit
bcfd2734b6
4 changed files with 32 additions and 21 deletions
|
|
@ -136,13 +136,24 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned
|
|||
int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size, int skip_fallocate);
|
||||
|
||||
/**
|
||||
* Complete all pending I/O and sync the parity files.
|
||||
*
|
||||
* This waits for all parity writes, reports their errors, and flushes the
|
||||
* parity data to disk. It also waits for all scheduled read-ahead to complete
|
||||
* without consuming the results, which remain available to the caller.
|
||||
* Wait for all scheduled read-ahead before writing content state.
|
||||
* state_write() bypasses extent locks and may remove obsolete extents, while
|
||||
* reader workers look up extents and update fs_last. They must finish first to
|
||||
* avoid races. Completed results remain queued for later use.
|
||||
*/
|
||||
int state_barrier(struct snapraid_state* state, struct snapraid_io* io, struct snapraid_parity_handle* parity_handle, block_off_t blockcur);
|
||||
void state_read_barrier(struct snapraid_io* io);
|
||||
|
||||
/**
|
||||
* Establish the durability and read-ahead barrier before publishing sync state.
|
||||
* Wait for parity writes and reject writer errors, then sync the parity files.
|
||||
* Content must not record completed BLK/EMPTY states until their parity is
|
||||
* durable. Finally wait for read-ahead so state_write() can access extent trees
|
||||
* without racing reader workers; completed results remain queued for later use.
|
||||
*
|
||||
* If io is 0, only the parity files are synced. Return -1 on a write or sync
|
||||
* failure; the caller must not publish completed state in that case.
|
||||
*/
|
||||
int state_write_barrier(struct snapraid_state* state, struct snapraid_io* io, struct snapraid_parity_handle* parity_handle, block_off_t blockcur);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -976,6 +976,7 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
|
|||
state_progress_stop(state);
|
||||
|
||||
msg_progress("Autosaving...\n");
|
||||
state_read_barrier(&io);
|
||||
state_write(state);
|
||||
|
||||
state_progress_restart(state);
|
||||
|
|
|
|||
|
|
@ -6651,13 +6651,12 @@ void generate_configuration(const char* path)
|
|||
state_done(&state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establish a durable I/O barrier: drain asynchronous writes, collect their
|
||||
* errors, sync parity only if all writes succeeded, then quiesce read-ahead.
|
||||
* A failed writer invalidates the whole barrier because parity must not be
|
||||
* treated as coherent, or recorded in content state, after a failed write.
|
||||
*/
|
||||
int state_barrier(struct snapraid_state* state, struct snapraid_io* io, struct snapraid_parity_handle* parity_handle, block_off_t blockcur)
|
||||
void state_read_barrier(struct snapraid_io* io)
|
||||
{
|
||||
io_quiesce(io);
|
||||
}
|
||||
|
||||
int state_write_barrier(struct snapraid_state* state, struct snapraid_io* io, struct snapraid_parity_handle* parity_handle, block_off_t blockcur)
|
||||
{
|
||||
unsigned l;
|
||||
|
||||
|
|
@ -6689,7 +6688,7 @@ int state_barrier(struct snapraid_state* state, struct snapraid_io* io, struct s
|
|||
|
||||
/* complete all read-ahead without consuming the results */
|
||||
if (io)
|
||||
io_quiesce(io);
|
||||
state_read_barrier(io);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@
|
|||
* 3. Sync reads current data and computes new parity. Blocks may already be
|
||||
* changed to BLK/EMPTY in memory while parity writes are still pending.
|
||||
*
|
||||
* 4. Before an autosave publishes these completed states, state_barrier()
|
||||
* 4. Before an autosave publishes these completed states, state_write_barrier()
|
||||
* drains pending parity writes and synchronizes the parity files.
|
||||
*
|
||||
* 5. Only after that barrier may BLK/EMPTY progress be written to content.
|
||||
|
|
@ -1730,7 +1730,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
state_progress_stop(state);
|
||||
|
||||
/* before spinning down flush all the caches */
|
||||
ret = state_barrier(state, &io, parity_handle, blockcur);
|
||||
ret = state_write_barrier(state, &io, parity_handle, blockcur);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Stopping at block %" PRIu64 "\n", blockcur);
|
||||
|
|
@ -1778,7 +1778,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
|
|||
* Before writing the new content file we ensure that
|
||||
* the parity is really written flushing the disk cache
|
||||
*/
|
||||
ret = state_barrier(state, &io, parity_handle, blockcur);
|
||||
ret = state_write_barrier(state, &io, parity_handle, blockcur);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EIO, "Stopping at block %" PRIu64 "\n", blockcur);
|
||||
|
|
@ -1804,7 +1804,7 @@ end:
|
|||
* Before returning we ensure that
|
||||
* the parity is really written flushing the disk cache
|
||||
*/
|
||||
ret = state_barrier(state, &io, parity_handle, blockcur);
|
||||
ret = state_write_barrier(state, &io, parity_handle, blockcur);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Stopping at block %" PRIu64 "\n", blockcur);
|
||||
|
|
@ -1859,7 +1859,7 @@ bail_durable:
|
|||
* parity generated up to the previous block so the partial progress
|
||||
* and any bad block markings can be made durable in the content file.
|
||||
*/
|
||||
ret = state_barrier(state, &io, parity_handle, blockcur);
|
||||
ret = state_write_barrier(state, &io, parity_handle, blockcur);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(errno, "Stopping at block %" PRIu64 "\n", blockcur);
|
||||
|
|
@ -2259,7 +2259,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
|||
* Ensure any parity files created or resized prior to this branch
|
||||
* are physically committed to disk before declaring sync durable.
|
||||
*/
|
||||
ret = state_barrier(state, 0, parity_handle, blockmax);
|
||||
ret = state_write_barrier(state, 0, parity_handle, blockmax);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
++process_error;
|
||||
|
|
@ -2304,7 +2304,7 @@ int state_sync(struct snapraid_state* state, block_off_t blockstart, block_off_t
|
|||
* Persist progress, error markings, and pending deallocations only after
|
||||
* all parity handles are closed AND sync durability has been confirmed.
|
||||
*
|
||||
* If an asynchronous parity write, state_barrier(), or parity_close() failed,
|
||||
* If an asynchronous parity write, state_write_barrier(), or parity_close() failed,
|
||||
* parity on disk is uncertain or incomplete. In that case, we must not publish
|
||||
* in-memory BLK/EMPTY transitions to the content file, keeping the previous
|
||||
* content file intact for recovery on the next run.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue