mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 10:51:54 -04:00
Adds pid file support.
This commit is contained in:
parent
875081f530
commit
bc2a837953
8 changed files with 149 additions and 14 deletions
3
HISTORY
3
HISTORY
|
|
@ -9,6 +9,9 @@ SnapRAID HISTORY
|
|||
* Added RAID5/RAID6 mmx and sse2 implementations with unrolling by 4.
|
||||
They are a little faster than the previous unroll by 2.
|
||||
* Added a hash seed to make harder intentional collision attacks.
|
||||
* Added a pid file to avoid multiple running instances on the same array.
|
||||
The file is named as the first content file adding the .pid extension.
|
||||
There is also the undocumented --test-skip-pid to avoid to check it.
|
||||
|
||||
3.1 2013/5
|
||||
==========
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ AC_HEADER_STDC
|
|||
AC_HEADER_DIRENT
|
||||
AC_HEADER_TIME
|
||||
AC_CHECK_HEADERS([fcntl.h stddef.h stdint.h stdlib.h string.h limits.h])
|
||||
AC_CHECK_HEADERS([sys/time.h unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h])
|
||||
AC_CHECK_HEADERS([sys/time.h sys/file.h unistd.h getopt.h fnmatch.h io.h inttypes.h byteswap.h])
|
||||
|
||||
dnl Checks for typedefs, structures, and compiler characteristics.
|
||||
AC_C_CONST
|
||||
|
|
@ -49,7 +49,7 @@ AC_SYS_LARGEFILE
|
|||
AC_CHECK_FUNCS([memset strchr strerror strrchr mkdir gettimeofday strtoul])
|
||||
AC_CHECK_FUNCS([getopt getopt_long snprintf vsnprintf])
|
||||
AC_CHECK_FUNCS([ftruncate fallocate fsync access posix_fallocate posix_fadvise pread pwrite getc_unlocked ferror_unlocked fnmatch])
|
||||
AC_CHECK_FUNCS([futimes futimens futimesat fstatat])
|
||||
AC_CHECK_FUNCS([futimes futimens futimesat fstatat flock])
|
||||
|
||||
dnl Checks for architecture
|
||||
AC_C_BIGENDIAN
|
||||
|
|
|
|||
11
portable.h
11
portable.h
|
|
@ -66,6 +66,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if HAVE_SYS_FILE_H
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_DIRENT_H
|
||||
#include <dirent.h>
|
||||
#define NAMLEN(dirent) strlen((dirent)->d_name)
|
||||
|
|
@ -120,6 +124,13 @@
|
|||
#define SWITCH_GETOPT_LONG(a,b) b
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Enable PID file support.
|
||||
*/
|
||||
#if HAVE_FLOCK && HAVE_FTRUNCATE
|
||||
#define HAVE_PIDFILE 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Includes specific support for Windows or Linux.
|
||||
*/
|
||||
|
|
|
|||
60
snapraid.c
60
snapraid.c
|
|
@ -84,7 +84,7 @@ void usage(void)
|
|||
#define OPT_TEST_SKIP_SEQUENTIAL 263
|
||||
#define OPT_TEST_FORCE_MURMUR3 264
|
||||
#define OPT_TEST_FORCE_SPOOKY2 265
|
||||
|
||||
#define OPT_TEST_SKIP_PID 266
|
||||
|
||||
#if HAVE_GETOPT_LONG
|
||||
struct option long_options[] = {
|
||||
|
|
@ -139,6 +139,9 @@ struct option long_options[] = {
|
|||
/* Force Spooky2 hash */
|
||||
{ "test-force-spooky2", 0, 0, OPT_TEST_FORCE_SPOOKY2 },
|
||||
|
||||
/* Skip the use of pid file */
|
||||
{ "test-skip-pid", 0, 0, OPT_TEST_SKIP_PID },
|
||||
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
|
|
@ -185,6 +188,7 @@ int main(int argc, char* argv[])
|
|||
int test_skip_device;
|
||||
int test_force_murmur3;
|
||||
int test_force_spooky2;
|
||||
int test_skip_pid;
|
||||
const char* conf;
|
||||
struct snapraid_state state;
|
||||
int operation;
|
||||
|
|
@ -198,6 +202,7 @@ int main(int argc, char* argv[])
|
|||
const char* command;
|
||||
const char* import;
|
||||
const char* log;
|
||||
int pid;
|
||||
|
||||
os_init();
|
||||
|
||||
|
|
@ -220,6 +225,7 @@ int main(int argc, char* argv[])
|
|||
test_skip_device = 0;
|
||||
test_force_murmur3 = 0;
|
||||
test_force_spooky2 = 0;
|
||||
test_skip_pid = 0;
|
||||
blockstart = 0;
|
||||
blockcount = 0;
|
||||
tommy_list_init(&filterlist_file);
|
||||
|
|
@ -227,6 +233,7 @@ int main(int argc, char* argv[])
|
|||
filter_missing = 0;
|
||||
import = 0;
|
||||
log = 0;
|
||||
pid = 0;
|
||||
|
||||
opterr = 0;
|
||||
while ((c =
|
||||
|
|
@ -347,6 +354,9 @@ int main(int argc, char* argv[])
|
|||
case OPT_TEST_FORCE_SPOOKY2 :
|
||||
test_force_spooky2 = 1;
|
||||
break;
|
||||
case OPT_TEST_SKIP_PID :
|
||||
test_skip_pid = 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option '%c'\n", (char)c);
|
||||
exit(EXIT_FAILURE);
|
||||
|
|
@ -427,6 +437,30 @@ int main(int argc, char* argv[])
|
|||
|
||||
raid_init();
|
||||
|
||||
if (!test_skip_self)
|
||||
selftest(gui);
|
||||
|
||||
state_init(&state);
|
||||
|
||||
/* read the configuration file */
|
||||
state_config(&state, conf, command, verbose, gui, force_zero, force_empty, force_uuid, find_by_name, test_expect_unrecoverable, test_expect_recoverable, test_skip_sign, test_skip_fallocate, test_skip_sequential, test_skip_device, test_force_murmur3, test_force_spooky2);
|
||||
|
||||
#if HAVE_PIDFILE
|
||||
/* create the pid file */
|
||||
if (!test_skip_pid) {
|
||||
pid = pid_lock(state.pidfile);
|
||||
if (pid == -1) {
|
||||
if (errno != EWOULDBLOCK) {
|
||||
fprintf(stderr, "Error creating the pid file '%s'. %s.\n", state.pidfile, strerror(errno));
|
||||
} else {
|
||||
fprintf(stderr, "The pid file '%s' is already locked!\n", state.pidfile);
|
||||
fprintf(stderr, "SnapRAID is already in use!\n");
|
||||
}
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* open the log file */
|
||||
if (log == 0)
|
||||
log = "2";
|
||||
|
|
@ -442,13 +476,6 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (!test_skip_self)
|
||||
selftest(gui);
|
||||
|
||||
state_init(&state);
|
||||
|
||||
state_config(&state, conf, command, verbose, gui, force_zero, force_empty, force_uuid, find_by_name, test_expect_unrecoverable, test_expect_recoverable, test_skip_sign, test_skip_fallocate, test_skip_sequential, test_skip_device, test_force_murmur3, test_force_spooky2);
|
||||
|
||||
if (operation == OPERATION_DIFF) {
|
||||
state_read(&state);
|
||||
|
||||
|
|
@ -545,10 +572,6 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
state_done(&state);
|
||||
tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free);
|
||||
tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free);
|
||||
|
||||
/* close log file */
|
||||
if (stdlog != stdout && stdlog != stderr) {
|
||||
if (fclose(stdlog) != 0) {
|
||||
|
|
@ -557,6 +580,19 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
|
||||
#if HAVE_PIDFILE
|
||||
if (!test_skip_pid) {
|
||||
if (pid_unlock(pid, state.pidfile) == -1) {
|
||||
fprintf(stderr, "Error closing the pid file '%s'. %s.\n", state.pidfile, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
state_done(&state);
|
||||
tommy_list_foreach(&filterlist_file, (tommy_foreach_func*)filter_free);
|
||||
tommy_list_foreach(&filterlist_disk, (tommy_foreach_func*)filter_free);
|
||||
|
||||
os_done();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
|
|
|
|||
7
state.c
7
state.c
|
|
@ -45,6 +45,7 @@ void state_init(struct snapraid_state* state)
|
|||
state->qarity_device = 0;
|
||||
state->pool[0] = 0;
|
||||
state->pool_device = 0;
|
||||
state->pidfile[0] = 0;
|
||||
state->level = 1; /* default is the lowest protection */
|
||||
|
||||
tommy_list_init(&state->disklist);
|
||||
|
|
@ -462,6 +463,12 @@ void state_config(struct snapraid_state* state, const char* path, const char* co
|
|||
content = content_alloc(buffer, st.st_dev);
|
||||
|
||||
tommy_list_insert_tail(&state->contentlist, &content->node, content);
|
||||
|
||||
/* if not set pid file, set it as the first content file */
|
||||
if (!state->pidfile[0]) {
|
||||
pathcpy(state->pidfile, sizeof(state->pidfile), buffer);
|
||||
pathcat(state->pidfile, sizeof(state->pidfile), ".pid");
|
||||
}
|
||||
} else if (strcmp(tag, "disk") == 0) {
|
||||
char dir[PATH_MAX];
|
||||
char device[PATH_MAX];
|
||||
|
|
|
|||
1
state.h
1
state.h
|
|
@ -50,6 +50,7 @@ struct snapraid_state {
|
|||
uint64_t qarity_device; /**< Device identifier of the qarity. */
|
||||
char pool[PATH_MAX]; /**< Path of the pool tree. */
|
||||
uint64_t pool_device; /**< Device identifier of the pool. */
|
||||
char pidfile[PATH_MAX]; /**< Path of the pid file to use. */
|
||||
unsigned char hashseed[HASH_SIZE]; /**< Hash seed. */
|
||||
unsigned level; /**< Number of parity levels. 1 for RAID5, 2 for RAID6. */
|
||||
unsigned hash; /**< Hash kind used. */
|
||||
|
|
|
|||
62
util.c
62
util.c
|
|
@ -866,3 +866,65 @@ void randomize(void* void_ptr, unsigned size)
|
|||
ptr[i] = rand();
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* pid */
|
||||
|
||||
#if HAVE_PIDFILE
|
||||
int pid_lock(const char* file)
|
||||
{
|
||||
char buffer[64];
|
||||
ssize_t len;
|
||||
int f;
|
||||
|
||||
f = open(file, O_CREAT | O_WRONLY, 0600);
|
||||
if (f == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* exclusive lock, not blocking */
|
||||
if (flock(f, LOCK_EX | LOCK_NB) == -1) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* write the pid into the file */
|
||||
snprintf(buffer, sizeof(buffer), "%ld", (long)getpid());
|
||||
|
||||
len = strlen(buffer);
|
||||
if (write(f, buffer, len) != len) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ftruncate(f, len) == -1) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_PIDFILE
|
||||
int pid_unlock(int f, const char* file)
|
||||
{
|
||||
/*
|
||||
* Remove file before closing it.
|
||||
* This opens a race course in case another process already opened it.
|
||||
* but has not yet failed the next flock() call.
|
||||
* But removing it after the close, opens a similar race course.
|
||||
* It seems that deleting a pid file is something just impossible to do it right.
|
||||
*/
|
||||
if (remove(file) == -1) {
|
||||
close(f);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (close(f) == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
15
util.h
15
util.h
|
|
@ -486,5 +486,20 @@ static inline oathash_t oathashm(oathash_t hash, const unsigned char* value, uns
|
|||
return hash;
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* pid */
|
||||
|
||||
/**
|
||||
* Creates and locks the pid file.
|
||||
* Returns -1 on error, otherwise it's the file handle to pass to pid_unlock().
|
||||
*/
|
||||
int pid_lock(const char* file);
|
||||
|
||||
/**
|
||||
* Unlocks the pid file.
|
||||
* Returns -1 on error.
|
||||
*/
|
||||
int pid_unlock(int f, const char* file);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue