4ed799d231a72dce3902127dc2ca3244f7ef2cb1
[platform/upstream/btrfs-progs.git] / btrfs-vol.c
1 /*
2  * Copyright (C) 2007 Oracle.  All rights reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public
6  * License v2 as published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11  * General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public
14  * License along with this program; if not, write to the
15  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16  * Boston, MA 021110-1307, USA.
17  */
18
19 #define _GNU_SOURCE
20 #ifndef __CHECKER__
21 #include <sys/ioctl.h>
22 #include <sys/mount.h>
23 #include "ioctl.h"
24 #endif
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <getopt.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
32 #include <dirent.h>
33 #include <uuid/uuid.h>
34 #include "kerncompat.h"
35 #include "ctree.h"
36 #include "transaction.h"
37 #include "utils.h"
38 #include "volumes.h"
39
40 #ifdef __CHECKER__
41 #define BLKGETSIZE64 0
42 #define BTRFS_IOC_SNAP_CREATE 0
43 #define BTRFS_IOC_ADD_DEV 0
44 #define BTRFS_IOC_RM_DEV 0
45 #define BTRFS_VOL_NAME_MAX 255
46 struct btrfs_ioctl_vol_args { char name[BTRFS_VOL_NAME_MAX]; };
47 static inline int ioctl(int fd, int define, void *arg) { return 0; }
48 #endif
49
50 static void print_usage(void)
51 {
52         fprintf(stderr, "usage: btrfs-vol [options] mount_point\n");
53         fprintf(stderr, "\t-a device add one device\n");
54         fprintf(stderr, "\t-b balance chunks across all devices\n");
55         fprintf(stderr, "\t-r device remove one device\n");
56         exit(1);
57 }
58
59 static struct option long_options[] = {
60         /* { "byte-count", 1, NULL, 'b' }, */
61         { "add", 1, NULL, 'a' },
62         { "balance", 0, NULL, 'b' },
63         { "remove", 1, NULL, 'r' },
64         { 0, 0, 0, 0}
65 };
66
67 int main(int ac, char **av)
68 {
69         struct stat st;
70         char *device = NULL;
71         char *mnt = NULL;
72         int ret;
73         int option_index = 0;
74         int cmd = 0;
75         int fd;
76         int devfd = 0;
77         DIR *dirstream;
78         struct btrfs_ioctl_vol_args args;
79         u64 dev_block_count = 0;
80
81         while(1) {
82                 int c;
83                 c = getopt_long(ac, av, "a:br:", long_options,
84                                 &option_index);
85                 if (c < 0)
86                         break;
87                 switch(c) {
88                         case 'a':
89                                 device = strdup(optarg);
90                                 cmd = BTRFS_IOC_ADD_DEV;
91                                 break;
92                         case 'b':
93                                 cmd = BTRFS_IOC_BALANCE;
94                                 break;
95                         case 'r':
96                                 device = strdup(optarg);
97                                 cmd = BTRFS_IOC_RM_DEV;
98                                 break;
99                         default:
100                                 print_usage();
101                 }
102         }
103         ac = ac - optind;
104         if (ac == 0)
105                 print_usage();
106         mnt = av[optind];
107
108         if (device && strcmp(device, "missing") == 0 &&
109             cmd == BTRFS_IOC_RM_DEV) {
110                 fprintf(stderr, "removing missing devices from %s\n", mnt);
111         } else if (cmd != BTRFS_IOC_BALANCE) {
112                 if (cmd == BTRFS_IOC_ADD_DEV) {
113                         ret = check_mounted(device);
114                         if (ret < 0) {
115                                 fprintf(stderr,
116                                         "error checking %s mount status\n",
117                                         device);
118                                 exit(1);
119                         }
120                         if (ret == 1) {
121                                 fprintf(stderr, "%s is mounted\n", device);
122                                 exit(1);
123                         }
124                 }
125                 devfd = open(device, O_RDWR);
126                 if (devfd < 0) {
127                         fprintf(stderr, "Unable to open device %s\n", device);
128                         exit(1);
129                 }
130                 ret = fstat(devfd, &st);
131                 if (ret) {
132                         fprintf(stderr, "Unable to stat %s\n", device);
133                         exit(1);
134                 }
135                 if (!S_ISBLK(st.st_mode)) {
136                         fprintf(stderr, "%s is not a block device\n", device);
137                         exit(1);
138                 }
139         }
140         dirstream = opendir(mnt);
141         if (!dirstream) {
142                 fprintf(stderr, "Unable to open directory %s\n", mnt);
143                 exit(1);
144         }
145         if (cmd == BTRFS_IOC_ADD_DEV) {
146                 ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count);
147                 if (ret) {
148                         fprintf(stderr, "Unable to init %s\n", device);
149                         exit(1);
150                 }
151         }
152         fd = dirfd(dirstream);
153         if (device)
154                 strcpy(args.name, device);
155         else
156                 args.name[0] = '\0';
157
158         ret = ioctl(fd, cmd, &args);
159         printf("ioctl returns %d\n", ret);
160         return 0;
161 }
162