author | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-10-28 00:35:58 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2009-10-28 00:35:58 UTC |
mk-dm-csum.c | +148 | -0 |
diff --git a/mk-dm-csum.c b/mk-dm-csum.c new file mode 100644 index 0000000..182def9 --- /dev/null +++ b/mk-dm-csum.c @@ -0,0 +1,148 @@ + +/* Formats the given file for use by dm-csum */ + +/* Needed to use pwrite() and strtoll() */ +#define _XOPEN_SOURCE 600 + +#include <stdio.h> /* printf() */ +#include <stdlib.h> /* malloc() */ +#include <unistd.h> /* pwrite() and friends */ +#include <sys/types.h> /* open() */ +#include <sys/stat.h> /* open() */ +#include <fcntl.h> /* open() */ +#include <stdint.h> /* uint8_t and friends */ +#include <string.h> /* memset() */ + + +/* simple definitions so we can copy-paste the structs from the kernel */ +#define u8 uint8_t +#define __be16 uint16_t +#define __be32 uint32_t + +/* + * Copied from the kernel definition, MUST match + */ + +#define RESERVED_INITIAL_SECTORS_D 1 +#define RESERVED_INITIAL_SECTORS_M 1 +#define SECTORS_PER_IMD 62 + +struct imd_tuple { + __be16 crc; + __be16 flags; + __be32 tag; +} __attribute__ ((packed)); + +struct imd_sector_header { + u8 last_updated; + u8 unused1; + __be16 crc; + __be32 unused3; +} __attribute__ ((packed)); + + +/* Format function to use when imd and data are on the same device */ +int format_same(int fd, off_t total_size) { + int r; + off_t off; + unsigned char buf[1024]; + struct imd_sector_header *m1, *m2; + + memset(buf, 0, sizeof(buf)); + + m1 = (struct imd_sector_header *) buf; + m2 = (struct imd_sector_header *) (buf + 512); + + m1->last_updated = 2; + m2->last_updated = 1; + + off = RESERVED_INITIAL_SECTORS_D * 512; + + while (off < total_size) { + r = pwrite(fd, buf, 1024, off); + if (r != 1024) + return -1; + off += 1024 + SECTORS_PER_IMD * 512; + } + + return 0; +} + +int format_diff(int data_fd, int imd_fd, off_t total_size) +{ + printf("Not implemented yet\n"); + return 0; +} + +void usage() +{ + printf("Use: mk-dm-csum same <device> [data length]\n"); + printf(" or: mk-dm-csum diff <data device> <imd device> [data length]\n"); + printf("\n"); + printf("Note: data length is in bytes, and will be rounded down to\n"); + printf("an appropriate bound.\n"); +} + +int main(int argc, char **argv) +{ + int fd = -1, imd_fd = -1; + long long total_size; + int same; + + if (argc < 3) { + usage(); + return 1; + } + + if (strcmp(argv[1], "same") == 0) { + same = 1; + } else if (strcmp(argv[1], "diff") == 0) { + /* TODO */ + same = 0; + printf("Error: not implemented yet.\n"); + return 1; + } else { + usage(); + return 1; + } + + fd = open(argv[2], O_WRONLY); + if (fd < 0) { + perror("Error opening device"); + return 1; + } + + if (argc >= 4) { + total_size = strtoll(argv[3], NULL, 0); + } else { + total_size = lseek(fd, 0, SEEK_END); + if (total_size == -1) { + perror("Error finding out the size"); + return 1; + } + } + + /* round down to a multiple of SECTORS_PER_IMD */ + total_size -= total_size % SECTORS_PER_IMD; + printf("Effective total size: %llu\n", total_size); + + if (same) { + if (format_same(fd, total_size) != 0) { + perror("Error formatting"); + return 2; + } + } else { + if (format_diff(fd, imd_fd, total_size) != 0) { + perror("Error formatting"); + return 2; + } + } + + if (fsync(fd) != 0) { + perror("Error syncing data to disk"); + return 3; + } + + return 0; +} +