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
cmd_pfs_list(int ac,char ** av)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
cmd_pfs_getid(const char * sel_path,const char * name,int privateid)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
cmd_pfs_create(const char * sel_path,const char * name,uint8_t pfs_type,const char * uuid_str)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
cmd_pfs_delete(const char * sel_path,char ** av,int ac)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