xref: /dragonfly/sbin/hammer2/cmd_pfs.c (revision 6996755b)
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