Improve parity fixing speed

This commit is contained in:
Andrea Mazzoleni 2019-05-19 08:33:08 +02:00
parent 19c75877f1
commit a873eee208
4 changed files with 49 additions and 2 deletions

View file

@ -1,8 +1,10 @@
SnapRAID HISTORY
================
11.4 2018/12
11.4 2019/05
============
* Avoid unnecessary parity read when fixing the parity itself.
This improves the 'fix' speed when a parity file is completely missing.
* Removed a build warning about major/minor defined now in sys/sysmacros.h.
11.3 2018/11

View file

@ -184,6 +184,7 @@ int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_p
handle->level = level;
handle->split_mac = 0;
handle->has_write_access = 0;
for (s = 0; s < parity->split_mac; ++s) {
struct snapraid_split_handle* split = &handle->split_map[s];
@ -217,6 +218,9 @@ int parity_create(struct snapraid_parity_handle* handle, const struct snapraid_p
/* LCOV_EXCL_STOP */
}
/* the initial valid size is the size on disk */
split->valid_size = split->st.st_size;
/**
* If the parity size is not yet set, set it now.
* This happens when expanding the number of parities,
@ -528,6 +532,10 @@ static int parity_handle_chsize(struct snapraid_split_handle* split, data_off_t
/* LCOV_EXCL_STOP */
}
/* if we shrink, update the valid size, but don't update when growing */
if (split->valid_size > split->st.st_size)
split->valid_size = split->st.st_size;
return 0;
}
@ -659,6 +667,7 @@ int parity_open(struct snapraid_parity_handle* handle, const struct snapraid_par
handle->level = level;
handle->split_mac = 0;
handle->has_write_access = 0;
/* mask of bits used by the block size */
block_mask = ((data_off_t)block_size) - 1;
@ -697,6 +706,9 @@ int parity_open(struct snapraid_parity_handle* handle, const struct snapraid_par
/* LCOV_EXCL_STOP */
}
/* the initial valid size is the size on disk */
split->valid_size = split->st.st_size;
/**
* If the parity size is not yet set, set it now.
* This happens when expanding the number of parities,
@ -770,6 +782,19 @@ int parity_close(struct snapraid_parity_handle* handle)
struct snapraid_split_handle* split = &handle->split_map[s];
int ret;
if (handle->has_write_access) {
/* truncate any data that we know it's not valid */
ret = ftruncate(split->f, split->valid_size);
if (ret != 0) {
/* LCOV_EXCL_START */
log_fatal("Error truncating the parity file '%s' to size %" PRIu64 ". %s.\n", split->path, split->valid_size, strerror(errno));
f_ret = -1;
/* LCOV_EXCL_STOP */
/* continue to close the others */
}
}
ret = close(split->f);
if (ret != 0) {
/* LCOV_EXCL_START */
@ -826,6 +851,10 @@ int parity_write(struct snapraid_parity_handle* handle, block_off_t pos, unsigne
/* LCOV_EXCL_STOP */
}
/* update the valid range */
if (split->valid_size < offset + block_size)
split->valid_size = offset + block_size;
write_ret = pwrite(split->f, block_buffer, block_size, offset);
if (write_ret != (ssize_t)block_size) { /* conversion is safe because block_size is always small */
/* LCOV_EXCL_START */
@ -867,6 +896,14 @@ int parity_read(struct snapraid_parity_handle* handle, block_off_t pos, unsigned
/* LCOV_EXCL_STOP */
}
/* if read is completely out of the valid range */
if (offset >= split->valid_size) {
/* LCOV_EXCL_START */
out("Missing data reading file '%s' at offset %" PRIu64 " for size %u.\n", split->path, offset, block_size);
return -1;
/* LCOV_EXCL_STOP */
}
count = 0;
do {
read_ret = pread(split->f, block_buffer + count, block_size - count, offset + count);

View file

@ -36,6 +36,13 @@ struct snapraid_split_handle {
*/
data_off_t size;
/**
* Valid size of the parity split.
* This is the size effectively written, and not the reult of a chsize operation.
* It's used to make read operations failing if read over that size.
*/
data_off_t valid_size;
/**
* Artificial size limit for testing.
* 0 means unlimited.
@ -47,6 +54,7 @@ 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. */
int has_write_access; /**< If the parity is open for writing. */
};
/**

View file

@ -109,7 +109,7 @@ void log_flush(void);
/**
* Pointer to log function.
*/
typedef void fptr(const char* format, ...);
typedef void fptr(const char* format, ...) __attribute__((format(attribute_printf, 1, 2)));
/****************************************************************************/
/* message */