From 34ebae70b5f266ed243c4eebf688381e257d74ab Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Wed, 2 Jul 2008 22:05:59 +0000 Subject: [PATCH] HAMMER Utilities: Mirroring and pseudo-fs directives * Add mirror-read, mirror-write, and mirror-copy. * Replace the pseudofs directive with pfs-status, pfs-create, and pfs-update. Create a pseudofs configuration infrastructure. Configuration parameters can be specified via pfs-create and pfs-update for any HAMMER filesystem or HAMMER pseudo-filesystem. This is basically how you tell HAMMER that a particular pfs is a master or slave, and allows both a unique and a shared uuid to be associated with the pfs. The mirroring code will only mirror to targets with the same shared uuid as the master sourcing the data. --- sbin/hammer/cmd_mirror.c | 238 ++++++++++++++++++++++++++++++++++++++++++--- sbin/hammer/cmd_pseudofs.c | 220 +++++++++++++++++++++++++++++++++++++++-- sbin/hammer/cmd_show.c | 4 +- sbin/hammer/cmd_status.c | 4 +- sbin/hammer/hammer.8 | 80 ++++++++++++++- sbin/hammer/hammer.c | 18 +++- sbin/hammer/hammer.h | 8 +- 7 files changed, 539 insertions(+), 33 deletions(-) diff --git a/sbin/hammer/cmd_mirror.c b/sbin/hammer/cmd_mirror.c index 5c3e5d224a..b0aace7c56 100644 --- a/sbin/hammer/cmd_mirror.c +++ b/sbin/hammer/cmd_mirror.c @@ -31,15 +31,26 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.1 2008/06/26 04:07:57 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.2 2008/07/02 22:05:59 dillon Exp $ */ #include "hammer.h" #define SERIALBUF_SIZE (512 * 1024) +struct hammer_pfs_head { + struct hammer_ioc_mrecord mrec; + u_int32_t version; + struct hammer_pseudofs_data pfsd; +}; + static int read_mrecords(int fd, char *buf, u_int size, hammer_ioc_mrecord_t pickup); +static void generate_mrec_header(int fd, int fdout, + hammer_tid_t *tid_begp, hammer_tid_t *tid_endp); +static void validate_mrec_header(int fd, int fdin, + hammer_tid_t *tid_begp, hammer_tid_t *tid_endp); +static void run_cmd(const char *path, ...); static void mirror_usage(int code); void @@ -49,14 +60,10 @@ hammer_cmd_mirror_read(char **av, int ac) const char *filesystem; char *buf = malloc(SERIALBUF_SIZE); int fd; - hammer_tid_t tid; if (ac > 2) mirror_usage(1); filesystem = av[0]; - tid = 0; - if (ac == 2) - tid = strtoull(av[1], NULL, 0); bzero(&mirror, sizeof(mirror)); hammer_key_beg_init(&mirror.key_beg); @@ -68,10 +75,12 @@ hammer_cmd_mirror_read(char **av, int ac) hammer_get_cycle(&mirror.key_beg); + generate_mrec_header(fd, 1, &mirror.tid_beg, &mirror.tid_end); + mirror.ubuf = buf; mirror.size = SERIALBUF_SIZE; - mirror.tid_beg = tid; - mirror.tid_end = HAMMER_MAX_TID; + if (ac == 2) + mirror.tid_beg = strtoull(av[1], NULL, 0); do { mirror.count = 0; @@ -96,6 +105,8 @@ hammer_cmd_mirror_read(char **av, int ac) write(1, mirror.ubuf, mirror.count); } while (mirror.count != 0); + /* generate_mrec_update(fd, 1); */ + if (CyclePath) hammer_reset_cycle(); fprintf(stderr, "Mirror-read %s succeeded\n", filesystem); @@ -109,14 +120,10 @@ hammer_cmd_mirror_write(char **av, int ac) char *buf = malloc(SERIALBUF_SIZE); int fd; struct hammer_ioc_mrecord pickup; - hammer_tid_t tid; if (ac > 2) mirror_usage(1); filesystem = av[0]; - tid = 0; - if (ac == 2) - tid = strtoull(av[1], NULL, 0); bzero(&mirror, sizeof(mirror)); hammer_key_beg_init(&mirror.key_beg); @@ -126,10 +133,10 @@ hammer_cmd_mirror_write(char **av, int ac) if (fd < 0) err(1, "Unable to open %s", filesystem); + validate_mrec_header(fd, 0, &mirror.tid_beg, &mirror.tid_end); + mirror.ubuf = buf; mirror.size = SERIALBUF_SIZE; - mirror.tid_beg = tid; - mirror.tid_end = HAMMER_MAX_TID; pickup.signature = 0; @@ -160,6 +167,61 @@ hammer_cmd_mirror_write(char **av, int ac) void hammer_cmd_mirror_copy(char **av, int ac) { + pid_t pid1; + pid_t pid2; + int fds[2]; + char *ptr; + + if (ac != 2) + mirror_usage(1); + + if (pipe(fds) < 0) { + perror("pipe"); + exit(1); + } + + /* + * Source + */ + if ((pid1 = fork()) == 0) { + dup2(fds[0], 0); + dup2(fds[0], 1); + close(fds[0]); + close(fds[1]); + if ((ptr = strchr(av[0], ':')) != NULL) { + *ptr++ = 0; + run_cmd("/usr/bin/ssh", "ssh", + av[0], "hammer mirror-read", ptr, NULL); + _exit(1); + } else { + hammer_cmd_mirror_read(av, 1); + } + } + + /* + * Target + */ + if ((pid2 = fork()) == 0) { + dup2(fds[1], 0); + dup2(fds[1], 1); + close(fds[0]); + close(fds[1]); + if ((ptr = strchr(av[1], ':')) != NULL) { + *ptr++ = 0; + run_cmd("/usr/bin/ssh", "ssh", + av[1], "hammer mirror-write", ptr, NULL); + _exit(1); + } else { + hammer_cmd_mirror_write(av + 1, 1); + } + } + close(fds[0]); + close(fds[1]); + + while (waitpid(pid1, NULL, 0) <= 0) + ; + while (waitpid(pid2, NULL, 0) <= 0) + ; } static int @@ -240,6 +302,156 @@ read_mrecords(int fd, char *buf, u_int size, hammer_ioc_mrecord_t pickup) return(count); } +/* + * Generate a mirroring header with the pfs information of the + * originating filesytem. + */ +static void +generate_mrec_header(int fd, int fdout, + hammer_tid_t *tid_begp, hammer_tid_t *tid_endp) +{ + struct hammer_ioc_pseudofs_rw pfs; + struct hammer_pfs_head pfs_head; + + bzero(&pfs, sizeof(pfs)); + bzero(&pfs_head, sizeof(pfs_head)); + pfs.ondisk = &pfs_head.pfsd; + pfs.bytes = sizeof(pfs_head.pfsd); + if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) != 0) { + fprintf(stderr, "mirror-read: not a HAMMER fs/pseudofs!\n"); + exit(1); + } + if (pfs.version != HAMMER_IOC_PSEUDOFS_VERSION) { + fprintf(stderr, "mirror-read: HAMMER pfs version mismatch!\n"); + exit(1); + } + + /* + * sync_beg_tid - lowest TID on source after which a full history + * is available. + * + * sync_end_tid - highest fully synchronized TID from source. + */ + *tid_begp = pfs_head.pfsd.sync_beg_tid; + *tid_endp = pfs_head.pfsd.sync_end_tid; + + pfs_head.version = pfs.version; + pfs_head.mrec.signature = HAMMER_IOC_MIRROR_SIGNATURE; + pfs_head.mrec.rec_size = sizeof(pfs_head); + pfs_head.mrec.type = HAMMER_MREC_TYPE_PFSD; + pfs_head.mrec.rec_crc = crc32((char *)&pfs_head + HAMMER_MREC_CRCOFF, + sizeof(pfs_head) - HAMMER_MREC_CRCOFF); + write(fdout, &pfs_head, sizeof(pfs_head)); +} + +/* + * Validate the pfs information from the originating filesystem + * against the target filesystem. shared_uuid must match. + */ +static void +validate_mrec_header(int fd, int fdin, + hammer_tid_t *tid_begp, hammer_tid_t *tid_endp) +{ + struct hammer_ioc_pseudofs_rw pfs; + struct hammer_pfs_head pfs_head; + struct hammer_pseudofs_data pfsd; + size_t bytes; + size_t n; + size_t i; + + /* + * Get the PFSD info from the target filesystem. + */ + bzero(&pfs, sizeof(pfs)); + bzero(&pfsd, sizeof(pfsd)); + pfs.ondisk = &pfsd; + pfs.bytes = sizeof(pfsd); + if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) != 0) { + fprintf(stderr, "mirror-write: not a HAMMER fs/pseudofs!\n"); + exit(1); + } + if (pfs.version != HAMMER_IOC_PSEUDOFS_VERSION) { + fprintf(stderr, "mirror-write: HAMMER pfs version mismatch!\n"); + exit(1); + } + + /* + * Read in the PFSD header from the sender. + */ + for (n = 0; n < HAMMER_MREC_HEADSIZE; n += i) { + i = read(fdin, (char *)&pfs_head + n, HAMMER_MREC_HEADSIZE - n); + if (i <= 0) + break; + } + if (n != HAMMER_MREC_HEADSIZE) { + fprintf(stderr, "mirror-write: short read of PFS header\n"); + exit(1); + } + if (pfs_head.mrec.signature != HAMMER_IOC_MIRROR_SIGNATURE) { + fprintf(stderr, "mirror-write: PFS header has bad signature\n"); + exit(1); + } + if (pfs_head.mrec.type != HAMMER_MREC_TYPE_PFSD) { + fprintf(stderr, "mirror-write: Expected PFS header, got mirroring record header instead!\n"); + exit(1); + } + bytes = pfs_head.mrec.rec_size; + if (bytes < HAMMER_MREC_HEADSIZE) + bytes = (int)HAMMER_MREC_HEADSIZE; + if (bytes > sizeof(pfs_head)) + bytes = sizeof(pfs_head); + while (n < bytes) { + i = read(fdin, (char *)&pfs_head + n, bytes - n); + if (i <= 0) + break; + n += i; + } + if (n != bytes) { + fprintf(stderr, "mirror-write: short read of PFS payload\n"); + exit(1); + } + if (pfs_head.version != pfs.version) { + fprintf(stderr, "mirror-write: Version mismatch in PFS header\n"); + exit(1); + } + if (pfs_head.mrec.rec_size != sizeof(pfs_head)) { + fprintf(stderr, "mirror-write: The PFS header has the wrong size!\n"); + exit(1); + } + + /* + * Whew. Ok, is the read PFS info compatible with the target? + */ + if (bcmp(&pfs_head.pfsd.shared_uuid, &pfsd.shared_uuid, sizeof(pfsd.shared_uuid)) != 0) { + fprintf(stderr, "mirror-write: source and target have different shared_uuid's!\n"); + exit(1); + } + if ((pfsd.mirror_flags & HAMMER_PFSD_SLAVE) == 0) { + fprintf(stderr, "mirror-write: target must be in slave mode\n"); + exit(1); + } + *tid_begp = pfs_head.pfsd.sync_beg_tid; + *tid_endp = pfs_head.pfsd.sync_end_tid; +} + +static void +run_cmd(const char *path, ...) +{ + va_list va; + char *av[16]; + int n; + + va_start(va, path); + for (n = 0; n < 16; ++n) { + av[n] = va_arg(va, char *); + if (av[n] == NULL) + break; + } + va_end(va); + assert(n != 16); + execv(path, av); +} + static void mirror_usage(int code) { diff --git a/sbin/hammer/cmd_pseudofs.c b/sbin/hammer/cmd_pseudofs.c index c1a3f1ed58..01b0dbec11 100644 --- a/sbin/hammer/cmd_pseudofs.c +++ b/sbin/hammer/cmd_pseudofs.c @@ -31,30 +31,232 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_pseudofs.c,v 1.2 2008/06/26 04:07:57 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_pseudofs.c,v 1.3 2008/07/02 22:05:59 dillon Exp $ */ #include "hammer.h" +static void parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd); +static void init_pfsd(hammer_pseudofs_data_t pfsd); +static void dump_pfsd(hammer_pseudofs_data_t pfsd); +static void pseudofs_usage(int code); + void -hammer_cmd_pseudofs(char **av, int ac) +hammer_cmd_pseudofs_status(char **av, int ac) { - struct hammer_ioc_get_pseudofs pfs; + struct hammer_ioc_pseudofs_rw pfs; + struct hammer_pseudofs_data pfsd; int i; int fd; for (i = 0; i < ac; ++i) { - if (mknod(av[i], S_IFDIR|0777, 0) < 0) { - perror("mknod (create pseudofs):"); - exit(1); - } + bzero(&pfsd, sizeof(pfsd)); + bzero(&pfs, sizeof(pfs)); + pfs.ondisk = &pfsd; + pfs.bytes = sizeof(pfsd); printf("%s\t", av[i]); fd = open(av[i], O_RDONLY); if (fd < 0 || ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) < 0) { - printf("Unable to verify pseudofs creation\n"); + printf("Not a HAMMER root\n"); + } else { + printf("Pseudo-fs #0x%08x {\n", pfs.pseudoid); + dump_pfsd(&pfsd); + printf("}\n"); + } + } +} + +void +hammer_cmd_pseudofs_create(char **av, int ac) +{ + if (ac == 0) + pseudofs_usage(1); + + if (mknod(av[0], S_IFDIR|0777, 0) < 0) { + perror("mknod (create pseudofs):"); + exit(1); + } + hammer_cmd_pseudofs_update(av, ac, 1); +} + +void +hammer_cmd_pseudofs_update(char **av, int ac, int doinit) +{ + struct hammer_ioc_pseudofs_rw pfs; + struct hammer_pseudofs_data pfsd; + int fd; + + if (ac == 0) + pseudofs_usage(1); + bzero(&pfs, sizeof(pfs)); + bzero(&pfsd, sizeof(pfsd)); + pfs.ondisk = &pfsd; + pfs.bytes = sizeof(pfsd); + pfs.version = HAMMER_IOC_PSEUDOFS_VERSION; + + printf("%s\t", av[0]); + fflush(stdout); + fd = open(av[0], O_RDONLY); + + if (fd >= 0 && ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) { + if (doinit) { + printf("Pseudo-fs #0x%08x created\n", pfs.pseudoid); + init_pfsd(&pfsd); } else { - printf("Pseudo-fs #0x%08x\n", pfs.pseudoid); + printf("\n"); } + parse_pfsd_options(av + 1, ac - 1, &pfsd); + pfs.bytes = sizeof(pfsd); + if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) == 0) { + if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) { + dump_pfsd(&pfsd); + } else { + printf("Unable to retrieve pfs configuration after successful update: %s\n", strerror(errno)); + exit(1); + } + } else { + printf("Unable to adjust pfs configuration: %s\n", strerror(errno)); + exit(1); + } + } else { + printf("PFS Creation failed: %s\n", strerror(errno)); + exit(1); } } +static void +init_pfsd(hammer_pseudofs_data_t pfsd) +{ + uint32_t status; + + pfsd->sync_beg_tid = 1; + pfsd->sync_end_tid = 1; + pfsd->sync_beg_ts = 0; + pfsd->sync_end_ts = 0; + uuid_create(&pfsd->shared_uuid, &status); + uuid_create(&pfsd->unique_uuid, &status); + pfsd->master_id = 0; +} + +static +void +dump_pfsd(hammer_pseudofs_data_t pfsd) +{ + u_int32_t status; + char *str = NULL; + + printf(" sync-beg-tid=0x%016llx\n", pfsd->sync_beg_tid); + printf(" sync-end-tid=0x%016llx\n", pfsd->sync_end_tid); + uuid_to_string(&pfsd->shared_uuid, &str, &status); + printf(" shared-uuid=%s\n", str); + uuid_to_string(&pfsd->unique_uuid, &str, &status); + printf(" unique-uuid=%s\n", str); + if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) { + printf(" slave\n"); + } else if (pfsd->master_id < 0) { + printf(" no-mirror\n"); + } else { + printf(" master=%d\n", pfsd->master_id); + } + printf(" label=\"%s\"\n", pfsd->label); +} + +static void +parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd) +{ + char *cmd; + char *ptr; + int len; + uint32_t status; + + while (ac) { + cmd = *av; + if ((ptr = strchr(cmd, '=')) != NULL) + *ptr++ = 0; + + /* + * Basic assignment value test + */ + if (strcmp(cmd, "no-mirror") == 0 || + strcmp(cmd, "slave") == 0) { + if (ptr) { + fprintf(stderr, + "option %s should not have " + "an assignment\n", + cmd); + exit(1); + } + } else { + if (ptr == NULL) { + fprintf(stderr, + "option %s requires an assignment\n", + cmd); + exit(1); + } + } + + status = uuid_s_ok; + if (strcmp(cmd, "sync-beg-tid") == 0) { + pfsd->sync_beg_tid = strtoull(ptr, NULL, 16); + } else if (strcmp(cmd, "sync-end-tid") == 0) { + pfsd->sync_end_tid = strtoull(ptr, NULL, 16); + } else if (strcmp(cmd, "shared-uuid") == 0) { + uuid_from_string(ptr, &pfsd->shared_uuid, &status); + } else if (strcmp(cmd, "unique-uuid") == 0) { + uuid_from_string(ptr, &pfsd->unique_uuid, &status); + } else if (strcmp(cmd, "master") == 0) { + pfsd->master_id = strtol(ptr, NULL, 0); + pfsd->mirror_flags &= ~HAMMER_PFSD_SLAVE; + } else if (strcmp(cmd, "slave") == 0) { + pfsd->master_id = -1; + pfsd->mirror_flags |= HAMMER_PFSD_SLAVE; + } else if (strcmp(cmd, "no-mirror") == 0) { + pfsd->master_id = -1; + pfsd->mirror_flags &= ~HAMMER_PFSD_SLAVE; + } else if (strcmp(cmd, "label") == 0) { + len = strlen(ptr); + if (ptr[0] == '"' && ptr[len-1] == '"') { + ptr[len-1] = 0; + ++ptr; + } else if (ptr[0] == '"') { + fprintf(stderr, + "option %s: malformed string\n", + cmd); + exit(1); + } + snprintf(pfsd->label, sizeof(pfsd->label), "%s", ptr); + } else { + fprintf(stderr, "invalid option: %s\n", cmd); + exit(1); + } + if (status != uuid_s_ok) { + fprintf(stderr, "option %s: error parsing uuid %s\n", + cmd, ptr); + exit(1); + } + --ac; + ++av; + } +} + +static +void +pseudofs_usage(int code) +{ + fprintf(stderr, + "hammer pfs-status ...\n" + "hammer pfs-create [options]\n" + "hammer pfs-update [options]\n" + "\n" + " sync-beg-tid=0x16llx\n" + " sync-end-tid=0x16llx\n" + " shared-uuid=0x16llx\n" + " unique-uuid=0x16llx\n" + " master=0-15\n" + " slave\n" + " no-mirror\n" + " label=\"string\"\n" + ); + exit(code); +} + diff --git a/sbin/hammer/cmd_show.c b/sbin/hammer/cmd_show.c index ecd6ea4585..7c44e717b4 100644 --- a/sbin/hammer/cmd_show.c +++ b/sbin/hammer/cmd_show.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_show.c,v 1.13 2008/06/26 04:07:57 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_show.c,v 1.14 2008/07/02 22:05:59 dillon Exp $ */ #include "hammer.h" @@ -177,6 +177,8 @@ print_btree_elm(hammer_btree_elm_t elm, int i, u_int8_t type, switch(type) { case HAMMER_BTREE_TYPE_INTERNAL: printf("suboff=%016llx", elm->internal.subtree_offset); + if (VerboseOpt) + printf(" mirror %016llx", elm->internal.mirror_tid); break; case HAMMER_BTREE_TYPE_LEAF: switch(elm->base.btype) { diff --git a/sbin/hammer/cmd_status.c b/sbin/hammer/cmd_status.c index 40787a586f..c09c5e7033 100644 --- a/sbin/hammer/cmd_status.c +++ b/sbin/hammer/cmd_status.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/cmd_status.c,v 1.1 2008/06/26 04:07:57 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_status.c,v 1.2 2008/07/02 22:05:59 dillon Exp $ */ #include "hammer.h" @@ -39,7 +39,7 @@ void hammer_cmd_status(char **av, int ac) { - struct hammer_ioc_get_pseudofs pfs; + struct hammer_ioc_pseudofs_rw pfs; int i; int fd; diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 3a7310e95e..e42c44594f 100644 --- a/sbin/hammer/hammer.8 +++ b/sbin/hammer/hammer.8 @@ -30,7 +30,7 @@ .\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.29 2008/06/28 14:51:50 swildner Exp $ +.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.30 2008/07/02 22:05:59 dillon Exp $ .Dd June 26, 2008 .Dt HAMMER 8 .Os @@ -235,10 +235,86 @@ It is recommended that separate invocations be used for each data type. Btree nodes, inodes, and directories are typically the most important elements needing defragmentation. Data can be defragmented over a longer period of time. -.It Ar pseudofs Ar dirpath +.It Ar pfs-status Ar dirpath +Retrieve the mirroring configuration parameters for the specified +HAMMER filesystem or pseudo-filesystem. +.It Ar pfs-create Ar dirpath Op options Create a pseudo-filesystem inside a HAMMER filesystem. Up to 65535 such filesystems can be created. Each one uses an independant inode numbering space making it suitable for use as a replication source or target. +.Pp +Note that rm -rf'ing a pseudo-fs will not allow the pseudo-id to be reused +until all historical data has been pruned out and the pseudo-fs is truely +empty. +.It Ar pfs-update Ar dirpath Op options +Update the configuration parameters for an existing HAMMER filesystem +or pseudo-filesystem. Options that may be specified: +.Pp +.Bl -tag -width indent +.It sync-beg-tid=0x16llx +This is the automatic snapshot access TID for mirroring slaves. +This parameter is normally updated automatically by the +.Ar mirror-write +directive. +.Pp +It is important to note that accessing a mirroring slave +with a transaction id greater then the last fully synchronized transaction +id can result in an unreliable snapshot since you will be accessing +data that is still undergoing synchronization. +.Pp +Manually modifying this field is dangerous and can result in a broken +mirror. +.It sync-end-tid=0x16llx +This is the current synchronization target for mirroring slaves. +This parameter is normally updated automatically by the +.Ar mirror-write +directive. +.Pp +Manually modifying this field is dangerous and can result in a broken +mirror. +.It shared-uuid= +Set the shared uuid for this filesystem. All mirrors must have the same +shared uuid. For safety purposes the mirror-write directives will refuse +to operate on a target with a different shared uuid. +.Pp +Changing the shared uuid on an existing, non-empty mirroring target, +including an empty but not completely pruned target, can lead +to corruption of the mirroring target. +.It unique-uuid= +Set the unique uuid for this filesystem. This uuid should not be used +anywhere else, even on exact copies of the filesystem. +.It master= +Set the master id for multi-master mirroring. Only values between 0 and 15 +inclusive may be specified. All masters sharing the same +.Ar shared-uuid +must have different ids. +Up to 16 masters will eventually be supported. +Multi-master mirroring is not supported yet and the master id should be +set to 0 on the single master when mirroring to one or more slaves. +.It no-mirror +This disables the ability to use this filesystem as a mirroring source +or target. You can still do full scans with mirror-read but incremental +scans will not work. +.It slave +Sets slave mode, allowing the mirror to be used as a slave. Except for +the mirror-write directive all accesses to the mirror will be made read-only +and will be as-of the +.Ar sync_beg_tid . +.It label= +Set a descriptive label for this filesystem. +.El +.It Ar mirror-read Ar filesystem Op Ar +Generate a mirroring stream to stdout. +.It Ar mirror-write Ar filesystem Op Ar +Take a mirroring stream on stdin and output it to stdout. +.Pp +This command will fail if the +.Ar shared_uuid +configuration field for the two filesystems do not match. +.It Ar mirror-copy Ar [[user@]host:]filesystem Ar [[user@]host:]filesystem +This is a shortcut which pipes a mirror-read command to a mirror-write +command. If a remote host specification is made the program forks an +ssh and execs the mirror-read and/or mirror-write on the appropriate host. .El .\".Sh EXAMPLES .Sh DIAGNOSTICS diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index 32f9e5d6b4..7662010328 100644 --- a/sbin/hammer/hammer.c +++ b/sbin/hammer/hammer.c @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/hammer.c,v 1.28 2008/06/26 15:12:21 mneumann Exp $ + * $DragonFly: src/sbin/hammer/hammer.c,v 1.29 2008/07/02 22:05:59 dillon Exp $ */ #include "hammer.h" @@ -125,8 +125,16 @@ main(int ac, char **av) printf("0x%08x\n", key); exit(0); } - if (strcmp(av[0], "pseudofs") == 0) { - hammer_cmd_pseudofs(av + 1, ac - 1); + if (strcmp(av[0], "pfs-status") == 0) { + hammer_cmd_pseudofs_status(av + 1, ac - 1); + exit(0); + } + if (strcmp(av[0], "pfs-create") == 0) { + hammer_cmd_pseudofs_create(av + 1, ac - 1); + exit(0); + } + if (strcmp(av[0], "pfs-update") == 0) { + hammer_cmd_pseudofs_update(av + 1, ac - 1, 0); exit(0); } if (strcmp(av[0], "status") == 0) { @@ -255,7 +263,9 @@ usage(int exit_code) " [[user@]host:]\n" "hammer reblock[-btree/inodes/dirs/data] " " [pack%%]\n" - "hammer pseudofs \n" + "hammer pfs-status \n" + "hammer pfs-create [options]\n" + "hammer pfs-update [options]\n" "hammer history[@offset[,len]] ...\n" "hammer -f blkdevs [-r] show\n" "hammer -f blkdevs blockmap\n" diff --git a/sbin/hammer/hammer.h b/sbin/hammer/hammer.h index 7a69bd5c77..68e53121ea 100644 --- a/sbin/hammer/hammer.h +++ b/sbin/hammer/hammer.h @@ -31,7 +31,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $DragonFly: src/sbin/hammer/hammer.h,v 1.19 2008/06/26 04:07:57 dillon Exp $ + * $DragonFly: src/sbin/hammer/hammer.h,v 1.20 2008/07/02 22:05:59 dillon Exp $ */ #include @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -53,6 +54,7 @@ #include #include #include +#include #include "hammer_util.h" #include @@ -75,7 +77,9 @@ void hammer_cmd_mirror_copy(char **av, int ac); void hammer_cmd_history(const char *offset_str, char **av, int ac); void hammer_cmd_blockmap(void); void hammer_cmd_reblock(char **av, int ac, int flags); -void hammer_cmd_pseudofs(char **av, int ac); +void hammer_cmd_pseudofs_status(char **av, int ac); +void hammer_cmd_pseudofs_create(char **av, int ac); +void hammer_cmd_pseudofs_update(char **av, int ac, int doinit); void hammer_cmd_status(char **av, int ac); void hammer_cmd_snapshot(char **av, int ac); -- 2.11.4.GIT