]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/storage/rbd.c
secure coding: #2 strcpy => strlcpy
[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 #ifndef HAVE_STRLCPY
38 #include "include/strlcpy.h"
39 #endif
40
41 lxc_log_define(rbd, lxc);
42
43 struct rbd_args {
44 const char *osd_pool_name;
45 const char *rbd_name;
46 const char *size;
47 };
48
49 int rbd_create_wrapper(void *data)
50 {
51 struct rbd_args *args = data;
52
53 execlp("rbd", "rbd", "create", "--pool", args->osd_pool_name,
54 args->rbd_name, "--size", args->size, (char *)NULL);
55
56 return -1;
57 }
58
59 int rbd_map_wrapper(void *data)
60 {
61 struct rbd_args *args = data;
62
63 execlp("rbd", "rbd", "map", "--pool", args->osd_pool_name,
64 args->rbd_name, (char *)NULL);
65
66 return -1;
67 }
68
69 int rbd_unmap_wrapper(void *data)
70 {
71 struct rbd_args *args = data;
72
73 execlp("rbd", "rbd", "unmap", args->rbd_name, (char *)NULL);
74
75 return -1;
76 }
77
78 int rbd_delete_wrapper(void *data)
79 {
80 struct rbd_args *args = data;
81
82 execlp("rbd", "rbd", "rm", args->rbd_name, (char *)NULL);
83
84 return -1;
85 }
86
87 int rbd_clonepaths(struct lxc_storage *orig, struct lxc_storage *new,
88 const char *oldname, const char *cname, const char *oldpath,
89 const char *lxcpath, int snap, uint64_t newsize,
90 struct lxc_conf *conf)
91 {
92 ERROR("rbd clonepaths not implemented");
93 return -1;
94 }
95
96 int rbd_create(struct lxc_storage *bdev, const char *dest, const char *n,
97 struct bdev_specs *specs)
98 {
99 const char *rbdpool, *fstype;
100 uint64_t size;
101 int ret, len;
102 char sz[24];
103 const char *cmd_args[2];
104 char cmd_output[MAXPATHLEN];
105 const char *rbdname = n;
106 struct rbd_args args = {0};
107
108 if (!specs)
109 return -1;
110
111 rbdpool = specs->rbd.rbdpool;
112 if (!rbdpool)
113 rbdpool = lxc_global_config_value("lxc.bdev.rbd.rbdpool");
114
115 if (specs->rbd.rbdname)
116 rbdname = specs->rbd.rbdname;
117
118 /* source device /dev/rbd/lxc/ctn */
119 len = strlen(rbdpool) + strlen(rbdname) + 4 + 11;
120 bdev->src = malloc(len);
121 if (!bdev->src) {
122 ERROR("Failed to allocate memory");
123 return -1;
124 }
125
126 ret = snprintf(bdev->src, len, "rbd:/dev/rbd/%s/%s", rbdpool, rbdname);
127 if (ret < 0 || ret >= len) {
128 ERROR("Failed to create string");
129 return -1;
130 }
131
132 /* fssize is in bytes */
133 size = specs->fssize;
134 if (!size)
135 size = DEFAULT_FS_SIZE;
136
137 /* in megabytes for rbd tool */
138 ret = snprintf(sz, 24, "%" PRIu64, size / 1024 / 1024);
139 if (ret < 0 || ret >= 24) {
140 ERROR("Failed to create string");
141 return -1;
142 }
143
144 args.osd_pool_name = rbdpool;
145 args.rbd_name = rbdname;
146 args.size = sz;
147 ret = run_command(cmd_output, sizeof(cmd_output), rbd_create_wrapper,
148 (void *)&args);
149 if (ret < 0) {
150 ERROR("Failed to create rbd storage volume \"%s\": %s", rbdname,
151 cmd_output);
152 return -1;
153 }
154
155 ret = run_command(cmd_output, sizeof(cmd_output), rbd_map_wrapper,
156 (void *)&args);
157 if (ret < 0) {
158 ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
159 cmd_output);
160 return -1;
161 }
162
163 fstype = specs->fstype;
164 if (!fstype)
165 fstype = DEFAULT_FSTYPE;
166
167 cmd_args[0] = fstype;
168 cmd_args[1] = lxc_storage_get_path(bdev->src, bdev->type);
169 ret = run_command(cmd_output, sizeof(cmd_output), do_mkfs_exec_wrapper,
170 (void *)cmd_args);
171 if (ret < 0) {
172 ERROR("Failed to map rbd storage volume \"%s\": %s", rbdname,
173 cmd_output);
174 return -1;
175 }
176
177 bdev->dest = strdup(dest);
178 if (!bdev->dest) {
179 ERROR("Failed to duplicate string \"%s\"", dest);
180 return -1;
181 }
182
183 ret = mkdir_p(bdev->dest, 0755);
184 if (ret < 0 && errno != EEXIST) {
185 ERROR("Failed to create directory \"%s\"", bdev->dest);
186 return -1;
187 }
188
189 TRACE("Created rbd storage volume \"%s\"", bdev->dest);
190 return 0;
191 }
192
193 int rbd_destroy(struct lxc_storage *orig)
194 {
195 int ret;
196 const char *src;
197 char *rbdfullname;
198 char cmd_output[MAXPATHLEN];
199 struct rbd_args args = {0};
200 size_t len;
201
202 src = lxc_storage_get_path(orig->src, orig->type);
203 if (file_exists(src)) {
204 args.rbd_name = src;
205 ret = run_command(cmd_output, sizeof(cmd_output),
206 rbd_unmap_wrapper, (void *)&args);
207 if (ret < 0) {
208 ERROR("Failed to map rbd storage volume \"%s\": %s",
209 src, cmd_output);
210 return -1;
211 }
212 }
213
214 len = strlen(src);
215 rbdfullname = alloca(len - 8);
216 (void)strlcpy(rbdfullname, &src[9], len - 8);
217 args.rbd_name = rbdfullname;
218
219 ret = run_command(cmd_output, sizeof(cmd_output),
220 rbd_delete_wrapper, (void *)&args);
221 if (ret < 0) {
222 ERROR("Failed to delete rbd storage volume \"%s\": %s",
223 rbdfullname, cmd_output);
224 return -1;
225 }
226
227 return 0;
228 }
229
230 bool rbd_detect(const char *path)
231 {
232 if (!strncmp(path, "rbd:", 4))
233 return true;
234
235 if (!strncmp(path, "/dev/rbd/", 9))
236 return true;
237
238 return false;
239 }
240
241 int rbd_mount(struct lxc_storage *bdev)
242 {
243 const char *src;
244
245 if (strcmp(bdev->type, "rbd"))
246 return -22;
247
248 if (!bdev->src || !bdev->dest)
249 return -22;
250
251 src = lxc_storage_get_path(bdev->src, bdev->type);
252 if (!file_exists(src)) {
253 /* If blkdev does not exist it should be mapped, because it is
254 * not persistent on reboot.
255 */
256 ERROR("Block device %s is not mapped.", bdev->src);
257 return -1;
258 }
259
260 return mount_unknown_fs(src, bdev->dest, bdev->mntopts);
261 }
262
263 int rbd_umount(struct lxc_storage *bdev)
264 {
265 if (strcmp(bdev->type, "rbd"))
266 return -22;
267
268 if (!bdev->src || !bdev->dest)
269 return -22;
270
271 return umount(bdev->dest);
272 }