author | Alberto Bertogli
<albertito@gmail.com> 2004-05-05 18:08:20 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 12:44:27 UTC |
parent | 68e1b10eaa64da6462437f5c1ba2a8700baf77d6 |
doc/libjio.3 | +18 | -7 |
jiofsck.c | +35 | -8 |
libjio.c | +41 | -0 |
libjio.h | +1 | -0 |
diff --git a/doc/libjio.3 b/doc/libjio.3 index 4a8132b..64078a6 100644 --- a/doc/libjio.3 +++ b/doc/libjio.3 @@ -34,6 +34,8 @@ libjio - A library for Journaled I/O .BI "int jfsck(const char *" name ", struct jfsck_result *" res " ); +.BI "int jfsck_cleanup(const char *" name" );" + .SH STRUCTURES .PP .RS @@ -109,13 +111,22 @@ jfs. To close a file, use jclose(). They're exactly like the open() and close() functions but use a struct jfs instead of a file descriptor; take a look at their manpages if you have any doubts about how to use them. -There is one function that differs from the rest, which is jfsck(). It is used -to perform journal checking and recovery in case of a crash. It must be -performed when nobody else is using the file (like in the case of a filesystem -which can't be mounted), and it returns 0 if success or -1 in case of a -failure. If it succeed, a structure jfsck_result that summarizes the outcome -of the operation. There is also a program named jiofsck which is just a simple -human frontend to this function. +There are two functions that differs from the rest, which are jfsck() and +jfsck_cleanup(). + +The first one, jfsck(), is used to perform journal checking and recovery in +case of a crash. It must be performed when nobody else is using the file (like +in the case of a filesystem which can't be mounted), and it returns 0 if +success or -1 in case of a failure. If it succeed, a structure jfsck_result +that summarizes the outcome of the operation. There is also a program named +jiofsck which is just a simple human frontend to this function. + +The second, jfsck_cleanup(), is intended to be used after jfsck() by programs +wanting to remove all the stall transaction files and leave the journal +directory ready to use. After calling jfsck(), the transaction files will no +longer be needed, so by cleaning up the directory you make sure you're +starting over with a clean journal. It returns 0 if there was an error, or 1 +if it succeeded. .SH HIGH LEVEL API diff --git a/jiofsck.c b/jiofsck.c index b48600d..c7df0f0 100644 --- a/jiofsck.c +++ b/jiofsck.c @@ -11,23 +11,36 @@ void usage() { - printf("Use: jiofsck FILE\n\n"); - printf("Where FILE is the name of the file" - "which you want to check the journal from.\n"); + printf("Use: jiofsck [clean] FILE\n\n"); + printf("Where \"FILE\" is the name of the file " + "which you want to check the journal from,\n" + "and the optional parameter \"clean\" makes " + "jiofsck to clean up the journal after\n" + "recovery.\n"); } int main(int argc, char **argv) { - int rv; + int rv, do_cleanup; char *file; struct jfsck_result res; - if (argc != 2) { + if (argc != 2 && argc != 3) { usage(); return 1; } - file = argv[1]; + if (argc == 3) { + if (strcmp("clean", argv[1]) != 0 ) { + usage(); + return 1; + } + file = argv[2]; + do_cleanup = 1; + } else { + file = argv[1]; + do_cleanup = 0; + } memset(&res, 0, sizeof(res)); @@ -45,6 +58,16 @@ int main(int argc, char **argv) printf("done\n"); + if (do_cleanup) { + printf("Cleaning journal: "); + if (!jfsck_cleanup(file)) { + printf("Error cleaning journal\n"); + return 1; + } + + printf("done\n"); + } + printf("Journal checking results\n"); printf("------------------------\n\n"); @@ -58,8 +81,12 @@ int main(int argc, char **argv) printf("Rollbacked:\t %d\n", res.rollbacked); printf("\n"); - printf("You can now safely remove the journal directory completely\n" - "to start a new journal.\n"); + if (!do_cleanup) { + printf("You can now safely remove the journal directory " + "completely\nto start a new journal.\n"); + } else { + printf("The journal has been checked and cleaned up.\n"); + } return 0; } diff --git a/libjio.c b/libjio.c index a530c6c..e6f88fc 100644 --- a/libjio.c +++ b/libjio.c @@ -15,6 +15,7 @@ #include <stdio.h> #include <dirent.h> #include <sys/uio.h> +#include <errno.h> #include "libjio.h" @@ -868,4 +869,44 @@ loop: } +/* remove all the files in the journal directory (if any) */ +int jfsck_cleanup(const char *name) +{ + char jdir[PATH_MAX], tfile[PATH_MAX*3]; + DIR *dir; + struct dirent *dent; + + if (!get_jdir(name, jdir)) + return 0; + + dir = opendir(jdir); + if (dir == NULL && errno == ENOENT) + /* it doesn't exist, so it's clean */ + return 1; + else if (dir == NULL) + return 0; + + for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { + /* we only care about transactions (named as numbers > 0) and + * the lockfile (named "lock"); ignore everything else */ + if (strcmp(dent->d_name, "lock") && atoi(dent->d_name) <= 0) + continue; + + /* build the full path to the transaction file */ + memset(tfile, 0, PATH_MAX * 3); + strcat(tfile, jdir); + strcat(tfile, "/"); + strcat(tfile, dent->d_name); + + /* the full filename is too large */ + if (strlen(tfile) > PATH_MAX) + return 0; + + /* and remove it */ + unlink(tfile); + } + closedir(dir); + + return 1; +} diff --git a/libjio.h b/libjio.h index 012905b..343bc69 100644 --- a/libjio.h +++ b/libjio.h @@ -87,6 +87,7 @@ void jtrans_free(struct jtrans *ts); /* journal checker */ int jfsck(const char *name, struct jfsck_result *res); +int jfsck_cleanup(const char *name); /* jfs constants */