From: Matthew Dillon Date: Sat, 12 Jul 2008 02:48:46 +0000 (+0000) Subject: HAMMER Utillities: Sync with 61D X-Git-Tag: v2.0.1~139 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/9c67b4d2b6dba8bd1db3343a9fa5ced441a9c7f2 HAMMER Utillities: Sync with 61D * Add the new pfs-upgrade, pfs-downgrade, and pfs-destroy directives. * Add more safeties to the PFS directives. --- diff --git a/sbin/hammer/cmd_mirror.c b/sbin/hammer/cmd_mirror.c index aca0b936d6..6360b8ad38 100644 --- a/sbin/hammer/cmd_mirror.c +++ b/sbin/hammer/cmd_mirror.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_mirror.c,v 1.7 2008/07/10 04:44:58 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_mirror.c,v 1.8 2008/07/12 02:48:46 dillon Exp $ */ #include "hammer.h" @@ -133,6 +133,12 @@ hammer_cmd_mirror_read(char **av, int ac) filesystem, strerror(errno)); exit(1); } + if (mirror.head.flags & HAMMER_IOC_HEAD_ERROR) { + fprintf(stderr, + "Mirror-read %s fatal error %d\n", + filesystem, mirror.head.error); + exit(1); + } if (mirror.count) { n = write(1, mirror.ubuf, mirror.count); if (n != mirror.count) { @@ -880,10 +886,12 @@ update_pfs_snapshot(int fd, hammer_tid_t snapshot_tid, int pfs_id) perror("update_pfs_snapshot (read)"); exit(1); } - pfsd.sync_end_tid = snapshot_tid; - if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) != 0) { - perror("update_pfs_snapshot (rewrite)"); - exit(1); + if (pfsd.sync_end_tid != snapshot_tid) { + pfsd.sync_end_tid = snapshot_tid; + if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) != 0) { + perror("update_pfs_snapshot (rewrite)"); + exit(1); + } } } diff --git a/sbin/hammer/cmd_pseudofs.c b/sbin/hammer/cmd_pseudofs.c index 87516f6475..79d2be2c2e 100644 --- a/sbin/hammer/cmd_pseudofs.c +++ b/sbin/hammer/cmd_pseudofs.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_pseudofs.c,v 1.5 2008/07/09 10:32:30 dillon Exp $ + * $DragonFly: src/sbin/hammer/cmd_pseudofs.c,v 1.6 2008/07/12 02:48:46 dillon Exp $ */ #include "hammer.h" @@ -40,6 +40,7 @@ static void parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd); static void init_pfsd(hammer_pseudofs_data_t pfsd, int is_slave); static void dump_pfsd(hammer_pseudofs_data_t pfsd); static void pseudofs_usage(int code); +static int getyn(void); /* * Calculate the pfs_id given a path to a directory or a @@PFS or @@%llx:%d @@ -70,6 +71,33 @@ getpfs(struct hammer_ioc_pseudofs_rw *pfs, const char *path) dirpath = strdup("."); if (lstat(path, &st) == 0 && S_ISLNK(st.st_mode)) { + /* + * Avoid foot-shooting. Don't let the user access a PFS + * softlink via a PFS. PFS softlinks may only be accessed + * via the master filesystem. + */ + fd = open(dirpath, O_RDONLY); + if (fd < 0) + goto done; + pfs->pfs_id = -1; + ioctl(fd, HAMMERIOC_GET_PSEUDOFS, pfs); + if (pfs->pfs_id != 0) { + fprintf(stderr, + "You are attempting to access a PFS softlink " + "from a PFS. It may not represent the PFS\n" + "on the main filesystem mount that you " + "expect! You may only access PFS softlinks\n" + "via the main filesystem mount!\n"); + exit(1); + } + close(fd); + + /* + * Extract the PFS from the link. HAMMER will automatically + * convert @@PFS%05d links so if actually see one in that + * form the target PFS may not exist or may be corrupt. But + * we can extract the PFS id anyway. + */ n = readlink(path, buf, sizeof(buf) - 1); if (n < 0) n = 0; @@ -224,7 +252,139 @@ hammer_cmd_pseudofs_create(char **av, int ac, int is_slave) void hammer_cmd_pseudofs_destroy(char **av, int ac) { - fprintf(stderr, "pfs-destroy not implemented yet\n"); + struct hammer_ioc_pseudofs_rw pfs; + struct stat st; + int fd; + int i; + + if (ac == 0) + pseudofs_usage(1); + bzero(&pfs, sizeof(pfs)); + fd = getpfs(&pfs, av[0]); + + if (pfs.pfs_id == 0) { + fprintf(stderr, "You cannot destroy PFS#0\n"); + exit(1); + } + printf("You have requested that PFS#%d (%s) be destroyed\n", + pfs.pfs_id, pfs.ondisk->label); + printf("This will irrevocably destroy all data on this PFS!!!!!\n"); + printf("Do you really want to do this? "); + fflush(stdout); + if (getyn() == 0) { + fprintf(stderr, "No action taken on PFS#%d\n", pfs.pfs_id); + exit(1); + } + + if ((pfs.ondisk->mirror_flags & HAMMER_PFSD_SLAVE) == 0) { + printf("This PFS is currently setup as a MASTER!\n"); + printf("Are you absolutely sure you want to destroy it? "); + fflush(stdout); + if (getyn() == 0) { + fprintf(stderr, "No action taken on PFS#%d\n", + pfs.pfs_id); + exit(1); + } + } + + printf("Destroying PFS #%d (%s) in ", pfs.pfs_id, pfs.ondisk->label); + for (i = 5; i; --i) { + printf(" %d", i); + fflush(stdout); + sleep(1); + } + printf(".. starting destruction pass\n"); + fflush(stdout); + + /* + * Set the sync_beg_tid and sync_end_tid's to 1, once we start the + * RMR the PFS is basically destroyed even if someone ^C's it. + */ + pfs.ondisk->mirror_flags |= HAMMER_PFSD_SLAVE; + pfs.ondisk->master_id = -1; + pfs.ondisk->sync_beg_tid = 1; + pfs.ondisk->sync_end_tid = 1; + + if (ioctl(fd, HAMMERIOC_SET_PSEUDOFS, &pfs) < 0) { + fprintf(stderr, "Unable to update the PFS configuration: %s\n", + strerror(errno)); + exit(1); + } + + /* + * Ok, do it. Remove the softlink on success. + */ + if (ioctl(fd, HAMMERIOC_RMR_PSEUDOFS, &pfs) == 0) { + printf("pfs-destroy of PFS#%d succeeded!\n", pfs.pfs_id); + if (lstat(av[0], &st) == 0 && S_ISLNK(st.st_mode)) { + if (remove(av[0]) < 0) { + fprintf(stderr, "Unable to remove softlink: %s " + "(but the PFS has been destroyed)\n", + av[0]); + /* exit status 0 anyway */ + } + } + } else { + printf("pfs-destroy of PFS#%d failed: %s\n", + pfs.pfs_id, strerror(errno)); + } +} + +void +hammer_cmd_pseudofs_upgrade(char **av, int ac) +{ + struct hammer_ioc_pseudofs_rw pfs; + int fd; + + if (ac == 0) + pseudofs_usage(1); + bzero(&pfs, sizeof(pfs)); + fd = getpfs(&pfs, av[0]); + + if (pfs.pfs_id == 0) { + fprintf(stderr, "You cannot upgrade PFS#0" + " (It should already be a master)\n"); + exit(1); + } + if (pfs.ondisk->master_id == -1) { + fprintf(stderr, "You must configure a master id before " + "upgrading a slave to a master.\n" + "Use pfs-update ... master= first.\n"); + exit(1); + } + + if (ioctl(fd, HAMMERIOC_UPG_PSEUDOFS, &pfs) == 0) { + printf("pfs-upgrade of PFS#%d (%s) succeeded\n", + pfs.pfs_id, pfs.ondisk->label); + } else { + fprintf(stderr, "pfs-upgrade of PFS#%d (%s) failed: %s\n", + pfs.pfs_id, pfs.ondisk->label, strerror(errno)); + } +} + +void +hammer_cmd_pseudofs_downgrade(char **av, int ac) +{ + struct hammer_ioc_pseudofs_rw pfs; + int fd; + + if (ac == 0) + pseudofs_usage(1); + bzero(&pfs, sizeof(pfs)); + fd = getpfs(&pfs, av[0]); + + if (pfs.pfs_id == 0) { + fprintf(stderr, "You cannot downgrade PFS#0\n"); + exit(1); + } + + if (ioctl(fd, HAMMERIOC_DGD_PSEUDOFS, &pfs) == 0) { + printf("pfs-downgrade of PFS#%d (%s) succeeded\n", + pfs.pfs_id, pfs.ondisk->label); + } else { + fprintf(stderr, "pfs-upgrade of PFS#%d (%s) failed: %s\n", + pfs.pfs_id, pfs.ondisk->label, strerror(errno)); + } } void @@ -241,11 +401,13 @@ hammer_cmd_pseudofs_update(char **av, int ac) printf("%s\n", av[0]); fflush(stdout); - if (fd >= 0 && ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) { + if (ioctl(fd, HAMMERIOC_GET_PSEUDOFS, &pfs) == 0) { parse_pfsd_options(av + 1, ac - 1, pfs.ondisk); if ((pfs.ondisk->mirror_flags & HAMMER_PFSD_SLAVE) && pfs.pfs_id == 0) { - fprintf(stderr, "The real mount point cannot be made a PFS slave, only PFS sub-directories can be made slaves\n"); + printf("The real mount point cannot be made a PFS " + "slave, only PFS sub-directories can be made " + "slaves\n"); exit(1); } pfs.bytes = sizeof(*pfs.ondisk); @@ -260,9 +422,6 @@ hammer_cmd_pseudofs_update(char **av, int ac) printf("Unable to adjust pfs configuration: %s\n", strerror(errno)); exit(1); } - } else { - printf("PFS Creation failed: %s\n", strerror(errno)); - exit(1); } } @@ -300,10 +459,20 @@ dump_pfsd(hammer_pseudofs_data_t pfsd) 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"); + } + if (pfsd->master_id < 0) { + if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) { + printf(" master=-1 " + "(no upgrade id assigned for slave)\n"); + } else { + printf(" no-mirror " + "(mirror TID propagation disabled)\n"); + } } else { - printf(" master=%d\n", pfsd->master_id); + printf(" master=%d", pfsd->master_id); + if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) + printf(" (only if upgraded, currently a slave)"); + printf("\n"); } printf(" label=\"%s\"\n", pfsd->label); } @@ -353,21 +522,25 @@ parse_pfsd_options(char **av, int ac, hammer_pseudofs_data_t pfsd) uuid_from_string(ptr, &pfsd->unique_uuid, &status); } else if (strcmp(cmd, "master") == 0) { if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) { - fprintf(stderr, "master mode cannot be set on a slave PFS\n"); - exit(1); + printf("NOTE: This PFS is a slave, the master " + "id you are setting only applies\n" + "when you pfs-upgrade the PFS to " + "a master!\n"); } pfsd->master_id = strtol(ptr, NULL, 0); - pfsd->mirror_flags &= ~HAMMER_PFSD_SLAVE; } else if (strcmp(cmd, "slave") == 0) { if ((pfsd->mirror_flags & HAMMER_PFSD_SLAVE) == 0) { - fprintf(stderr, "slave mode cannot be set on a master PFS\n"); + fprintf(stderr, + "slave mode cannot be set on a master " + "PFS, use pfs-upgrade instead!\n"); exit(1); } - pfsd->master_id = -1; pfsd->mirror_flags |= HAMMER_PFSD_SLAVE; } else if (strcmp(cmd, "no-mirror") == 0) { if (pfsd->mirror_flags & HAMMER_PFSD_SLAVE) { - fprintf(stderr, "no-mirror master mode cannot be set on a slave PFS\n"); + fprintf(stderr, + "no-mirror mode cannot be set on a " + "slave PFS\n"); exit(1); } pfsd->master_id = -1; @@ -406,9 +579,12 @@ pseudofs_usage(int code) "hammer pfs-status ...\n" "hammer pfs-master [options]\n" "hammer pfs-slave [options]\n" - "hammer pfs-destroy \n" "hammer pfs-update [options]\n" + "hammer pfs-upgrade \n" + "hammer pfs-downgrade \n" + "hammer pfs-destroy \n" "\n" + "options:\n" " sync-beg-tid=0x16llx\n" " sync-end-tid=0x16llx\n" " shared-uuid=0x16llx\n" @@ -421,3 +597,25 @@ pseudofs_usage(int code) exit(code); } +static +int +getyn(void) +{ + char buf[256]; + int len; + + if (fgets(buf, sizeof(buf), stdin) == NULL) + return(0); + len = strlen(buf); + while (len && (buf[len-1] == '\n' || buf[len-1] == '\r')) + --len; + buf[len] = 0; + if (strcmp(buf, "y") == 0 || + strcmp(buf, "yes") == 0 || + strcmp(buf, "Y") == 0 || + strcmp(buf, "YES") == 0) { + return(1); + } + return(0); +} + diff --git a/sbin/hammer/hammer.8 b/sbin/hammer/hammer.8 index 9abbc3853a..53aab3668d 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.34 2008/07/09 18:32:19 swildner Exp $ +.\" $DragonFly: src/sbin/hammer/hammer.8,v 1.35 2008/07/12 02:48:46 dillon Exp $ .Dd June 26, 2008 .Dt HAMMER 8 .Os @@ -275,8 +275,27 @@ A PFS can only be truely destroyed with the .AR pfs-destroy directive. Removing the softlink will not destroy the underlying PFS. +.It Ar pfs-upgrade Ar dirpath +Upgrade a PFS from slave to master operation. The PFS becomes writable. +A master id must already be assigned to the PFS. +.Pp +WARNING! HAMMER currently supports only single masters and using +this command can easily result in filesystem corruption if you don't +know what you are doing. +.Pp +This directive will refuse to run if any programs have open descriptors +in the PFS, including programs chdir'd into the PFS. +.It Ar pfs-downgrade Ar dirpath +Downgrade a master PFS from master to slave operation. The PFS becomes +read-only and access will be locked to its sync_end_tid. +.Pp +This directive will refuse to run if any programs have open descriptors +in the PFS, including programs chdir'd into the PFS. .It Ar pfs-destroy Ar dirpath This permanently destroys a PFS. +.Pp +This directive will refuse to run if any programs have open descriptors +in the PFS, including programs chdir'd into the PFS. .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: @@ -355,11 +374,39 @@ representation of the mirroring stream. 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 a ssh and execs the mirror-read and/or mirror-write on the appropriate host. +The source may be a master or slave PFS, and the target must be a slave PFS. .Pp -This command also turns on the two-way protocol feature which automatically -negotiates TID ranges without having to use a cycle file. +This command also established full duplex communication and turns on +the two-way protocol feature which automatically negotiates TID ranges +without having to use a cycle file. +If the operation completes successfully the target PFS's sync_end_tid will +be updated. Note that you must re-chdir into the target PFS to see the +updated information. If you do not you will still be in the previous snapshot. .El .\".Sh EXAMPLES +.Sh PSEUDO FILESYSTEM (PFS) NOTES +The root of a PFS is not hooked into the primary HAMMER filesystem as a +directory. +Instead, HAMMER creates a special softlink called "@@PFS%05d" (exactly 10 +characters long) in the primary HAMMER filesystem. +HAMMER then modifies the contents of the softlink as read by +.Xr readlink 2 , +and thus what you see with an ls command or if you were to cd into the link. +If the PFS is a master the link reflects the current state of the PFS. +If the PFS is a slave the link reflects the last completed snapshot, and the +contents of the link will change when the next snapshot is completed, and +so forth. +.Pp +PFS support is currently very new and experimental. The +.Nm +utility +employs numerous safeties to reduce user foot-shooting. +The +.Ar mirror-copy +directive requires that the target be configured as a slave and that the +.Ar shared-uuid +field of the mirroring source and target match. +.Pp .Sh DIAGNOSTICS .Ex -std .Sh SEE ALSO diff --git a/sbin/hammer/hammer.c b/sbin/hammer/hammer.c index 04b788e90f..40f3b422d9 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.32 2008/07/09 18:32:19 swildner Exp $ + * $DragonFly: src/sbin/hammer/hammer.c,v 1.33 2008/07/12 02:48:46 dillon Exp $ */ #include "hammer.h" @@ -142,6 +142,14 @@ main(int ac, char **av) hammer_cmd_pseudofs_update(av + 1, ac - 1); exit(0); } + if (strcmp(av[0], "pfs-upgrade") == 0) { + hammer_cmd_pseudofs_upgrade(av + 1, ac - 1); + exit(0); + } + if (strcmp(av[0], "pfs-downgrade") == 0) { + hammer_cmd_pseudofs_downgrade(av + 1, ac - 1); + exit(0); + } if (strcmp(av[0], "pfs-destroy") == 0) { hammer_cmd_pseudofs_destroy(av + 1, ac - 1); exit(0); @@ -279,6 +287,9 @@ usage(int exit_code) "hammer pfs-master [options]\n" "hammer pfs-slave [options]\n" "hammer pfs-update [options]\n" + "hammer pfs-upgrade \n" + "hammer pfs-downgrade \n" + "hammer pfs-destroy \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 1bb9f4ed4e..802d31d9dd 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.22 2008/07/09 10:32:30 dillon Exp $ + * $DragonFly: src/sbin/hammer/hammer.h,v 1.23 2008/07/12 02:48:46 dillon Exp $ */ #include @@ -85,6 +85,8 @@ void hammer_cmd_pseudofs_status(char **av, int ac); void hammer_cmd_pseudofs_create(char **av, int ac, int is_slave); void hammer_cmd_pseudofs_update(char **av, int ac); void hammer_cmd_pseudofs_destroy(char **av, int ac); +void hammer_cmd_pseudofs_upgrade(char **av, int ac); +void hammer_cmd_pseudofs_downgrade(char **av, int ac); void hammer_cmd_status(char **av, int ac); void hammer_cmd_snapshot(char **av, int ac);