drm/linux: Add list_for_each_entry_safe_reverse()
[dragonfly.git] / sbin / hammer / cmd_volume.c
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
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
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
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
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 }