1 /* 2 * Copyright (c) 2007 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sbin/mount_hammer/mount_hammer.c,v 1.9 2008/07/19 18:48:15 dillon Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/diskslice.h> 39 #include <sys/diskmbr.h> 40 #include <sys/stat.h> 41 #include <sys/time.h> 42 #include <sys/syslimits.h> 43 #include <vfs/hammer/hammer_mount.h> 44 #include <vfs/hammer/hammer_disk.h> 45 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <stdarg.h> 49 #include <stddef.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <uuid.h> 55 #include <err.h> 56 #include <assert.h> 57 #include <ctype.h> 58 59 #include "mntopts.h" 60 61 typedef const char **ary_ptr_t; 62 63 static void extract_volumes(ary_ptr_t *aryp, int *countp, char **av, int ac); 64 65 #define MOPT_UPDATE { "update", 0, MNT_UPDATE, 0 } 66 67 #define MOPT_HAMMEROPTS \ 68 { "history", 1, HMNT_NOHISTORY, 1 }, \ 69 { "master=", 0, HMNT_MASTERID, 1 }, \ 70 { "mirror", 1, HMNT_MASTERID, 1 } 71 72 static struct mntopt mopts[] = { MOPT_STDOPTS, MOPT_HAMMEROPTS, 73 MOPT_UPDATE, MOPT_NULL }; 74 75 static void usage(void); 76 77 int 78 main(int ac, char **av) 79 { 80 struct hammer_mount_info info; 81 struct vfsconf vfc; 82 struct hammer_volume_ondisk *od; 83 int mount_flags = 0; 84 int error; 85 int ch; 86 int init_flags = 0; 87 int ax; 88 int fd; 89 int pr; 90 int fdevs_size; 91 char *mountpt; 92 char *ptr; 93 char *fdevs; 94 95 96 bzero(&info, sizeof(info)); 97 info.asof = 0; 98 mount_flags = 0; 99 info.hflags = 0; 100 101 while ((ch = getopt(ac, av, "o:T:u")) != -1) { 102 switch(ch) { 103 case 'T': 104 info.asof = strtoull(optarg, NULL, 0); 105 break; 106 case 'o': 107 getmntopts(optarg, mopts, &mount_flags, &info.hflags); 108 109 110 /* 111 * Handle extended flags with parameters. 112 */ 113 if (info.hflags & HMNT_MASTERID) { 114 ptr = strstr(optarg, "master="); 115 if (ptr) { 116 info.master_id = strtol(ptr + 7, NULL, 0); 117 if (info.master_id == 0) { 118 fprintf(stderr, 119 "hammer_mount: Warning: a master id of 0 is the default, explicit\n" 120 "settings should probably use 1-15\n"); 121 } 122 } 123 ptr = strstr(optarg, "nomirror"); 124 if (ptr) 125 info.master_id = -1; 126 } 127 break; 128 case 'u': 129 init_flags |= MNT_UPDATE; 130 break; 131 default: 132 usage(); 133 /* not reached */ 134 } 135 } 136 ac -= optind; 137 av += optind; 138 mount_flags |= init_flags; 139 140 /* 141 * Only the mount point need be specified in update mode. 142 */ 143 if (init_flags & MNT_UPDATE) { 144 if (ac != 1) { 145 usage(); 146 /* not reached */ 147 } 148 mountpt = av[0]; 149 if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) 150 err(1, "mountpoint %s", mountpt); 151 exit(0); 152 } 153 154 if (ac < 2) { 155 usage(); 156 /* not reached */ 157 } 158 159 /* 160 * Mount arguments: vol [vol...] mountpt 161 */ 162 extract_volumes(&info.volumes, &info.nvolumes, av, ac - 1); 163 mountpt = av[ac - 1]; 164 165 /* 166 * Load the hammer module if necessary (this bit stolen from 167 * mount_null). 168 */ 169 error = getvfsbyname("hammer", &vfc); 170 if (error && vfsisloadable("hammer")) { 171 if (vfsload("hammer") != 0) 172 err(1, "vfsload(hammer)"); 173 endvfsent(); 174 error = getvfsbyname("hammer", &vfc); 175 } 176 if (error) 177 errx(1, "hammer filesystem is not available"); 178 179 if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { 180 /* Build fdevs in case of error to report failed devices */ 181 fdevs_size = ac * PATH_MAX; 182 fdevs = malloc(fdevs_size); 183 for (ax = 0; ax < ac - 1; ax++) { 184 fd = open(info.volumes[ax], O_RDONLY); 185 if (fd < 0 ) { 186 printf ("%s: open failed\n", info.volumes[ax]); 187 strlcat(fdevs, info.volumes[ax], fdevs_size); 188 if (ax < ac - 2) 189 strlcat(fdevs, " ", fdevs_size); 190 continue; 191 } 192 193 od = malloc(HAMMER_BUFSIZE); 194 if (od == NULL) { 195 close (fd); 196 perror("malloc"); 197 continue; 198 } 199 200 bzero(od, HAMMER_BUFSIZE); 201 pr = pread(fd, od, HAMMER_BUFSIZE, 0); 202 if (pr != HAMMER_BUFSIZE || 203 od->vol_signature != HAMMER_FSBUF_VOLUME) { 204 printf("%s: Not a valid HAMMER filesystem\n", info.volumes[ax]); 205 strlcat(fdevs, info.volumes[ax], fdevs_size); 206 if (ax < ac - 2) 207 strlcat(fdevs, " ", fdevs_size); 208 } 209 close(fd); 210 } 211 err(1,"mount %s on %s", fdevs, mountpt); 212 } 213 exit (0); 214 } 215 216 /* 217 * Extract a volume list 218 */ 219 static void 220 extract_volumes(ary_ptr_t *aryp, int *countp, char **av, int ac) 221 { 222 int idx = 0; 223 int arymax = 32; 224 const char **ary = malloc(sizeof(char *) * 32); 225 char *ptr; 226 char *next; 227 228 while (ac) { 229 if (idx == arymax) { 230 arymax += 32; 231 ary = realloc(ary, sizeof(char *) * arymax); 232 } 233 if (strchr(*av, ':') == NULL) { 234 ary[idx++] = *av; 235 } else { 236 next = strdup(*av); 237 while ((ptr = next) != NULL) { 238 if (idx == arymax) { 239 arymax += 32; 240 ary = realloc(ary, sizeof(char *) * 241 arymax); 242 } 243 if ((next = strchr(ptr, ':')) != NULL) 244 *next++ = 0; 245 ary[idx++] = ptr; 246 } 247 } 248 --ac; 249 ++av; 250 251 } 252 *aryp = ary; 253 *countp = idx; 254 } 255 256 static 257 void 258 usage(void) 259 { 260 fprintf(stderr, "usage: mount_hammer [-o options] [-T transaction-id] " 261 "special ... node\n"); 262 fprintf(stderr, " mount_hammer [-o options] [-T transaction-id] " 263 "special[:special]* node\n"); 264 fprintf(stderr, " mount_hammer -u [-o options] node\n"); 265 exit(1); 266 } 267