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