Splits create and truncate operations.

This commit is contained in:
Andrea Mazzoleni 2014-12-28 19:11:58 +01:00
parent 084240dda5
commit b47d78c581
3 changed files with 54 additions and 50 deletions

View file

@ -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);
}
}

View file

@ -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 */

View file

@ -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.