mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Splits create and truncate operations.
This commit is contained in:
parent
084240dda5
commit
b47d78c581
3 changed files with 54 additions and 50 deletions
|
|
@ -803,17 +803,6 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* check if the file was larger and now truncated */
|
||||
if (handle[j].truncated != 0) {
|
||||
fprintf(stdlog, "File '%s' is larger than expected.\n", handle[j].path);
|
||||
fprintf(stdlog, "error:%u:%s:%s: Size error\n", i, disk->name, file->sub);
|
||||
++error;
|
||||
|
||||
/* this is already a recovered error */
|
||||
fprintf(stdlog, "fixed:%u:%s:%s: Fixed size\n", i, disk->name, file->sub);
|
||||
++recovered_error;
|
||||
}
|
||||
|
||||
/* check if the file was just created */
|
||||
if (handle[j].created != 0) {
|
||||
/* if fragmented, it may be reopened, so remember that the file */
|
||||
|
|
@ -836,19 +825,35 @@ static int state_check_process(struct snapraid_state* state, int fix, struct sna
|
|||
++error;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* check if it's a larger file, but not if already notified */
|
||||
if (!file_flag_has(file, FILE_IS_LARGER)
|
||||
&& handle[j].st.st_size > file->size
|
||||
) {
|
||||
fprintf(stdlog, "File '%s' is larger than expected.\n", handle[j].path);
|
||||
fprintf(stdlog, "error:%u:%s:%s: Size error\n", i, disk->name, file->sub);
|
||||
++error;
|
||||
/* check if it's a larger file, but not if already notified or excluded */
|
||||
if (!file_flag_has(file, FILE_IS_LARGER)
|
||||
&& !file_flag_has(file, FILE_IS_EXCLUDED)
|
||||
&& handle[j].st.st_size > file->size
|
||||
) {
|
||||
fprintf(stdlog, "File '%s' is larger than expected.\n", handle[j].path);
|
||||
fprintf(stdlog, "error:%u:%s:%s: Size error\n", i, disk->name, file->sub);
|
||||
++error;
|
||||
|
||||
/* if fragmented, it may be reopened, so store the notification */
|
||||
/* to prevent to signal and count the error more than one time */
|
||||
file_flag_set(file, FILE_IS_LARGER);
|
||||
if (fix) {
|
||||
ret = handle_truncate(&handle[j], file);
|
||||
if (ret == -1) {
|
||||
/* LCOV_EXCL_START */
|
||||
fprintf(stderr, "DANGER! Unexpected truncate error in a data disk, it isn't possible to fix.\n");
|
||||
printf("Stopping at block %u\n", i);
|
||||
++unrecoverable_error;
|
||||
goto bail;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
fprintf(stdlog, "fixed:%u:%s:%s: Fixed size\n", i, disk->name, file->sub);
|
||||
++recovered_error;
|
||||
}
|
||||
|
||||
/* if fragmented, it may be reopened, so store the notification */
|
||||
/* to prevent to report and/or truncate it again */
|
||||
file_flag_set(file, FILE_IS_LARGER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
|
|||
}
|
||||
|
||||
/* initial values, changed later if required */
|
||||
handle->truncated = 0;
|
||||
handle->created = 0;
|
||||
|
||||
/* flags for opening */
|
||||
|
|
@ -111,29 +110,6 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
|
|||
/* get the size of the existing data */
|
||||
handle->valid_size = handle->st.st_size;
|
||||
|
||||
/* Here we only truncate the file and we don't grow it */
|
||||
/* as allocating real space for it would imply a too big performance drop, */
|
||||
/* and allocating sparse space wouldn't improve the safety of subsequent writes. */
|
||||
if (handle->st.st_size > file->size) {
|
||||
ret = ftruncate(handle->f, file->size);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
if (errno == EACCES) {
|
||||
fprintf(stderr, "Failed to truncate file '%s' for missing write permission.\n", handle->path);
|
||||
} else {
|
||||
fprintf(stderr, "Error truncating file '%s'. %s.\n", handle->path, strerror(errno));
|
||||
}
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* mark it as truncated */
|
||||
handle->truncated = 1;
|
||||
|
||||
/* adjust the size to the truncated size */
|
||||
handle->valid_size = file->size;
|
||||
}
|
||||
|
||||
#if HAVE_POSIX_FADVISE
|
||||
if ((mode & MODE_SEQUENTIAL) != 0) {
|
||||
/* advise sequential access */
|
||||
|
|
@ -150,6 +126,28 @@ int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, in
|
|||
return 0;
|
||||
}
|
||||
|
||||
int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ftruncate(handle->f, file->size);
|
||||
if (ret != 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
if (errno == EACCES) {
|
||||
fprintf(stderr, "Failed to truncate file '%s' for missing write permission.\n", handle->path);
|
||||
} else {
|
||||
fprintf(stderr, "Error truncating file '%s'. %s.\n", handle->path, strerror(errno));
|
||||
}
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* adjust the size to the truncated size */
|
||||
handle->valid_size = file->size;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int mode, FILE* out)
|
||||
{
|
||||
int ret;
|
||||
|
|
@ -162,8 +160,7 @@ int handle_open(struct snapraid_handle* handle, struct snapraid_file* file, int
|
|||
|
||||
pathprint(handle->path, sizeof(handle->path), "%s%s", handle->disk->dir, file->sub);
|
||||
|
||||
/* for sure neither created and truncated */
|
||||
handle->truncated = 0;
|
||||
/* for sure not created */
|
||||
handle->created = 0;
|
||||
|
||||
/* flags for opening */
|
||||
|
|
|
|||
|
|
@ -31,21 +31,23 @@ struct snapraid_handle {
|
|||
struct stat st; /**< Stat info of the opened file. */
|
||||
data_off_t valid_size; /**< Size of the valid data. */
|
||||
int created; /**< If the file was created, otherwise it was already existing. */
|
||||
int truncated; /**< If the file was truncated. */
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a file.
|
||||
* The file is created if missing, and opened with write access.
|
||||
* If the file has a different size than expected, it's enlarged or truncated to the correct size.
|
||||
* If the file is created, the handle->created is set.
|
||||
* If the file is truncated, the handle->truncated is set.
|
||||
* The initial size of the file is stored in the file->st struct.
|
||||
* If the file cannot be opened for write access, it's opened with read-only access.
|
||||
* The read-only access works only if the file has already the correct size and doesn't need to be modified.
|
||||
*/
|
||||
int handle_create(struct snapraid_handle* handle, struct snapraid_file* file, int mode);
|
||||
|
||||
/**
|
||||
* Truncate a file if required.
|
||||
*/
|
||||
int handle_truncate(struct snapraid_handle* handle, struct snapraid_file* file);
|
||||
|
||||
/**
|
||||
* Opens a file.
|
||||
* The file is opened for reading.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue