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 type_str = hammer2_pfssubtype_to_str(pfs.pfs_subtype); 79 else 80 type_str = hammer2_pfstype_to_str(pfs.pfs_type); 81 e = calloc(1, sizeof(*e)); 82 snprintf(e->name, sizeof(e->name), "%s", pfs.name); 83 snprintf(e->s, sizeof(e->s), "%-11s %s", 84 type_str, pfs_id_str); 85 free(pfs_id_str); 86 pfs_id_str = NULL; 87 88 p = TAILQ_FIRST(&head); 89 while (p) { 90 if (strcmp(e->name, p->name) <= 0) { 91 TAILQ_INSERT_BEFORE(p, e, entry); 92 break; 93 } 94 p = TAILQ_NEXT(p, entry); 95 } 96 if (!p) 97 TAILQ_INSERT_TAIL(&head, e, entry); 98 } 99 close(fd); 100 101 printf("Type " 102 "ClusterId (pfs_clid) " 103 "Label on %s\n", av[i]); 104 while ((p = TAILQ_FIRST(&head)) != NULL) { 105 printf("%s %s\n", p->s, p->name); 106 TAILQ_REMOVE(&head, p, entry); 107 free(p); 108 } 109 } 110 111 if (all) 112 put_hammer2_mounts(ac, av); 113 114 return (ecode); 115 } 116 117 int 118 cmd_pfs_getid(const char *sel_path, const char *name, int privateid) 119 { 120 hammer2_ioc_pfs_t pfs; 121 int ecode = 0; 122 int fd; 123 char *pfs_id_str = NULL; 124 125 if ((fd = hammer2_ioctl_handle(sel_path)) < 0) 126 return(1); 127 bzero(&pfs, sizeof(pfs)); 128 129 snprintf(pfs.name, sizeof(pfs.name), "%s", name); 130 if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0) { 131 perror("ioctl"); 132 ecode = 1; 133 } else { 134 if (privateid) 135 hammer2_uuid_to_str(&pfs.pfs_fsid, &pfs_id_str); 136 else 137 hammer2_uuid_to_str(&pfs.pfs_clid, &pfs_id_str); 138 printf("%s\n", pfs_id_str); 139 free(pfs_id_str); 140 pfs_id_str = NULL; 141 } 142 close(fd); 143 return (ecode); 144 } 145 146 147 int 148 cmd_pfs_create(const char *sel_path, const char *name, 149 uint8_t pfs_type, const char *uuid_str) 150 { 151 hammer2_ioc_pfs_t pfs; 152 int ecode = 0; 153 int fd; 154 uint32_t status; 155 156 /* 157 * Default to MASTER if no uuid was specified. 158 * Default to SLAVE if a uuid was specified. 159 * 160 * When adding masters to a cluster, the new PFS must be added as 161 * a slave and then upgraded to ensure proper synchronization. 162 */ 163 if (pfs_type == HAMMER2_PFSTYPE_NONE) { 164 if (uuid_str) 165 pfs_type = HAMMER2_PFSTYPE_SLAVE; 166 else 167 pfs_type = HAMMER2_PFSTYPE_MASTER; 168 } 169 170 if ((fd = hammer2_ioctl_handle(sel_path)) < 0) 171 return(1); 172 bzero(&pfs, sizeof(pfs)); 173 snprintf(pfs.name, sizeof(pfs.name), "%s", name); 174 pfs.pfs_type = pfs_type; 175 if (uuid_str) { 176 uuid_from_string(uuid_str, &pfs.pfs_clid, &status); 177 } else { 178 uuid_create(&pfs.pfs_clid, &status); 179 } 180 if (status == uuid_s_ok) 181 uuid_create(&pfs.pfs_fsid, &status); 182 if (status == uuid_s_ok) { 183 if (ioctl(fd, HAMMER2IOC_PFS_CREATE, &pfs) < 0) { 184 if (errno == EEXIST) { 185 fprintf(stderr, 186 "NOTE: Typically the same name is " 187 "used for cluster elements on " 188 "different mounts,\n" 189 " but cluster elements on the " 190 "same mount require unique names.\n" 191 "hammer2: pfs_create(%s): already present\n", 192 name); 193 } else { 194 fprintf(stderr, "hammer2: pfs_create(%s): %s\n", 195 name, strerror(errno)); 196 } 197 ecode = 1; 198 } else { 199 printf("hammer2: pfs_create(%s): SUCCESS\n", name); 200 } 201 } else { 202 fprintf(stderr, "hammer2: pfs_create(%s): badly formed uuid\n", 203 name); 204 ecode = 1; 205 } 206 close(fd); 207 return (ecode); 208 } 209 210 int 211 cmd_pfs_delete(const char *sel_path, char **av, int ac) 212 { 213 hammer2_ioc_pfs_t pfs; 214 int ecode = 0; 215 int fd; 216 int i; 217 int n; 218 int use_fd; 219 int nmnts = 0; 220 char **mnts = NULL; 221 222 if (sel_path == NULL) 223 mnts = get_hammer2_mounts(&nmnts); 224 225 for (i = 1; i < ac; ++i) { 226 int enoents = 0; 227 bzero(&pfs, sizeof(pfs)); 228 snprintf(pfs.name, sizeof(pfs.name), "%s", av[i]); 229 230 if (sel_path) { 231 use_fd = hammer2_ioctl_handle(sel_path); 232 } else { 233 use_fd = -1; 234 for (n = 0; n < nmnts; ++n) { 235 if ((fd = hammer2_ioctl_handle(mnts[n])) < 0) { 236 enoents++; 237 continue; 238 } 239 if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0) { 240 enoents++; 241 continue; 242 } 243 if (use_fd >= 0) { 244 fprintf(stderr, 245 "hammer2: pfs_delete(%s): " 246 "Duplicate PFS name, " 247 "must specify mount\n", 248 av[i]); 249 close(use_fd); 250 use_fd = -1; 251 break; 252 } 253 use_fd = fd; 254 } 255 } 256 if (use_fd >= 0) { 257 if (ioctl(use_fd, HAMMER2IOC_PFS_DELETE, &pfs) < 0) { 258 printf("hammer2: pfs_delete(%s): %s\n", 259 av[i], strerror(errno)); 260 ecode = 1; 261 } else { 262 printf("hammer2: pfs_delete(%s): SUCCESS\n", 263 av[i]); 264 } 265 close(use_fd); 266 } else { 267 if (enoents == nmnts) 268 printf("hammer2: pfs_delete(%s): %s not found\n", 269 av[i], av[i]); 270 else 271 printf("hammer2: pfs_delete(%s): FAILED\n", 272 av[i]); 273 ecode = 1; 274 } 275 } 276 if (mnts) 277 put_hammer2_mounts(nmnts, mnts); 278 return (ecode); 279 } 280