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