]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/rbd.c
Merge pull request #1950 from brauner/2017-11-27/criu_fixes
[mirror_lxc.git] / src / lxc / storage / rbd.c
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 */
23
24 #define _GNU_SOURCE
25 #define __STDC_FORMAT_MACROS /* Required for PRIu64 to work. */
26 #include <inttypes.h> /* Required for PRIu64 to work. */
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "log.h"
33 #include "storage.h"
34 #include "storage_utils.h"
35 #include "utils.h"
36
37 lxc_log_define(rbd, lxc);
38
39 struct rbd_args {
40 const char *osd_pool_name;
41 const char *rbd_name;
42 const char *size;
43 };
44
45 int rbd_create_wrapper(void *data)
46 {
47 struct rbd_args *args = data;
48
49 execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name,
50 args->rbd_name, "--size", args->size, (char *)NULL);
51
52 return -1;
53 }
54
55 int rbd_map_wrapper(void *data)
56 {
57 struct rbd_args *args = data;
58
59 execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name,
60 args->rbd_name, (char *)NULL);
61
62 return -1;
63 }
64
65 int rbd_unmap_wrapper(void *data)
66 {
67 struct rbd_args *args = data;
68
69 execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL);
70
71 return -1;
72 }
73
74 int rbd_delete_wrapper(void *data)
75 {
76 struct rbd_args *args = data;
77
78 execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL);
79
80 return -1;
81 }
82
83 int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
84 const char *oldname, const char *cname, const char *oldpath,
85 const char *lxcpath, int snap, uint64_t newsize,
86 struct lxc_conf *conf)
87 {
88 ERROR("rbd clonepaths not implemented");
89 return -1;
90 }
91
92 int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
93 struct bdev_specs *specs)
94 {
95 const char *rbdpool, *fstype;
96 uint64_t size;
97 int ret, len;
98 char sz[24];
99 const char *cmd_args[2];
100 char cmd_output[MAXPATHLEN];
101 const char *rbdname = n;
102 struct rbd_args args = {0};
103
104 if (!specs)
105 return -1;
106
107 rbdpool = specs->rbd.rbdpool;
108 if (!rbdpool)
109 rbdpool = lxc_global_config_value("lxc.bdev.rbd.rbdpool");
110
111 if (specs->rbd.rbdname)
112 rbdname = specs->rbd.rbdname;
113
114 /* source device /dev/rbd/lxc/ctn */
115 len = strlen(rbdpool) + strlen(rbdname) + 4 + 11;
116 bdev->src = malloc(len);
117 if (!bdev->src) {
118 ERROR("Failed to allocate memory");
119 return -1;
120 }
121
122 ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname);
123 if (ret < 0 || ret >= len) {
124 ERROR("Failed to create string");
125 return -1;
126 }
127
128 /* fssize is in bytes */
129 size = specs->fssize;
130 if (!size)
131 size = DEFAULT_FS_SIZE;
132
133 /* in megabytes for rbd tool */
134 ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
135 if (ret < 0 || ret >= 24) {
136 ERROR("Failed to create string");
137 return -1;
138 }
139
140 args.osd_pool_name = rbdpool;
141 args.rbd_name = rbdname;
142 args.size = sz;
143 ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper,
144 (void *)&args);
145 if (ret < 0) {
146 ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname,
147 cmd_output);
148 return -1;
149 }
150
151 ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper,
152 (void *)&args);
153 if (ret < 0) {
154 ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
155 cmd_output);
156 return -1;
157 }
158
159 fstype = specs->fstype;
160 if (!fstype)
161 fstype = DEFAULT_FSTYPE;
162
163 cmd_args[0] = fstype;
164 cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
165 ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
166 (void *)cmd_args);
167 if (ret < 0) {
168 ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
169 cmd_output);
170 return -1;
171 }
172
173 bdev->dest = strdup(dest);
174 if (!bdev->dest) {
175 ERROR("Failed to duplicate string \"%s\"", dest);
176 return -1;
177 }
178
179 ret = mkdir_p(bdev->dest, 0755);
180 if (ret < 0 && errno != EEXIST) {
181 ERROR("Failed to create directory \"%s\"", bdev->dest);
182 return -1;
183 }
184
185 TRACE("Created rbd storage volume \"%s\"", bdev->dest);
186 return 0;
187 }
188
189 int rbd_destroy(struct lxc_storage *orig)
190 {
191 int ret;
192 const char *src;
193 char *rbdfullname;
194 char cmd_output[MAXPATHLEN];
195 struct rbd_args args = {0};
196
197 src = lxc_storage_get_path(orig->src, orig->type);
198 if (file_exists(src)) {
199 args.rbd_name = src;
200 ret = run_command(cmd_output, sizeof(cmd_output),
201 rbd_unmap_wrapper, (void *)&args);
202 if (ret < 0) {
203 ERROR("Failed to map rbd storage volume \"%s\": %s",
204 src, cmd_output);
205 return -1;
206 }
207 }
208
209 rbdfullname = alloca(strlen(src) - 8);
210 strcpy(rbdfullname, &src[9]);
211 args.rbd_name = rbdfullname;
212 ret = run_command(cmd_output, sizeof(cmd_output),
213 rbd_delete_wrapper, (void *)&args);
214 if (ret < 0) {
215 ERROR("Failed to delete rbd storage volume \"%s\": %s",
216 rbdfullname, cmd_output);
217 return -1;
218 }
219
220 return 0;
221 }
222
223 bool rbd_detect(const char *path)
224 {
225 if (!strncmp(path, "rbd:", 4))
226 return true;
227
228 if (!strncmp(path, "/dev/rbd/", 9))
229 return true;
230
231 return false;
232 }
233
234 int rbd_mount(struct lxc_storage *bdev)
235 {
236 const char *src;
237
238 if (strcmp(bdev->type, "rbd"))
239 return -22;
240
241 if (!bdev->src || !bdev->dest)
242 return -22;
243
244 src = lxc_storage_get_path(bdev->src, bdev->type);
245 if (!file_exists(src)) {
246 /* If blkdev does not exist it should be mapped, because it is
247 * not persistent on reboot.
248 */
249 ERROR("Block device %s is not mapped.", bdev->src);
250 return -1;
251 }
252
253 return mount_unknown_fs(src, bdev->dest, bdev->mntopts);
254 }
255
256 int rbd_umount(struct lxc_storage *bdev)
257 {
258 if (strcmp(bdev->type, "rbd"))
259 return -22;
260
261 if (!bdev->src || !bdev->dest)
262 return -22;
263
264 return umount(bdev->dest);
265 }