xref: /dragonfly/sbin/hammer2/cmd_pfs.c (revision 029e6489)
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 int
39 cmd_pfs_list(int ac, char **av)
40 {
41 	hammer2_ioc_pfs_t pfs;
42 	int ecode = 0;
43 	int count;
44 	int fd;
45 	int i;
46 	int all = 0;
47 	char *pfs_id_str = NULL;
48 
49 	if (ac == 1 && av[0] == NULL) {
50 		av = get_hammer2_mounts(&ac);
51 		all = 1;
52 	}
53 
54 	for (i = 0; i < ac; ++i) {
55 		if ((fd = hammer2_ioctl_handle(av[i])) < 0)
56 			return(1);
57 		bzero(&pfs, sizeof(pfs));
58 		count = 0;
59 		if (i)
60 			printf("\n");
61 
62 		while ((pfs.name_key = pfs.name_next) != (hammer2_key_t)-1) {
63 			if (ioctl(fd, HAMMER2IOC_PFS_GET, &pfs) < 0) {
64 				perror("ioctl");
65 				ecode = 1;
66 				break;
67 			}
68 			if (count == 0) {
69 				printf("Type        "
70 				       "ClusterId (pfs_clid)                 "
71 				       "Labels on %s\n", av[i]);
72 			}
73 			switch(pfs.pfs_type) {
74 			case HAMMER2_PFSTYPE_NONE:
75 				printf("NONE        ");
76 				break;
77 			case HAMMER2_PFSTYPE_CACHE:
78 				printf("CACHE       ");
79 				break;
80 			case HAMMER2_PFSTYPE_SLAVE:
81 				printf("SLAVE       ");
82 				break;
83 			case HAMMER2_PFSTYPE_SOFT_SLAVE:
84 				printf("SOFT_SLAVE  ");
85 				break;
86 			case HAMMER2_PFSTYPE_SOFT_MASTER:
87 				printf("SOFT_MASTER ");
88 				break;
89 			case HAMMER2_PFSTYPE_MASTER:
90 				switch (pfs.pfs_subtype) {
91 				case HAMMER2_PFSSUBTYPE_NONE:
92 					printf("MASTER      ");
93 					break;
94 				case HAMMER2_PFSSUBTYPE_SNAPSHOT:
95 					printf("SNAPSHOT    ");
96 					break;
97 				case HAMMER2_PFSSUBTYPE_AUTOSNAP:
98 					printf("AUTOSNAP    ");
99 					break;
100 				default:
101 					printf("MASTER(sub?)");
102 					break;
103 				}
104 				break;
105 			default:
106 				printf("%02x          ", pfs.pfs_type);
107 				break;
108 			}
109 			hammer2_uuid_to_str(&pfs.pfs_clid, &pfs_id_str);
110 			printf("%s ", pfs_id_str);
111 			free(pfs_id_str);
112 			pfs_id_str = NULL;
113 			printf("%s\n", pfs.name);
114 			++count;
115 		}
116 		close(fd);
117 	}
118 
119 	if (all)
120 		put_hammer2_mounts(ac, av);
121 
122 	return (ecode);
123 }
124 
125 int
126 cmd_pfs_getid(const char *sel_path, const char *name, int privateid)
127 {
128 	hammer2_ioc_pfs_t pfs;
129 	int ecode = 0;
130 	int fd;
131 	char *pfs_id_str = NULL;
132 
133 	if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
134 		return(1);
135 	bzero(&pfs, sizeof(pfs));
136 
137 	snprintf(pfs.name, sizeof(pfs.name), "%s", name);
138 	if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0) {
139 		perror("ioctl");
140 		ecode = 1;
141 	} else {
142 		if (privateid)
143 			hammer2_uuid_to_str(&pfs.pfs_fsid, &pfs_id_str);
144 		else
145 			hammer2_uuid_to_str(&pfs.pfs_clid, &pfs_id_str);
146 		printf("%s\n", pfs_id_str);
147 		free(pfs_id_str);
148 		pfs_id_str = NULL;
149 	}
150 	close(fd);
151 	return (ecode);
152 }
153 
154 
155 int
156 cmd_pfs_create(const char *sel_path, const char *name,
157 	       uint8_t pfs_type, const char *uuid_str)
158 {
159 	hammer2_ioc_pfs_t pfs;
160 	int ecode = 0;
161 	int fd;
162 	uint32_t status;
163 
164 	/*
165 	 * Default to MASTER if no uuid was specified.
166 	 * Default to SLAVE if a uuid was specified.
167 	 *
168 	 * When adding masters to a cluster, the new PFS must be added as
169 	 * a slave and then upgraded to ensure proper synchronization.
170 	 */
171 	if (pfs_type == HAMMER2_PFSTYPE_NONE) {
172 		if (uuid_str)
173 			pfs_type = HAMMER2_PFSTYPE_SLAVE;
174 		else
175 			pfs_type = HAMMER2_PFSTYPE_MASTER;
176 	}
177 
178 	if ((fd = hammer2_ioctl_handle(sel_path)) < 0)
179 		return(1);
180 	bzero(&pfs, sizeof(pfs));
181 	snprintf(pfs.name, sizeof(pfs.name), "%s", name);
182 	pfs.pfs_type = pfs_type;
183 	if (uuid_str) {
184 		uuid_from_string(uuid_str, &pfs.pfs_clid, &status);
185 	} else {
186 		uuid_create(&pfs.pfs_clid, &status);
187 	}
188 	if (status == uuid_s_ok)
189 		uuid_create(&pfs.pfs_fsid, &status);
190 	if (status == uuid_s_ok) {
191 		if (ioctl(fd, HAMMER2IOC_PFS_CREATE, &pfs) < 0) {
192 			if (errno == EEXIST) {
193 				fprintf(stderr,
194 					"NOTE: Typically the same name is "
195 					"used for cluster elements on "
196 					"different mounts,\n"
197 					"      but cluster elements on the "
198 					"same mount require unique names.\n"
199 					"pfs-create %s: already present\n",
200 					name);
201 			} else {
202 				perror("ioctl");
203 			}
204 			ecode = 1;
205 		}
206 	} else {
207 		fprintf(stderr, "hammer2: pfs_create: badly formed uuid\n");
208 		ecode = 1;
209 	}
210 	close(fd);
211 	return (ecode);
212 }
213 
214 int
215 cmd_pfs_delete(const char *sel_path, char **av, int ac)
216 {
217 	hammer2_ioc_pfs_t pfs;
218 	int ecode = 0;
219 	int fd;
220 	int i;
221 	int n;
222 	int use_fd;
223 	int nmnts = 0;
224 	char **mnts = NULL;
225 
226 	if (sel_path == NULL)
227 		mnts = get_hammer2_mounts(&nmnts);
228 
229 	for (i = 1; i < ac; ++i) {
230 		bzero(&pfs, sizeof(pfs));
231 		snprintf(pfs.name, sizeof(pfs.name), "%s", av[i]);
232 
233 		if (sel_path) {
234 			use_fd = hammer2_ioctl_handle(sel_path);
235 		} else {
236 			use_fd = -1;
237 			for (n = 0; n < nmnts; ++n) {
238 				if ((fd = hammer2_ioctl_handle(mnts[n])) < 0)
239 					continue;
240 				if (ioctl(fd, HAMMER2IOC_PFS_LOOKUP, &pfs) < 0)
241 					continue;
242 				if (use_fd >= 0) {
243 					fprintf(stderr,
244 						"hammer2: pfs_delete(%s): "
245 						"Duplicate PFS name, "
246 						"must specify mount\n",
247 						av[i]);
248 					close(use_fd);
249 					use_fd = -1;
250 					break;
251 				}
252 				use_fd = fd;
253 			}
254 		}
255 		if (use_fd >= 0) {
256 			if (ioctl(use_fd, HAMMER2IOC_PFS_DELETE, &pfs) < 0) {
257 				printf("hammer2: pfs_delete(%s): %s\n",
258 				       av[i], strerror(errno));
259 				ecode = 1;
260 			} else {
261 				printf("hammer2: pfs_delete(%s): SUCCESS\n",
262 				       av[i]);
263 			}
264 			close(use_fd);
265 		} else {
266 			printf("hammer2: pfs_delete(%s): FAILED\n",
267 			       av[i]);
268 			ecode = 1;
269 		}
270 	}
271 	if (mnts)
272 		put_hammer2_mounts(nmnts, mnts);
273 	return (ecode);
274 }
275