1 /* 2 * Copyright (c) 2011-2012 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@dragonflybsd.org> 6 * by Venkatesh Srinivas <vsrinivas@dragonflybsd.org> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include "hammer2.h" 37 38 struct pfs_entry { 39 TAILQ_ENTRY(pfs_entry) entry; 40 char name[NAME_MAX+1]; 41 char s[NAME_MAX+1]; 42 }; 43 44 int 45 cmd_pfs_list(int ac, char **av) 46 { 47 hammer2_ioc_pfs_t pfs; 48 int ecode = 0; 49 int fd; 50 int i; 51 int all = 0; 52 char *pfs_id_str = NULL; 53 const char *type_str; 54 TAILQ_HEAD(, pfs_entry) head; 55 struct pfs_entry *p, *e; 56 57 if (ac == 1 && av[0] == NULL) { 58 av = get_hammer2_mounts(&ac); 59 all = 1; 60 } 61 62 for (i = 0; i < ac; ++i) { 63 if ((fd = hammer2_ioctl_handle(av[i])) < 0) 64 return(1); 65 bzero(&pfs, sizeof(pfs)); 66 TAILQ_INIT(&head); 67 if (i) 68 printf("\n"); 69 70 while ((pfs.name_key = pfs.name_next) != (hammer2_key_t)-1) { 71 if (ioctl(fd, HAMMER2IOC_PFS_GET, &pfs) < 0) { 72 perror("ioctl"); 73 ecode = 1; 74 break; 75 } 76 hammer2_uuid_to_str(&pfs.pfs_clid, &pfs_id_str); 77 if (pfs.pfs_type == HAMMER2_PFSTYPE_MASTER) { 78 if (pfs.pfs_subtype == HAMMER2_PFSSUBTYPE_NONE) 79 type_str = "MASTER"; 80 else 81 type_str = hammer2_pfssubtype_to_str( 82 pfs.pfs_subtype); 83 } else { 84 type_str = hammer2_pfstype_to_str(pfs.pfs_type); 85 } 86 e = calloc(1, sizeof(*e)); 87 snprintf(e->name, sizeof(e->name), "%s", pfs.name); 88 snprintf(e->s, sizeof(e->s), "%-11s %s", 89 type_str, pfs_id_str); 90 free(pfs_id_str); 91 pfs_id_str = NULL; 92 93 p = TAILQ_FIRST(&head); 94 while (p) { 95 if (strcmp(e->name, p->name) <= 0) { 96 TAILQ_INSERT_BEFORE(p, e, entry); 97 break; 98 } 99 p = TAILQ_NEXT(p, entry); 100 } 101 if (!p) 102 TAILQ_INSERT_TAIL(&head, e, entry); 103 } 104 close(fd); 105 106 printf("Type " 107 "ClusterId (pfs_clid) " 108 "Label on %s\n", av[i]); 109 while ((p = TAILQ_FIRST(&head)) != NULL) { 110 printf("%s %s\n", p->s, p->name); 111 TAILQ_REMOVE(&head, p, entry); 112 free(p); 113 } 114 } 115 116 if (all) 117 put_hammer2_mounts(ac, av); 118 119 return (ecode); 120 } 121 122 int 123 cmd_pfs_getid(const char *sel_path, const char *name, int privateid) 124 { 125 hammer2_ioc_pfs_t pfs; 126 int ecode = 0; 127 int fd; 128 char *pfs_id_str = NULL; 129 130 if ((fd = hammer2_ioctl_handle(sel_path)) < 0) 131 return(1); 132 bzero(&pfs, sizeof(pfs)); 133 134 snprintf(pfs.name, sizeof(pfs.name), "%s", name); 135 if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0) { 136 perror("ioctl"); 137 ecode = 1; 138 } else { 139 if (privateid) 140 hammer2_uuid_to_str(&pfs.pfs_fsid, &pfs_id_str); 141 else 142 hammer2_uuid_to_str(&pfs.pfs_clid, &pfs_id_str); 143 printf("%s\n", pfs_id_str); 144 free(pfs_id_str); 145 pfs_id_str = NULL; 146 } 147 close(fd); 148 return (ecode); 149 } 150 151 152 int 153 cmd_pfs_create(const char *sel_path, const char *name, 154 uint8_t pfs_type, const char *uuid_str) 155 { 156 hammer2_ioc_pfs_t pfs; 157 int ecode = 0; 158 int fd; 159 uint32_t status; 160 161 /* 162 * Default to MASTER if no uuid was specified. 163 * Default to SLAVE if a uuid was specified. 164 * 165 * When adding masters to a cluster, the new PFS must be added as 166 * a slave and then upgraded to ensure proper synchronization. 167 */ 168 if (pfs_type == HAMMER2_PFSTYPE_NONE) { 169 if (uuid_str) 170 pfs_type = HAMMER2_PFSTYPE_SLAVE; 171 else 172 pfs_type = HAMMER2_PFSTYPE_MASTER; 173 } 174 175 if ((fd = hammer2_ioctl_handle(sel_path)) < 0) 176 return(1); 177 bzero(&pfs, sizeof(pfs)); 178 snprintf(pfs.name, sizeof(pfs.name), "%s", name); 179 pfs.pfs_type = pfs_type; 180 if (uuid_str) { 181 uuid_from_string(uuid_str, &pfs.pfs_clid, &status); 182 } else { 183 uuid_create(&pfs.pfs_clid, &status); 184 } 185 if (status == uuid_s_ok) 186 uuid_create(&pfs.pfs_fsid, &status); 187 if (status == uuid_s_ok) { 188 if (ioctl(fd, HAMMER2IOC_PFS_CREATE, &pfs) < 0) { 189 if (errno == EEXIST) { 190 fprintf(stderr, 191 "NOTE: Typically the same name is " 192 "used for cluster elements on " 193 "different mounts,\n" 194 " but cluster elements on the " 195 "same mount require unique names.\n" 196 "hammer2: pfs_create(%s): already present\n", 197 name); 198 } else { 199 fprintf(stderr, "hammer2: pfs_create(%s): %s\n", 200 name, strerror(errno)); 201 } 202 ecode = 1; 203 } else { 204 printf("hammer2: pfs_create(%s): SUCCESS\n", name); 205 } 206 } else { 207 fprintf(stderr, "hammer2: pfs_create(%s): badly formed uuid\n", 208 name); 209 ecode = 1; 210 } 211 close(fd); 212 return (ecode); 213 } 214 215 int 216 cmd_pfs_delete(const char *sel_path, char **av, int ac) 217 { 218 hammer2_ioc_pfs_t pfs; 219 int ecode = 0; 220 int fd; 221 int i; 222 int n; 223 int use_fd; 224 int nmnts = 0; 225 char **mnts = NULL; 226 227 if (sel_path == NULL) 228 mnts = get_hammer2_mounts(&nmnts); 229 230 for (i = 1; i < ac; ++i) { 231 int enoents = 0; 232 bzero(&pfs, sizeof(pfs)); 233 snprintf(pfs.name, sizeof(pfs.name), "%s", av[i]); 234 235 if (sel_path) { 236 use_fd = hammer2_ioctl_handle(sel_path); 237 } else { 238 use_fd = -1; 239 for (n = 0; n < nmnts; ++n) { 240 if ((fd = hammer2_ioctl_handle(mnts[n])) < 0) { 241 enoents++; 242 continue; 243 } 244 if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0) { 245 enoents++; 246 continue; 247 } 248 if (use_fd >= 0) { 249 fprintf(stderr, 250 "hammer2: pfs_delete(%s): " 251 "Duplicate PFS name, " 252 "must specify mount\n", 253 av[i]); 254 close(use_fd); 255 use_fd = -1; 256 break; 257 } 258 use_fd = fd; 259 } 260 } 261 if (use_fd >= 0) { 262 if (ioctl(use_fd, HAMMER2IOC_PFS_DELETE, &pfs) < 0) { 263 printf("hammer2: pfs_delete(%s): %s\n", 264 av[i], strerror(errno)); 265 ecode = 1; 266 } else { 267 printf("hammer2: pfs_delete(%s): SUCCESS\n", 268 av[i]); 269 } 270 close(use_fd); 271 } else { 272 if (enoents == nmnts) 273 printf("hammer2: pfs_delete(%s): %s not found\n", 274 av[i], av[i]); 275 else 276 printf("hammer2: pfs_delete(%s): FAILED\n", 277 av[i]); 278 ecode = 1; 279 } 280 } 281 if (mnts) 282 put_hammer2_mounts(nmnts, mnts); 283 return (ecode); 284 } 285