mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
170 lines
5.9 KiB
C
170 lines
5.9 KiB
C
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
// Copyright (C) 2011 Andrea Mazzoleni
|
|
|
|
#ifndef __PARITY_H
|
|
#define __PARITY_H
|
|
|
|
#include "support.h"
|
|
#include "bw.h"
|
|
#include "state.h"
|
|
#include "io.h"
|
|
|
|
/****************************************************************************/
|
|
/* parity */
|
|
|
|
struct snapraid_split_handle {
|
|
char path[PATH_MAX]; /**< Path of the file. */
|
|
int f; /**< Handle of the files. */
|
|
struct stat st; /**< Stat info of the opened file. */
|
|
struct advise_struct advise; /**< Advise information. */
|
|
|
|
/**
|
|
* Size of the parity split.
|
|
* Only the latest not zero size is allowed to grow.
|
|
* Note that this value CANNOT be PARITY_SIZE_INVALID.
|
|
*/
|
|
data_off_t size;
|
|
|
|
/**
|
|
* High-water mark size of the parity split.
|
|
*
|
|
* This is the physical truncation and read limit of the split.
|
|
*
|
|
* physical_reach_size does NOT indicate that data below this offset is valid parity.
|
|
* Parity may be invalid, stale, unwritten, or sparse at any point below this
|
|
* boundary. Correctness is tracked independently per block in the content state
|
|
* and verified through data hashes and recomputation.
|
|
*
|
|
* Data beyond physical_reach_size is disposable/preallocated and discarded by
|
|
* parity_truncate(). A completed write advances physical_reach_size to the end of
|
|
* the written block so it is not truncated away.
|
|
*
|
|
* Before closing writable parity handles during fix operations, parity_truncate()
|
|
* persists this boundary into the physical EOF. On the next open, physical_reach_size can
|
|
* therefore be initialized from st_size.
|
|
*/
|
|
data_off_t physical_reach_size;
|
|
|
|
/**
|
|
* Artificial size limit for testing.
|
|
* 0 means unlimited.
|
|
*/
|
|
data_off_t limit_size;
|
|
};
|
|
|
|
struct snapraid_parity_handle {
|
|
struct snapraid_split_handle split_map[SPLIT_MAX];
|
|
unsigned split_mac; /**< Number of parity splits. */
|
|
unsigned level; /**< Level of the parity. */
|
|
struct snapraid_bw* bw; /**< Context for bandwidth limiting. */
|
|
};
|
|
|
|
/**
|
|
* Compute the size of the allocated parity data in number of blocks.
|
|
*
|
|
* This includes parity blocks not yet written and still invalid.
|
|
*/
|
|
block_off_t parity_allocated_size(struct snapraid_state* state);
|
|
|
|
/**
|
|
* Compute the size of the used parity data in number of blocks.
|
|
*
|
|
* This includes only parity blocks used for files, not counting
|
|
* potential invalid parity at the end.
|
|
*
|
|
* If the array is fully synced there is no difference between
|
|
* parity_allocate_size() and parity_used_size().
|
|
* But if the sync is interrupted, the parity_used_size() returns
|
|
* the position of the latest BLK block, ignoring CHG, REL and DELETED ones,
|
|
* because their parity may be still not even written in the parity file.
|
|
*/
|
|
block_off_t parity_used_size(struct snapraid_state* state);
|
|
|
|
/**
|
|
* Report all the files outside the specified parity size.
|
|
*/
|
|
void parity_overflow(struct snapraid_state* state, data_off_t size);
|
|
|
|
/**
|
|
* Create the parity file.
|
|
* \param out_size Return the size of the parity file.
|
|
*/
|
|
int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size);
|
|
|
|
/**
|
|
* Change the parity size.
|
|
*
|
|
* If allow_split_realloc is nonzero, an elastic split that cannot reach the
|
|
* requested size may keep the size actually allocated and leave the remaining
|
|
* space to following splits.
|
|
*
|
|
* If allow_split_realloc is zero, a partial allocation must fail instead of
|
|
* moving a logical split boundary. This is required by callers that cannot
|
|
* persist a changed split layout.
|
|
*/
|
|
int parity_chsize(struct snapraid_parity_handle* handle, struct snapraid_parity* parity, int* is_modified, data_off_t size, uint32_t block_size, int skip_fallocate, int skip_space_holder, int allow_split_realloc);
|
|
|
|
/**
|
|
* Get the size of the parity.
|
|
*
|
|
* This returns the cached/expected version of the split sizes, and not the real file size.
|
|
*/
|
|
void parity_size(struct snapraid_parity_handle* handle, data_off_t* out_size);
|
|
|
|
/**
|
|
* Get the physical reach of the logical parity file across splits.
|
|
*
|
|
* This composes the physical_reach_size boundaries of consecutive splits.
|
|
* If the physical_reach_size of an earlier split is smaller than its logical size,
|
|
* later splits cannot extend the logical offset past that missing region.
|
|
*
|
|
* Parity within this range is not necessarily valid or synchronized;
|
|
* per-block validity is tracked independently in the content state.
|
|
*
|
|
* For example, with two 100 GiB splits, if the first has physical_reach_size 90 GiB
|
|
* and the second has physical_reach_size 100 GiB, the result is 90 GiB, not 190 GiB.
|
|
*/
|
|
void parity_physical_reach_size(struct snapraid_parity_handle* handle, data_off_t* out_size);
|
|
|
|
/**
|
|
* Open an already existing parity file.
|
|
*/
|
|
int parity_open(struct snapraid_parity_handle* handle, const struct snapraid_parity* parity, unsigned level, int mode, uint32_t block_size, data_off_t limit_size);
|
|
|
|
/**
|
|
* Flush the parity file in the disk.
|
|
*/
|
|
int parity_sync(struct snapraid_parity_handle* handle);
|
|
|
|
/**
|
|
* Truncate each split to its physical physical_reach_size boundary.
|
|
*/
|
|
int parity_truncate(struct snapraid_parity_handle* handle);
|
|
|
|
/**
|
|
* Close the parity file.
|
|
*/
|
|
int parity_close(struct snapraid_parity_handle* handle);
|
|
|
|
/**
|
|
* Read a block from the parity file.
|
|
*/
|
|
int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size);
|
|
|
|
/**
|
|
* Write a block in the parity file.
|
|
*/
|
|
int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigned char* block_buffer, unsigned block_size);
|
|
|
|
/**
|
|
* 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.
|
|
*/
|
|
int state_barrier(struct snapraid_state* state, struct snapraid_io* io, struct snapraid_parity_handle* parity_handle, block_off_t blockcur);
|
|
|
|
|
|
#endif
|
|
|