author | Alberto Bertogli
<albertito@gmail.com> 2004-07-13 21:16:46 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 13:12:27 UTC |
parent | 8c967b60786a87a2562e2f99911222bcffbccb45 |
Makefile | +1 | -1 |
check.c | +11 | -2 |
checksum.c | +47 | -0 |
common.h | +8 | -0 |
jiofsck.c | +1 | -0 |
libjio.h | +1 | -0 |
trans.c | +10 | -0 |
diff --git a/Makefile b/Makefile index a032e05..31942ad 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ include Make.conf # objects to build -OBJS = common.o trans.o check.o unix.o ansi.o +OBJS = checksum.o common.o trans.o check.o unix.o ansi.o # rules default: all diff --git a/check.c b/check.c index ba7cd4c..a6ff36a 100644 --- a/check.c +++ b/check.c @@ -95,13 +95,14 @@ int jfsck(const char *name, struct jfsck_result *res) { int fd, tfd, rv, i; unsigned int maxtid; + uint32_t csum1, csum2; char jdir[PATH_MAX], jlockfile[PATH_MAX], tname[PATH_MAX]; struct stat sinfo; struct jfs fs; struct jtrans *curts; DIR *dir; struct dirent *dent; - void *map; + unsigned char *map; off_t filelen; @@ -192,12 +193,20 @@ int jfsck(const char *name, struct jfsck_result *res) filelen = lseek(tfd, 0, SEEK_END); map = mmap(0, filelen, PROT_READ, MAP_SHARED, tfd, 0); - rv = fill_trans((unsigned char *) map, filelen, curts); + rv = fill_trans(map, filelen, curts); if (rv != 1) { res->broken++; goto loop; } + /* verify the checksum */ + csum1 = checksum_map(map, filelen - (sizeof(uint32_t))); + csum2 = * (uint32_t *) (map + filelen - (sizeof(uint32_t))); + if (csum1 != csum2) { + res->corrupt++; + goto loop; + } + /* remove flags from the transaction */ curts->flags = 0; diff --git a/checksum.c b/checksum.c new file mode 100644 index 0000000..60e9758 --- /dev/null +++ b/checksum.c @@ -0,0 +1,47 @@ + +/* + * libjio - A library for Journaled I/O + * Alberto Bertogli (albertogli@telpin.com.ar) + * + * Checksum functions + * Based on RFC 1071, "Computing the Internet Checksum" + */ + +#include <stddef.h> +#include <stdint.h> +#include <sys/mman.h> +#include "common.h" + + +int checksum(int fd, size_t len, uint32_t *csum) +{ + uint8_t *map; + + map = (uint8_t *) mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + return 0; + + *csum = checksum_map(map, len); + + munmap(map, len); + return 1; +} + +uint32_t checksum_map(uint8_t *map, size_t count) +{ + uint32_t sum = 0; + + while( count > 1 ) { + sum += * (uint16_t *) map++; + count -= 2; + } + + if( count > 0 ) + sum += * (uint8_t *) map; + + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + return ~sum; +} + diff --git a/common.h b/common.h index 3e8f703..1b7bada 100644 --- a/common.h +++ b/common.h @@ -9,6 +9,10 @@ #ifndef _COMMON_H #define _COMMON_H +#include <sys/types.h> /* for ssize_t and off_t */ +#include <stdint.h> /* for uint*_t */ + + #define _F_READ 0x00001 #define _F_WRITE 0x00010 #define _F_LOCK 0x00100 @@ -21,11 +25,15 @@ #define F_TLOCKW (_F_TLOCK | _F_WRITE) #define F_UNLOCK (_F_ULOCK) + off_t plockf(int fd, int cmd, off_t offset, off_t len); ssize_t spread(int fd, void *buf, size_t count, off_t offset); ssize_t spwrite(int fd, const void *buf, size_t count, off_t offset); int get_jdir(const char *filename, char *jdir); int get_jtfile(const char *filename, int tid, char *jtfile); +int checksum(int fd, size_t len, uint32_t *csum); +uint32_t checksum_map(uint8_t *map, size_t count); + #endif diff --git a/jiofsck.c b/jiofsck.c index f9ac3ea..b7c8ad4 100644 --- a/jiofsck.c +++ b/jiofsck.c @@ -77,6 +77,7 @@ int main(int argc, char **argv) printf("Broken head:\t %d\n", res.broken_head); printf("Broken body:\t %d\n", res.broken_body); printf("Load error:\t %d\n", res.load_error); + printf("Corrupt:\t %d\n", res.corrupt); printf("Apply error:\t %d\n", res.apply_error); printf("Reapplied:\t %d\n", res.reapplied); printf("\n"); diff --git a/libjio.h b/libjio.h index 90ef862..101a42e 100644 --- a/libjio.h +++ b/libjio.h @@ -67,6 +67,7 @@ struct jfsck_result { int invalid; /* invalid files in the journal directory */ int in_progress; /* transactions in progress */ int broken; /* transactions broken */ + int corrupt; /* corrupt transactions */ int apply_error; /* errors applying the transaction */ int reapplied; /* transactions that were reapplied */ }; diff --git a/trans.c b/trans.c index 3a25de2..6bc3904 100644 --- a/trans.c +++ b/trans.c @@ -179,6 +179,7 @@ int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offset) int jtrans_commit(struct jtrans *ts) { int id, rv, fd = -1; + uint32_t csum; char *name; unsigned char *buf_init, *bufp; struct joper *op; @@ -307,6 +308,15 @@ int jtrans_commit(struct jtrans *ts) curpos += op->len; } + /* compute and save the checksum */ + if (!checksum(fd, curpos, &csum)) + goto exit; + + rv = spwrite(fd, &csum, sizeof(uint32_t), curpos); + if (rv != sizeof(uint32_t)) + goto exit; + curpos += sizeof(uint32_t); + /* this is a simple but efficient optimization: instead of doing * everything O_SYNC, we sync at this point only, this way we avoid * doing a lot of very small writes; in case of a crash the