btrfsck: add code to rebuild extent records
[platform/upstream/btrfs-progs.git] / cmds-device.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public
4  * License v2 as published by the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
9  * General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public
12  * License along with this program; if not, write to the
13  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
14  * Boston, MA 021110-1307, USA.
15  */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <sys/ioctl.h>
23 #include <errno.h>
24 #include <sys/stat.h>
25
26 #include "kerncompat.h"
27 #include "ctree.h"
28 #include "ioctl.h"
29 #include "utils.h"
30
31 #include "commands.h"
32
33 /* FIXME - imported cruft, fix sparse errors and warnings */
34 #ifdef __CHECKER__
35 #define BLKGETSIZE64 0
36 #define BTRFS_IOC_SNAP_CREATE_V2 0
37 #define BTRFS_VOL_NAME_MAX 255
38 struct btrfs_ioctl_vol_args { char name[BTRFS_VOL_NAME_MAX]; };
39 static inline int ioctl(int fd, int define, void *arg) { return 0; }
40 #endif
41
42 static const char device_cmd_group_usage[] =
43         "btrfs device <command> [<args>]";
44
45 static const char * const cmd_add_dev_usage[] = {
46         "btrfs device add <device> [<device>...] <path>",
47         "Add a device to a filesystem",
48         NULL
49 };
50
51 static int cmd_add_dev(int argc, char **argv)
52 {
53         char    *mntpnt;
54         int     i, fdmnt, ret=0, e;
55
56         if (check_argc_min(argc, 3))
57                 usage(cmd_add_dev_usage);
58
59         mntpnt = argv[argc - 1];
60
61         fdmnt = open_file_or_dir(mntpnt);
62         if (fdmnt < 0) {
63                 fprintf(stderr, "ERROR: can't access to '%s'\n", mntpnt);
64                 return 12;
65         }
66
67         for (i = 1; i < argc - 1; i++ ){
68                 struct btrfs_ioctl_vol_args ioctl_args;
69                 int     devfd, res;
70                 u64 dev_block_count = 0;
71                 struct stat st;
72                 int mixed = 0;
73
74                 res = check_mounted(argv[i]);
75                 if (res < 0) {
76                         fprintf(stderr, "error checking %s mount status\n",
77                                 argv[i]);
78                         ret++;
79                         continue;
80                 }
81                 if (res == 1) {
82                         fprintf(stderr, "%s is mounted\n", argv[i]);
83                         ret++;
84                         continue;
85                 }
86
87                 devfd = open(argv[i], O_RDWR);
88                 if (!devfd) {
89                         fprintf(stderr, "ERROR: Unable to open device '%s'\n", argv[i]);
90                         close(devfd);
91                         ret++;
92                         continue;
93                 }
94                 res = fstat(devfd, &st);
95                 if (res) {
96                         fprintf(stderr, "ERROR: Unable to stat '%s'\n", argv[i]);
97                         close(devfd);
98                         ret++;
99                         continue;
100                 }
101                 if (!S_ISBLK(st.st_mode)) {
102                         fprintf(stderr, "ERROR: '%s' is not a block device\n", argv[i]);
103                         close(devfd);
104                         ret++;
105                         continue;
106                 }
107
108                 res = btrfs_prepare_device(devfd, argv[i], 1, &dev_block_count, &mixed);
109                 if (res) {
110                         fprintf(stderr, "ERROR: Unable to init '%s'\n", argv[i]);
111                         close(devfd);
112                         ret++;
113                         continue;
114                 }
115                 close(devfd);
116
117                 strncpy(ioctl_args.name, argv[i], BTRFS_PATH_NAME_MAX);
118                 res = ioctl(fdmnt, BTRFS_IOC_ADD_DEV, &ioctl_args);
119                 e = errno;
120                 if(res<0){
121                         fprintf(stderr, "ERROR: error adding the device '%s' - %s\n",
122                                 argv[i], strerror(e));
123                         ret++;
124                 }
125
126         }
127
128         close(fdmnt);
129         if (ret)
130                 return ret+20;
131         else
132                 return 0;
133 }
134
135 static const char * const cmd_rm_dev_usage[] = {
136         "btrfs device delete <device> [<device>...] <path>",
137         "Remove a device from a filesystem",
138         NULL
139 };
140
141 static int cmd_rm_dev(int argc, char **argv)
142 {
143         char    *mntpnt;
144         int     i, fdmnt, ret=0, e;
145
146         if (check_argc_min(argc, 3))
147                 usage(cmd_rm_dev_usage);
148
149         mntpnt = argv[argc - 1];
150
151         fdmnt = open_file_or_dir(mntpnt);
152         if (fdmnt < 0) {
153                 fprintf(stderr, "ERROR: can't access to '%s'\n", mntpnt);
154                 return 12;
155         }
156
157         for(i=1 ; i < argc - 1; i++ ){
158                 struct  btrfs_ioctl_vol_args arg;
159                 int     res;
160
161                 strncpy(arg.name, argv[i], BTRFS_PATH_NAME_MAX);
162                 res = ioctl(fdmnt, BTRFS_IOC_RM_DEV, &arg);
163                 e = errno;
164                 if(res<0){
165                         fprintf(stderr, "ERROR: error removing the device '%s' - %s\n",
166                                 argv[i], strerror(e));
167                         ret++;
168                 }
169         }
170
171         close(fdmnt);
172         if( ret)
173                 return ret+20;
174         else
175                 return 0;
176 }
177
178 static const char * const cmd_scan_dev_usage[] = {
179         "btrfs device scan [<device>...]",
180         "Scan devices for a btrfs filesystem",
181         NULL
182 };
183
184 static int cmd_scan_dev(int argc, char **argv)
185 {
186         int     i, fd, e;
187         int     checklist = 1;
188         int     devstart = 1;
189
190         if( argc > 1 && !strcmp(argv[1],"--all-devices")){
191                 if (check_argc_max(argc, 2))
192                         usage(cmd_scan_dev_usage);
193
194                 checklist = 0;
195                 devstart += 1;
196         }
197
198         if(argc<=devstart){
199
200                 int ret;
201
202                 printf("Scanning for Btrfs filesystems\n");
203                 if(checklist)
204                         ret = btrfs_scan_block_devices(1);
205                 else
206                         ret = btrfs_scan_one_dir("/dev", 1);
207                 if (ret){
208                         fprintf(stderr, "ERROR: error %d while scanning\n", ret);
209                         return 18;
210                 }
211                 return 0;
212         }
213
214         fd = open("/dev/btrfs-control", O_RDWR);
215         if (fd < 0) {
216                 perror("failed to open /dev/btrfs-control");
217                 return 10;
218         }
219
220         for( i = devstart ; i < argc ; i++ ){
221                 struct btrfs_ioctl_vol_args args;
222                 int ret;
223
224                 printf("Scanning for Btrfs filesystems in '%s'\n", argv[i]);
225
226                 strncpy(args.name, argv[i], BTRFS_PATH_NAME_MAX);
227                 /*
228                  * FIXME: which are the error code returned by this ioctl ?
229                  * it seems that is impossible to understand if there no is
230                  * a btrfs filesystem from an I/O error !!!
231                  */
232                 ret = ioctl(fd, BTRFS_IOC_SCAN_DEV, &args);
233                 e = errno;
234
235                 if( ret < 0 ){
236                         close(fd);
237                         fprintf(stderr, "ERROR: unable to scan the device '%s' - %s\n",
238                                 argv[i], strerror(e));
239                         return 11;
240                 }
241         }
242
243         close(fd);
244         return 0;
245 }
246
247 const struct cmd_group device_cmd_group = {
248         device_cmd_group_usage, NULL, {
249                 { "add", cmd_add_dev, cmd_add_dev_usage, NULL, 0 },
250                 { "delete", cmd_rm_dev, cmd_rm_dev_usage, NULL, 0 },
251                 { "scan", cmd_scan_dev, cmd_scan_dev_usage, NULL, 0 },
252                 { 0, 0, 0, 0, 0 }
253         }
254 };
255
256 int cmd_device(int argc, char **argv)
257 {
258         return handle_command_group(&device_cmd_group, argc, argv);
259 }