xref: /dragonfly/sbin/hammer/cmd_volume.c (revision 1ec4d15f586ac3193c2add8ec1c5001e2967bfc8)
1 /*
2  * Copyright (c) 2009 The DragonFly Project.  All rights reserved.
3  *
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com> and
6  * Michael Neumann <mneumann@ntecs.de>
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 /*
37  * Volume operations:
38  *
39  *   - volume-add: Add new volume to HAMMER filesystem
40  *   - volume-del: Remove volume from HAMMER filesystem
41  *   - volume-list: List volumes making up a HAMMER filesystem
42  *   - volume-blkdevs: List volumes making up a HAMMER filesystem
43  *     in blkdevs format
44  */
45 
46 #include "hammer.h"
47 
48 /*
49  * volume-add <device> <filesystem>
50  */
51 void
hammer_cmd_volume_add(char ** av,int ac)52 hammer_cmd_volume_add(char **av, int ac)
53 {
54           struct hammer_ioc_volume ioc;
55           volume_info_t volume;
56           int fd;
57           const char *device, *filesystem;
58 
59           if (ac != 2) {
60                     errx(1, "hammer volume-add <device> <filesystem>");
61                     /* not reached */
62           }
63 
64           device = av[0];
65           filesystem = av[1];
66 
67         fd = open(filesystem, O_RDONLY);
68           if (fd < 0) {
69                     err(1, "hammer volume-add: unable to access %s", filesystem);
70                     /* not reached */
71           }
72 
73           /*
74            * Initialize and check the device
75            */
76           volume = init_volume(device, O_RDONLY, -1);
77           assert(volume->vol_no == -1);
78           if (is_regfile(volume)) {
79                     errx(1, "Not a block device: %s", device);
80                     /* not reached */
81           }
82           close(volume->fd);
83 
84           /*
85            * volume-add ioctl
86            */
87           bzero(&ioc, sizeof(ioc));
88           strncpy(ioc.device_name, device, sizeof(ioc.device_name) - 1);
89           ioc.vol_size = volume->size;
90           ioc.boot_area_size = init_boot_area_size(0, ioc.vol_size);
91           ioc.memory_log_size = init_memory_log_size(0, ioc.vol_size);
92 
93           if (ioctl(fd, HAMMERIOC_ADD_VOLUME, &ioc) < 0) {
94                     err(1, "hammer volume-add ioctl");
95                     /* not reached */
96           }
97 
98           close(fd);
99           hammer_cmd_volume_list(av + 1, ac - 1);
100 }
101 
102 /*
103  * volume-del <device> <filesystem>
104  */
105 void
hammer_cmd_volume_del(char ** av,int ac)106 hammer_cmd_volume_del(char **av, int ac)
107 {
108           struct hammer_ioc_volume ioc;
109           int fd, retried = 0;
110           const char *device, *filesystem;
111 
112           if (ac != 2) {
113                     errx(1, "hammer volume-del <device> <filesystem>");
114                     /* not reached */
115           }
116 
117           device = av[0];
118           filesystem = av[1];
119 
120         fd = open(filesystem, O_RDONLY);
121           if (fd < 0) {
122                     err(1, "hammer volume-del: unable to access %s", filesystem);
123                     /* not reached */
124           }
125 
126           /*
127            * volume-del ioctl
128            */
129           bzero(&ioc, sizeof(ioc));
130           strncpy(ioc.device_name, device, sizeof(ioc.device_name) - 1);
131           if (ForceOpt)
132                     ioc.flag |= HAMMER_IOC_VOLUME_REBLOCK;
133 retry:
134           if (ioctl(fd, HAMMERIOC_DEL_VOLUME, &ioc) < 0) {
135                     if ((errno == ENOTEMPTY) && (retried++ == 0)) {
136                               printf("%s is not empty, ", device);
137                               printf("do you want to reblock %s? [y/n] ", device);
138                               fflush(stdout);
139                               if (getyn() == 1) {
140                                         ioc.flag |= HAMMER_IOC_VOLUME_REBLOCK;
141                                         goto retry;
142                               }
143                     }
144                     err(1, "hammer volume-del ioctl");
145                     /* not reached */
146           }
147 
148           close(fd);
149           hammer_cmd_volume_list(av + 1, ac - 1);
150 }
151 
152 /*
153  * volume-list <filesystem>
154  */
155 void
hammer_cmd_volume_list(char ** av,int ac)156 hammer_cmd_volume_list(char **av, int ac)
157 {
158           struct hammer_ioc_volume_list ioc;
159           char *device_name;
160           int vol_no, i;
161 
162           if (ac < 1) {
163                     errx(1, "hammer volume-list <filesystem>");
164                     /* not reached */
165           }
166 
167           if (hammer_fs_to_vol(av[0], &ioc) == -1) {
168                     errx(1, "hammer volume-list: failed");
169                     /* not reached */
170           }
171 
172           for (i = 0; i < ioc.nvols; i++) {
173                     device_name = ioc.vols[i].device_name;
174                     vol_no = ioc.vols[i].vol_no;
175                     if (VerboseOpt) {
176                               printf("%d\t%s%s\n", vol_no, device_name,
177                                         (vol_no == HAMMER_ROOT_VOLNO ?
178                                         " (Root Volume)" : ""));
179                     } else {
180                               printf("%s\n", device_name);
181                     }
182           }
183 
184           free(ioc.vols);
185 }
186 
187 /*
188  * volume-blkdevs <filesystem>
189  */
190 void
hammer_cmd_volume_blkdevs(char ** av,int ac)191 hammer_cmd_volume_blkdevs(char **av, int ac)
192 {
193           struct hammer_ioc_volume_list ioc;
194           int i;
195 
196           if (ac < 1) {
197                     errx(1, "hammer volume-blkdevs <filesystem>");
198                     /* not reached */
199           }
200 
201           if (hammer_fs_to_vol(av[0], &ioc) == -1) {
202                     errx(1, "hammer volume-list: failed");
203                     /* not reached */
204           }
205 
206           for (i = 0; i < ioc.nvols; i++) {
207                     printf("%s", ioc.vols[i].device_name);
208                     if (i != ioc.nvols - 1)
209                               printf(":");
210           }
211           printf("\n");
212 
213           free(ioc.vols);
214 }
215