1 /*
2 * storage_util.c: helper functions for the storage driver
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library. If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19 #include <config.h>
20
21 #include <sys/types.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <sys/statvfs.h>
26 #include <sys/param.h>
27 #include <dirent.h>
28 #ifdef __linux__
29 # include <sys/ioctl.h>
30 # include <linux/fs.h>
31 # define default_mount_opts "nodev,nosuid,noexec"
32 #elif defined(__FreeBSD__)
33 # define default_mount_opts "nosuid,noexec"
34 #else
35 # define default_mount_opts ""
36 #endif
37
38 #if WITH_BLKID
39 # include <blkid.h>
40 #endif
41
42 #if WITH_SELINUX
43 # include <selinux/selinux.h>
44 #endif
45
46 #ifdef FICLONE
47 # define REFLINK_IOC_CLONE FICLONE
48 #elif WITH_LINUX_BTRFS_H
49 # include <linux/btrfs.h>
50 # define REFLINK_IOC_CLONE BTRFS_IOC_CLONE
51 #elif WITH_XFS_XFS_H
52 # include <xfs/xfs.h>
53 # define REFLINK_IOC_CLONE XFS_IOC_CLONE
54 #endif
55
56 #include "datatypes.h"
57 #include "virerror.h"
58 #include "viralloc.h"
59 #include "internal.h"
60 #include "secret_conf.h"
61 #include "virsecret.h"
62 #include "vircrypto.h"
63 #include "viruuid.h"
64 #include "virstoragefile.h"
65 #include "storage_file_probe.h"
66 #include "storage_util.h"
67 #include "storage_source.h"
68 #include "storage_source_conf.h"
69 #include "virlog.h"
70 #include "virfile.h"
71 #include "viridentity.h"
72 #include "virjson.h"
73 #include "virqemu.h"
74 #include "virstring.h"
75 #include "virxml.h"
76 #include "virfdstream.h"
77 #include "virutil.h"
78 #include "virsecureerase.h"
79
80 #define VIR_FROM_THIS VIR_FROM_STORAGE
81
82 VIR_LOG_INIT("storage.storage_util");
83
84 #ifndef S_IRWXUGO
85 # define S_IRWXUGO (S_IRWXU | S_IRWXG | S_IRWXO)
86 #endif
87
88 /* virStorageBackendNamespaceInit:
89 * @poolType: virStoragePoolType
90 * @xmlns: Storage Pool specific namespace callback methods
91 *
92 * To be called during storage backend registration to configure the
93 * Storage Pool XML Namespace based on the backend's needs.
94 */
95 int
virStorageBackendNamespaceInit(int poolType,virXMLNamespace * xmlns)96 virStorageBackendNamespaceInit(int poolType,
97 virXMLNamespace *xmlns)
98 {
99 return virStoragePoolOptionsPoolTypeSetXMLNamespace(poolType, xmlns);
100 }
101
102
103 #define READ_BLOCK_SIZE_DEFAULT (1024 * 1024)
104 #define WRITE_BLOCK_SIZE_DEFAULT (4 * 1024)
105
106 /*
107 * Perform the O(1) btrfs clone operation, if possible.
108 * Upon success, return 0. Otherwise, return -1 and set errno.
109 */
110 #ifdef REFLINK_IOC_CLONE
111 static inline int
reflinkCloneFile(int dest_fd,int src_fd)112 reflinkCloneFile(int dest_fd, int src_fd)
113 {
114 return ioctl(dest_fd, REFLINK_IOC_CLONE, src_fd);
115 }
116 #else
117 static inline int
reflinkCloneFile(int dest_fd G_GNUC_UNUSED,int src_fd G_GNUC_UNUSED)118 reflinkCloneFile(int dest_fd G_GNUC_UNUSED,
119 int src_fd G_GNUC_UNUSED)
120 {
121 errno = ENOTSUP;
122 return -1;
123 }
124 #endif
125
126
127 static int ATTRIBUTE_NONNULL(2)
virStorageBackendCopyToFD(virStorageVolDef * vol,virStorageVolDef * inputvol,int fd,unsigned long long * total,bool want_sparse,bool reflink_copy)128 virStorageBackendCopyToFD(virStorageVolDef *vol,
129 virStorageVolDef *inputvol,
130 int fd,
131 unsigned long long *total,
132 bool want_sparse,
133 bool reflink_copy)
134 {
135 int amtread = -1;
136 size_t rbytes = READ_BLOCK_SIZE_DEFAULT;
137 int wbytes = 0;
138 int interval;
139 struct stat st;
140 g_autofree char *zerobuf = NULL;
141 g_autofree char *buf = NULL;
142 VIR_AUTOCLOSE inputfd = -1;
143
144 if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
145 virReportSystemError(errno,
146 _("could not open input path '%s'"),
147 inputvol->target.path);
148 return -1;
149 }
150
151 #ifdef __linux__
152 if (ioctl(fd, BLKBSZGET, &wbytes) < 0)
153 wbytes = 0;
154 #endif
155 if ((wbytes == 0) && fstat(fd, &st) == 0)
156 wbytes = st.st_blksize;
157 if (wbytes < WRITE_BLOCK_SIZE_DEFAULT)
158 wbytes = WRITE_BLOCK_SIZE_DEFAULT;
159
160 zerobuf = g_new0(char, wbytes);
161
162 buf = g_new0(char, rbytes);
163
164 if (reflink_copy) {
165 if (reflinkCloneFile(fd, inputfd) < 0) {
166 virReportSystemError(errno,
167 _("failed to clone files from '%s'"),
168 inputvol->target.path);
169 return -1;
170 } else {
171 VIR_DEBUG("btrfs clone finished.");
172 return 0;
173 }
174 }
175
176 while (amtread != 0) {
177 int amtleft;
178
179 if (*total < rbytes)
180 rbytes = *total;
181
182 if ((amtread = saferead(inputfd, buf, rbytes)) < 0) {
183 virReportSystemError(errno,
184 _("failed reading from file '%s'"),
185 inputvol->target.path);
186 return -1;
187 }
188 *total -= amtread;
189
190 /* Loop over amt read in 512 byte increments, looking for sparse
191 * blocks */
192 amtleft = amtread;
193 do {
194 int offset = amtread - amtleft;
195 interval = ((wbytes > amtleft) ? amtleft : wbytes);
196
197 if (want_sparse && memcmp(buf+offset, zerobuf, interval) == 0) {
198 if (lseek(fd, interval, SEEK_CUR) < 0) {
199 virReportSystemError(errno,
200 _("cannot extend file '%s'"),
201 vol->target.path);
202 return -1;
203 }
204 } else if (safewrite(fd, buf+offset, interval) < 0) {
205 virReportSystemError(errno,
206 _("failed writing to file '%s'"),
207 vol->target.path);
208 return -1;
209
210 }
211 } while ((amtleft -= interval) > 0);
212 }
213
214 if (virFileDataSync(fd) < 0) {
215 virReportSystemError(errno, _("cannot sync data to file '%s'"),
216 vol->target.path);
217 return -1;
218 }
219
220 if (VIR_CLOSE(inputfd) < 0) {
221 virReportSystemError(errno,
222 _("cannot close file '%s'"),
223 inputvol->target.path);
224 return -1;
225 }
226
227 return 0;
228 }
229
230 static int
storageBackendCreateBlockFrom(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)231 storageBackendCreateBlockFrom(virStoragePoolObj *pool G_GNUC_UNUSED,
232 virStorageVolDef *vol,
233 virStorageVolDef *inputvol,
234 unsigned int flags)
235 {
236 unsigned long long remain;
237 struct stat st;
238 gid_t gid;
239 uid_t uid;
240 mode_t mode;
241 bool reflink_copy = false;
242 VIR_AUTOCLOSE fd = -1;
243
244 virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
245 VIR_STORAGE_VOL_CREATE_REFLINK,
246 -1);
247
248 if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
249 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
250 _("metadata preallocation is not supported for block "
251 "volumes"));
252 return -1;
253 }
254
255 if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
256 reflink_copy = true;
257
258 if ((fd = open(vol->target.path, O_RDWR)) < 0) {
259 virReportSystemError(errno,
260 _("cannot create path '%s'"),
261 vol->target.path);
262 return -1;
263 }
264
265 remain = vol->target.capacity;
266
267 if (inputvol) {
268 if (virStorageBackendCopyToFD(vol, inputvol, fd, &remain,
269 false, reflink_copy) < 0)
270 return -1;
271 }
272
273 if (fstat(fd, &st) == -1) {
274 virReportSystemError(errno, _("stat of '%s' failed"),
275 vol->target.path);
276 return -1;
277 }
278 uid = (vol->target.perms->uid != st.st_uid) ? vol->target.perms->uid
279 : (uid_t)-1;
280 gid = (vol->target.perms->gid != st.st_gid) ? vol->target.perms->gid
281 : (gid_t)-1;
282 if (((uid != (uid_t)-1) || (gid != (gid_t)-1))
283 && (fchown(fd, uid, gid) < 0)) {
284 virReportSystemError(errno,
285 _("cannot chown '%s' to (%u, %u)"),
286 vol->target.path, (unsigned int)uid,
287 (unsigned int)gid);
288 return -1;
289 }
290
291 mode = (vol->target.perms->mode == (mode_t)-1 ?
292 VIR_STORAGE_DEFAULT_VOL_PERM_MODE : vol->target.perms->mode);
293 if (fchmod(fd, mode) < 0) {
294 virReportSystemError(errno,
295 _("cannot set mode of '%s' to %04o"),
296 vol->target.path, mode);
297 return -1;
298 }
299 if (VIR_CLOSE(fd) < 0) {
300 virReportSystemError(errno,
301 _("cannot close file '%s'"),
302 vol->target.path);
303 return -1;
304 }
305
306 return 0;
307 }
308
309 static int
createRawFile(int fd,virStorageVolDef * vol,virStorageVolDef * inputvol,bool reflink_copy)310 createRawFile(int fd, virStorageVolDef *vol,
311 virStorageVolDef *inputvol,
312 bool reflink_copy)
313 {
314 bool need_alloc = true;
315 unsigned long long pos = 0;
316
317 /* If the new allocation is lower than the capacity of the original file,
318 * the cloned volume will be sparse */
319 if (inputvol &&
320 vol->target.allocation < inputvol->target.capacity)
321 need_alloc = false;
322
323 /* Seek to the final size, so the capacity is available upfront
324 * for progress reporting */
325 if (ftruncate(fd, vol->target.capacity) < 0) {
326 virReportSystemError(errno,
327 _("cannot extend file '%s'"),
328 vol->target.path);
329 return -1;
330 }
331
332 /* Avoid issues with older kernel's <linux/fs.h> namespace pollution. */
333 #if WITH_FALLOCATE - 0
334 /* Try to preallocate all requested disk space, but fall back to
335 * other methods if this fails with ENOSYS or EOPNOTSUPP. If allocation
336 * is 0 (or less than 0), then fallocate will fail with EINVAL.
337 * NOTE: do not use posix_fallocate; posix_fallocate falls back
338 * to writing zeroes block by block in case fallocate isn't
339 * available, and since we're going to copy data from another
340 * file it doesn't make sense to write the file twice. */
341 if (vol->target.allocation && need_alloc) {
342 if (fallocate(fd, 0, 0, vol->target.allocation) == 0) {
343 need_alloc = false;
344 } else if (errno != ENOSYS && errno != EOPNOTSUPP) {
345 virReportSystemError(errno,
346 _("cannot allocate %llu bytes in file '%s'"),
347 vol->target.allocation, vol->target.path);
348 return -1;
349 }
350 }
351 #endif
352
353 if (inputvol) {
354 unsigned long long remain = inputvol->target.capacity;
355 /* allow zero blocks to be skipped if we've requested sparse
356 * allocation (allocation < capacity) or we have already
357 * been able to allocate the required space. */
358 if (virStorageBackendCopyToFD(vol, inputvol, fd, &remain,
359 !need_alloc, reflink_copy) < 0)
360 return -1;
361
362 /* If the new allocation is greater than the original capacity,
363 * but fallocate failed, fill the rest with zeroes.
364 */
365 pos = inputvol->target.capacity - remain;
366 }
367
368 if (need_alloc && (vol->target.allocation - pos > 0)) {
369 if (safezero(fd, pos, vol->target.allocation - pos) < 0) {
370 virReportSystemError(errno, _("cannot fill file '%s'"),
371 vol->target.path);
372 return -1;
373 }
374 }
375
376 if (g_fsync(fd) < 0) {
377 virReportSystemError(errno, _("cannot sync data to file '%s'"),
378 vol->target.path);
379 return -1;
380 }
381
382 return 0;
383 }
384
385 static int
storageBackendCreateRaw(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)386 storageBackendCreateRaw(virStoragePoolObj *pool,
387 virStorageVolDef *vol,
388 virStorageVolDef *inputvol,
389 unsigned int flags)
390 {
391 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
392 int operation_flags;
393 bool reflink_copy = false;
394 mode_t open_mode = VIR_STORAGE_DEFAULT_VOL_PERM_MODE;
395 VIR_AUTOCLOSE fd = -1;
396
397 virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA |
398 VIR_STORAGE_VOL_CREATE_REFLINK,
399 -1);
400
401 if (flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA) {
402 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
403 _("metadata preallocation is not supported for raw "
404 "volumes"));
405 return -1;
406 }
407
408 if (virStorageSourceHasBacking(&vol->target)) {
409 virReportError(VIR_ERR_NO_SUPPORT, "%s",
410 _("backing storage not supported for raw volumes"));
411 return -1;
412 }
413
414 if (flags & VIR_STORAGE_VOL_CREATE_REFLINK)
415 reflink_copy = true;
416
417
418 if (vol->target.encryption) {
419 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
420 _("storage pool does not support encrypted volumes"));
421 return -1;
422 }
423
424 operation_flags = VIR_FILE_OPEN_FORCE_MODE | VIR_FILE_OPEN_FORCE_OWNER;
425 if (def->type == VIR_STORAGE_POOL_NETFS)
426 operation_flags |= VIR_FILE_OPEN_FORK;
427
428 if (vol->target.perms->mode != (mode_t)-1)
429 open_mode = vol->target.perms->mode;
430
431 if ((fd = virFileOpenAs(vol->target.path,
432 O_RDWR | O_CREAT | O_EXCL,
433 open_mode,
434 vol->target.perms->uid,
435 vol->target.perms->gid,
436 operation_flags)) < 0) {
437 virReportSystemError(-fd,
438 _("Failed to create file '%s'"),
439 vol->target.path);
440 return -1;
441 }
442
443 /* NB, COW flag can only be toggled when the file is zero-size,
444 * so must go before the createRawFile call allocates payload */
445 if (vol->target.nocow &&
446 virFileSetCOW(vol->target.path, VIR_TRISTATE_BOOL_NO) < 0)
447 goto error;
448
449 if (createRawFile(fd, vol, inputvol, reflink_copy) < 0) {
450 /* createRawFile already reported the exact error. */
451 goto error;
452 }
453
454 return 0;
455
456 error:
457 virFileRemove(vol->target.path,
458 vol->target.perms->uid,
459 vol->target.perms->gid);
460 return -1;
461 }
462
463
464 static int
virStorageBackendCreateExecCommand(virStoragePoolObj * pool,virStorageVolDef * vol,virCommand * cmd)465 virStorageBackendCreateExecCommand(virStoragePoolObj *pool,
466 virStorageVolDef *vol,
467 virCommand *cmd)
468 {
469 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
470 struct stat st;
471 gid_t gid;
472 uid_t uid;
473 mode_t mode = (vol->target.perms->mode == (mode_t)-1 ?
474 VIR_STORAGE_DEFAULT_VOL_PERM_MODE :
475 vol->target.perms->mode);
476 bool filecreated = false;
477 int ret = -1;
478
479 if ((def->type == VIR_STORAGE_POOL_NETFS)
480 && (((geteuid() == 0)
481 && (vol->target.perms->uid != (uid_t)-1)
482 && (vol->target.perms->uid != 0))
483 || ((vol->target.perms->gid != (gid_t)-1)
484 && (vol->target.perms->gid != getegid())))) {
485
486 virCommandSetUID(cmd, vol->target.perms->uid);
487 virCommandSetGID(cmd, vol->target.perms->gid);
488 virCommandSetUmask(cmd, S_IRWXUGO ^ mode);
489
490 if (virCommandRun(cmd, NULL) == 0) {
491 /* command was successfully run, check if the file was created */
492 if (stat(vol->target.path, &st) >= 0) {
493 filecreated = true;
494
495 /* seems qemu-img disregards umask and open/creates using 0644.
496 * If that doesn't match what we expect, then let's try to
497 * re-open the file and attempt to force the mode change.
498 */
499 if (mode != (st.st_mode & S_IRWXUGO)) {
500 VIR_AUTOCLOSE fd = -1;
501 int flags = VIR_FILE_OPEN_FORK | VIR_FILE_OPEN_FORCE_MODE;
502
503 if ((fd = virFileOpenAs(vol->target.path, O_RDWR, mode,
504 vol->target.perms->uid,
505 vol->target.perms->gid,
506 flags)) >= 0) {
507 /* Success - means we're good */
508 ret = 0;
509 goto cleanup;
510 }
511 }
512 }
513 }
514 }
515
516 if (!filecreated) {
517 /* don't change uid/gid/mode if we retry */
518 virCommandSetUID(cmd, -1);
519 virCommandSetGID(cmd, -1);
520 virCommandSetUmask(cmd, 0);
521
522 if (virCommandRun(cmd, NULL) < 0)
523 goto cleanup;
524 if (stat(vol->target.path, &st) < 0) {
525 virReportSystemError(errno,
526 _("failed to create %s"), vol->target.path);
527 goto cleanup;
528 }
529 filecreated = true;
530 }
531
532 uid = (vol->target.perms->uid != st.st_uid) ? vol->target.perms->uid
533 : (uid_t)-1;
534 gid = (vol->target.perms->gid != st.st_gid) ? vol->target.perms->gid
535 : (gid_t)-1;
536 if (((uid != (uid_t)-1) || (gid != (gid_t)-1))
537 && (chown(vol->target.path, uid, gid) < 0)) {
538 virReportSystemError(errno,
539 _("cannot chown %s to (%u, %u)"),
540 vol->target.path, (unsigned int)uid,
541 (unsigned int)gid);
542 goto cleanup;
543 }
544
545 if (mode != (st.st_mode & S_IRWXUGO) &&
546 chmod(vol->target.path, mode) < 0) {
547 virReportSystemError(errno,
548 _("cannot set mode of '%s' to %04o"),
549 vol->target.path, mode);
550 goto cleanup;
551 }
552
553 ret = 0;
554
555 cleanup:
556 if (ret < 0 && filecreated)
557 virFileRemove(vol->target.path, vol->target.perms->uid,
558 vol->target.perms->gid);
559 return ret;
560 }
561
562 /* Create ploop directory with ploop image and DiskDescriptor.xml
563 * if function fails to create image file the directory will be deleted.*/
564 static int
storageBackendCreatePloop(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)565 storageBackendCreatePloop(virStoragePoolObj *pool G_GNUC_UNUSED,
566 virStorageVolDef *vol,
567 virStorageVolDef *inputvol,
568 unsigned int flags)
569 {
570 int ret = -1;
571 g_autoptr(virCommand) cmd = NULL;
572 g_autofree char *create_tool = NULL;
573
574 virCheckFlags(0, -1);
575
576 if (inputvol && inputvol->target.format != VIR_STORAGE_FILE_PLOOP) {
577 virReportError(VIR_ERR_INTERNAL_ERROR,
578 _("unsupported input storage vol type %d"),
579 inputvol->target.format);
580 return -1;
581 }
582
583 if (vol->target.encryption) {
584 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
585 _("encrypted ploop volumes are not supported with "
586 "ploop init"));
587 return -1;
588 }
589
590 if (virStorageSourceHasBacking(&vol->target)) {
591 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
592 _("copy-on-write ploop volumes are not yet supported"));
593 return -1;
594 }
595
596 create_tool = virFindFileInPath("ploop");
597 if (!create_tool && !inputvol) {
598 virReportError(VIR_ERR_INTERNAL_ERROR,
599 "%s", _("unable to find ploop, please install "
600 "ploop tools"));
601 return -1;
602 }
603
604 if (!inputvol) {
605 if ((virDirCreate(vol->target.path,
606 (vol->target.perms->mode == (mode_t)-1 ?
607 VIR_STORAGE_DEFAULT_VOL_PERM_MODE:
608 vol->target.perms->mode),
609 vol->target.perms->uid,
610 vol->target.perms->gid,
611 0)) < 0) {
612 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
613 _("error creating directory for ploop volume"));
614 return -1;
615 }
616 cmd = virCommandNewArgList(create_tool, "init", "-s", NULL);
617 virCommandAddArgFormat(cmd, "%lluM", VIR_DIV_UP(vol->target.capacity,
618 (1024 * 1024)));
619 virCommandAddArgList(cmd, "-t", "ext4", NULL);
620 virCommandAddArgFormat(cmd, "%s/root.hds", vol->target.path);
621
622 } else {
623 vol->target.capacity = inputvol->target.capacity;
624 cmd = virCommandNewArgList("cp", "-r", inputvol->target.path,
625 vol->target.path, NULL);
626 }
627 ret = virCommandRun(cmd, NULL);
628 if (ret < 0)
629 virFileDeleteTree(vol->target.path);
630 return ret;
631 }
632
633
634 static int
storagePloopResize(virStorageVolDef * vol,unsigned long long capacity)635 storagePloopResize(virStorageVolDef *vol,
636 unsigned long long capacity)
637 {
638 g_autoptr(virCommand) cmd = NULL;
639 g_autofree char *resize_tool = NULL;
640
641 resize_tool = virFindFileInPath("ploop");
642 if (!resize_tool) {
643 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
644 _("unable to find ploop, please install ploop tools"));
645 return -1;
646 }
647 cmd = virCommandNewArgList(resize_tool, "resize", "-s", NULL);
648 virCommandAddArgFormat(cmd, "%lluM", VIR_DIV_UP(capacity, (1024 * 1024)));
649
650 virCommandAddArgFormat(cmd, "%s/DiskDescriptor.xml", vol->target.path);
651
652 return virCommandRun(cmd, NULL);
653 }
654
655
656 /* The _virStorageBackendQemuImgInfo separates the command line building from
657 * the volume definition so that qemuDomainSnapshotCreateInactiveExternal can
658 * use it without needing to deal with a volume.
659 */
660 struct _virStorageBackendQemuImgInfo {
661 int format;
662 const char *type;
663 const char *inputType;
664 const char *path;
665 unsigned long long size_arg;
666 unsigned long long allocation;
667 unsigned long long clusterSize;
668 bool encryption;
669 bool preallocate;
670 const char *compat;
671 virBitmap *features;
672 bool nocow;
673
674 const char *backingPath;
675 int backingFormat;
676
677 const char *inputPath;
678 const char *inputFormatStr;
679 int inputFormat;
680
681 char *secretAlias;
682 };
683
684
685 /**
686 * storageBackendBuildQemuImgEncriptionOpts:
687 * @buf: buffer to build the string into
688 * @encinfo: pointer to encryption info
689 * @alias: alias to use
690 *
691 * Generate the string for id=$alias and any encryption options for
692 * into the buffer.
693 *
694 * Important note, a trailing comma (",") is built into the return since
695 * it's expected other arguments are appended after the id=$alias string.
696 * So either turn something like:
697 *
698 * "key-secret=$alias,"
699 *
700 * or
701 * "key-secret=$alias,cipher-alg=twofish-256,cipher-mode=cbc,
702 * hash-alg=sha256,ivgen-alg=plain64,igven-hash-alg=sha256,"
703 *
704 */
705 static void
storageBackendBuildQemuImgEncriptionOpts(virBuffer * buf,int format,virStorageEncryptionInfoDef * encinfo,const char * alias)706 storageBackendBuildQemuImgEncriptionOpts(virBuffer *buf,
707 int format,
708 virStorageEncryptionInfoDef *encinfo,
709 const char *alias)
710 {
711 const char *encprefix;
712
713 if (format == VIR_STORAGE_FILE_QCOW2) {
714 virBufferAddLit(buf, "encrypt.format=luks,");
715 encprefix = "encrypt.";
716 } else {
717 encprefix = "";
718 }
719
720 virBufferAsprintf(buf, "%skey-secret=%s,", encprefix, alias);
721
722 if (!encinfo->cipher_name)
723 return;
724
725 virBufferAsprintf(buf, "%scipher-alg=", encprefix);
726 virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_name);
727 virBufferAsprintf(buf, "-%u,", encinfo->cipher_size);
728 if (encinfo->cipher_mode) {
729 virBufferAsprintf(buf, "%scipher-mode=", encprefix);
730 virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_mode);
731 virBufferAddLit(buf, ",");
732 }
733 if (encinfo->cipher_hash) {
734 virBufferAsprintf(buf, "%shash-alg=", encprefix);
735 virQEMUBuildBufferEscapeComma(buf, encinfo->cipher_hash);
736 virBufferAddLit(buf, ",");
737 }
738 if (!encinfo->ivgen_name)
739 return;
740
741 virBufferAsprintf(buf, "%sivgen-alg=", encprefix);
742 virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_name);
743 virBufferAddLit(buf, ",");
744
745 if (encinfo->ivgen_hash) {
746 virBufferAsprintf(buf, "%sivgen-hash-alg=", encprefix);
747 virQEMUBuildBufferEscapeComma(buf, encinfo->ivgen_hash);
748 virBufferAddLit(buf, ",");
749 }
750 }
751
752
753 static int
storageBackendCreateQemuImgOpts(virStorageEncryptionInfoDef * encinfo,char ** opts,struct _virStorageBackendQemuImgInfo * info)754 storageBackendCreateQemuImgOpts(virStorageEncryptionInfoDef *encinfo,
755 char **opts,
756 struct _virStorageBackendQemuImgInfo *info)
757 {
758 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
759
760 if (info->backingPath)
761 virBufferAsprintf(&buf, "backing_fmt=%s,",
762 virStorageFileFormatTypeToString(info->backingFormat));
763
764 if (encinfo) {
765 storageBackendBuildQemuImgEncriptionOpts(&buf, info->format, encinfo,
766 info->secretAlias);
767 }
768
769 if (info->preallocate) {
770 if (info->size_arg > info->allocation)
771 virBufferAddLit(&buf, "preallocation=metadata,");
772 else
773 virBufferAddLit(&buf, "preallocation=falloc,");
774 }
775
776 if (info->nocow)
777 virBufferAddLit(&buf, "nocow=on,");
778
779 if (info->compat)
780 virBufferAsprintf(&buf, "compat=%s,", info->compat);
781 else if (info->format == VIR_STORAGE_FILE_QCOW2)
782 virBufferAddLit(&buf, "compat=0.10,");
783
784 if (info->clusterSize > 0)
785 virBufferAsprintf(&buf, "cluster_size=%llu,", info->clusterSize);
786
787 if (info->features && info->format == VIR_STORAGE_FILE_QCOW2) {
788 if (virBitmapIsBitSet(info->features,
789 VIR_STORAGE_FILE_FEATURE_LAZY_REFCOUNTS)) {
790 if (STREQ_NULLABLE(info->compat, "0.10")) {
791 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
792 _("lazy_refcounts not supported with compat"
793 " level %s"),
794 info->compat);
795 return -1;
796 }
797 virBufferAddLit(&buf, "lazy_refcounts,");
798 }
799 }
800
801 virBufferTrim(&buf, ",");
802
803 *opts = virBufferContentAndReset(&buf);
804 return 0;
805 }
806
807
808 /* storageBackendCreateQemuImgCheckEncryption:
809 * @format: format of file found
810 * @type: TypeToString of format.type
811 * @vol: pointer to volume def
812 *
813 * Ensure the proper setup for encryption.
814 *
815 * Returns 0 on success, -1 on failure w/ error set
816 */
817 static int
storageBackendCreateQemuImgCheckEncryption(int format,const char * type,virStorageVolDef * vol)818 storageBackendCreateQemuImgCheckEncryption(int format,
819 const char *type,
820 virStorageVolDef *vol)
821 {
822 virStorageEncryption *enc = vol->target.encryption;
823
824 if (format == VIR_STORAGE_FILE_RAW ||
825 format == VIR_STORAGE_FILE_QCOW2) {
826 if (enc->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
827 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
828 _("unsupported volume encryption format %d"),
829 vol->target.encryption->format);
830 return -1;
831 }
832 if (enc->nsecrets > 1) {
833 virReportError(VIR_ERR_XML_ERROR, "%s",
834 _("too many secrets for luks encryption"));
835 return -1;
836 }
837 if (enc->nsecrets == 0) {
838 virReportError(VIR_ERR_XML_ERROR, "%s",
839 _("no secret provided for luks encryption"));
840 return -1;
841 }
842 } else {
843 virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
844 _("volume encryption unsupported with format %s"), type);
845 return -1;
846 }
847
848 return 0;
849 }
850
851
852 static int
storageBackendCreateQemuImgSetInput(virStorageVolDef * inputvol,virStorageVolEncryptConvertStep convertStep,struct _virStorageBackendQemuImgInfo * info)853 storageBackendCreateQemuImgSetInput(virStorageVolDef *inputvol,
854 virStorageVolEncryptConvertStep convertStep,
855 struct _virStorageBackendQemuImgInfo *info)
856 {
857 if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CREATE) {
858 if (!(info->inputPath = inputvol->target.path)) {
859 virReportError(VIR_ERR_INVALID_ARG, "%s",
860 _("missing input volume target path"));
861 return -1;
862 }
863 }
864
865 info->inputFormat = inputvol->target.format;
866 if (inputvol->type == VIR_STORAGE_VOL_BLOCK)
867 info->inputFormat = VIR_STORAGE_FILE_RAW;
868 if (info->inputFormat == VIR_STORAGE_FILE_ISO)
869 info->inputFormat = VIR_STORAGE_FILE_RAW;
870 if (!(info->inputFormatStr =
871 virStorageFileFormatTypeToString(info->inputFormat))) {
872 virReportError(VIR_ERR_INTERNAL_ERROR,
873 _("unknown storage vol type %d"),
874 info->inputFormat);
875 return -1;
876 }
877
878 return 0;
879 }
880
881
882 static int
storageBackendCreateQemuImgSetBacking(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,struct _virStorageBackendQemuImgInfo * info)883 storageBackendCreateQemuImgSetBacking(virStoragePoolObj *pool,
884 virStorageVolDef *vol,
885 virStorageVolDef *inputvol,
886 struct _virStorageBackendQemuImgInfo *info)
887 {
888 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
889 int accessRetCode = -1;
890 g_autofree char *absolutePath = NULL;
891
892 if (info->format == VIR_STORAGE_FILE_RAW) {
893 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
894 _("cannot set backing store for raw volume"));
895 return -1;
896 }
897
898 info->backingFormat = vol->target.backingStore->format;
899 info->backingPath = vol->target.backingStore->path;
900
901 if (info->preallocate) {
902 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
903 _("metadata preallocation conflicts with backing"
904 " store"));
905 return -1;
906 }
907
908 /* XXX: Not strictly required: qemu-img has an option a different
909 * backing store, not really sure what use it serves though, and it
910 * may cause issues with lvm. Untested essentially.
911 */
912 if (inputvol && virStorageSourceHasBacking(&inputvol->target) &&
913 STRNEQ_NULLABLE(inputvol->target.backingStore->path,
914 info->backingPath)) {
915 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
916 _("a different backing store cannot be specified."));
917 return -1;
918 }
919
920 if (!virStorageFileFormatTypeToString(info->backingFormat)) {
921 virReportError(VIR_ERR_INTERNAL_ERROR,
922 _("unknown storage vol backing store type %d"),
923 info->backingFormat);
924 return -1;
925 }
926
927 /* Convert relative backing store paths to absolute paths for access
928 * validation.
929 */
930 if (*(info->backingPath) != '/')
931 absolutePath = g_strdup_printf("%s/%s", def->target.path, info->backingPath);
932 accessRetCode = access(absolutePath ? absolutePath :
933 info->backingPath, R_OK);
934 if (accessRetCode != 0) {
935 virReportSystemError(errno,
936 _("inaccessible backing store volume %s"),
937 info->backingPath);
938 return -1;
939 }
940
941 return 0;
942 }
943
944
945 static int
storageBackendCreateQemuImgSetOptions(virCommand * cmd,virStorageEncryptionInfoDef * encinfo,struct _virStorageBackendQemuImgInfo * info)946 storageBackendCreateQemuImgSetOptions(virCommand *cmd,
947 virStorageEncryptionInfoDef *encinfo,
948 struct _virStorageBackendQemuImgInfo *info)
949 {
950 g_autofree char *opts = NULL;
951
952 if (storageBackendCreateQemuImgOpts(encinfo, &opts, info) < 0)
953 return -1;
954 if (opts)
955 virCommandAddArgList(cmd, "-o", opts, NULL);
956
957 return 0;
958 }
959
960
961 /* Add a secret object to the command line:
962 * --object secret,id=$secretAlias,file=$secretPath
963 *
964 * NB: format=raw is assumed
965 */
966 static int
storageBackendCreateQemuImgSecretObject(virCommand * cmd,const char * secretPath,const char * secretAlias)967 storageBackendCreateQemuImgSecretObject(virCommand *cmd,
968 const char *secretPath,
969 const char *secretAlias)
970 {
971 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
972 g_autofree char *commandStr = NULL;
973
974 virBufferAsprintf(&buf, "secret,id=%s,file=", secretAlias);
975 virQEMUBuildBufferEscapeComma(&buf, secretPath);
976
977 commandStr = virBufferContentAndReset(&buf);
978
979 virCommandAddArgList(cmd, "--object", commandStr, NULL);
980
981 return 0;
982 }
983
984
985 /* Add a --image-opts to the qemu-img resize command line for use
986 * with encryption:
987 * --image-opts driver=luks,file.filename=$volpath,key-secret=$secretAlias
988 * or
989 * --image-opts driver=qcow2,file.filename=$volpath,encrypt.key-secret=$secretAlias
990 *
991 */
992 static int
storageBackendResizeQemuImgImageOpts(virCommand * cmd,int format,const char * path,const char * secretAlias)993 storageBackendResizeQemuImgImageOpts(virCommand *cmd,
994 int format,
995 const char *path,
996 const char *secretAlias)
997 {
998 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
999 g_autofree char *commandStr = NULL;
1000 const char *encprefix;
1001 const char *driver;
1002
1003 if (format == VIR_STORAGE_FILE_QCOW2) {
1004 driver = "qcow2";
1005 encprefix = "encrypt.";
1006 } else {
1007 driver = "luks";
1008 encprefix = "";
1009 }
1010
1011 virBufferAsprintf(&buf, "driver=%s,%skey-secret=%s,file.filename=",
1012 driver, encprefix, secretAlias);
1013 virQEMUBuildBufferEscapeComma(&buf, path);
1014
1015 commandStr = virBufferContentAndReset(&buf);
1016
1017 virCommandAddArgList(cmd, "--image-opts", commandStr, NULL);
1018
1019 return 0;
1020 }
1021
1022
1023 static int
virStorageBackendCreateQemuImgSetInfo(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,virStorageVolEncryptConvertStep convertStep,struct _virStorageBackendQemuImgInfo * info)1024 virStorageBackendCreateQemuImgSetInfo(virStoragePoolObj *pool,
1025 virStorageVolDef *vol,
1026 virStorageVolDef *inputvol,
1027 virStorageVolEncryptConvertStep convertStep,
1028 struct _virStorageBackendQemuImgInfo *info)
1029 {
1030 /* Treat output block devices as 'raw' format */
1031 if (vol->type == VIR_STORAGE_VOL_BLOCK)
1032 info->format = VIR_STORAGE_FILE_RAW;
1033
1034 if (info->format == VIR_STORAGE_FILE_ISO)
1035 info->format = VIR_STORAGE_FILE_RAW;
1036
1037 if (!(info->type = virStorageFileFormatTypeToString(info->format))) {
1038 virReportError(VIR_ERR_INTERNAL_ERROR,
1039 _("unknown storage vol type %d"),
1040 info->format);
1041 return -1;
1042 }
1043
1044 if (inputvol &&
1045 !(info->inputType =
1046 virStorageFileFormatTypeToString(inputvol->target.format))) {
1047 virReportError(VIR_ERR_INTERNAL_ERROR,
1048 _("unknown inputvol storage vol type %d"),
1049 inputvol->target.format);
1050 return -1;
1051 }
1052
1053 if (info->preallocate && info->format != VIR_STORAGE_FILE_QCOW2) {
1054 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1055 _("metadata preallocation only available with qcow2"));
1056 return -1;
1057 }
1058 if (info->compat && info->format != VIR_STORAGE_FILE_QCOW2) {
1059 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1060 _("compatibility option only available with qcow2"));
1061 return -1;
1062 }
1063 if (info->features && info->format != VIR_STORAGE_FILE_QCOW2) {
1064 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1065 _("format features only available with qcow2"));
1066 return -1;
1067 }
1068 if (info->format == VIR_STORAGE_FILE_RAW && vol->target.encryption) {
1069 if (vol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
1070 info->type = "luks";
1071 } else {
1072 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1073 _("Only luks encryption is supported for raw files"));
1074 return -1;
1075 }
1076 }
1077 if (inputvol && inputvol->target.format == VIR_STORAGE_FILE_RAW &&
1078 inputvol->target.encryption) {
1079 if (inputvol->target.encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
1080 info->inputType = "luks";
1081 } else {
1082 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1083 _("Only luks encryption is supported for raw files"));
1084 return -1;
1085 }
1086 }
1087
1088 if (inputvol &&
1089 storageBackendCreateQemuImgSetInput(inputvol, convertStep, info) < 0)
1090 return -1;
1091
1092 if (virStorageSourceHasBacking(&vol->target) &&
1093 storageBackendCreateQemuImgSetBacking(pool, vol, inputvol, info) < 0)
1094 return -1;
1095
1096 if (info->encryption &&
1097 storageBackendCreateQemuImgCheckEncryption(info->format, info->type,
1098 vol) < 0)
1099 return -1;
1100
1101 /* Size in KB */
1102 info->size_arg = VIR_DIV_UP(vol->target.capacity, 1024);
1103
1104 return 0;
1105 }
1106
1107
1108 /* Create a qemu-img virCommand from the supplied arguments */
1109 virCommand *
virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags,const char * create_tool,const char * secretPath,const char * inputSecretPath,virStorageVolEncryptConvertStep convertStep)1110 virStorageBackendCreateQemuImgCmdFromVol(virStoragePoolObj *pool,
1111 virStorageVolDef *vol,
1112 virStorageVolDef *inputvol,
1113 unsigned int flags,
1114 const char *create_tool,
1115 const char *secretPath,
1116 const char *inputSecretPath,
1117 virStorageVolEncryptConvertStep convertStep)
1118 {
1119 virCommand *cmd = NULL;
1120 struct _virStorageBackendQemuImgInfo info = {
1121 .format = vol->target.format,
1122 .type = NULL,
1123 .inputType = NULL,
1124 .path = vol->target.path,
1125 .allocation = VIR_DIV_UP(vol->target.allocation, 1024),
1126 .encryption = !!vol->target.encryption,
1127 .preallocate = !!(flags & VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA),
1128 .compat = vol->target.compat,
1129 .features = vol->target.features,
1130 .nocow = vol->target.nocow,
1131 .clusterSize = vol->target.clusterSize,
1132 .secretAlias = NULL,
1133 };
1134 virStorageEncryption *enc = vol->target.encryption;
1135 virStorageEncryption *inputenc = inputvol ? inputvol->target.encryption : NULL;
1136 virStorageEncryptionInfoDef *encinfo = NULL;
1137 g_autofree char *inputSecretAlias = NULL;
1138 const char *encprefix;
1139 const char *inputencprefix;
1140
1141 virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, NULL);
1142
1143 if (enc && (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
1144 enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT) &&
1145 (vol->target.format == VIR_STORAGE_FILE_QCOW ||
1146 vol->target.format == VIR_STORAGE_FILE_QCOW2)) {
1147 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1148 _("creation of qcow2 encrypted image is not supported"));
1149 goto error;
1150 }
1151
1152 if (inputenc && inputenc->format != VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
1153 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1154 _("encryption format of inputvol must be LUKS"));
1155 goto error;
1156 }
1157
1158 if (virStorageBackendCreateQemuImgSetInfo(pool, vol, inputvol,
1159 convertStep, &info) < 0)
1160 goto error;
1161
1162 cmd = virCommandNew(create_tool);
1163
1164 /* ignore the backing volume when we're converting a volume
1165 * including when we're doing a two step convert during create */
1166 if (info.inputPath || convertStep == VIR_STORAGE_VOL_ENCRYPT_CREATE)
1167 info.backingPath = NULL;
1168
1169 /* Converting to use encryption is a two step process - step 1 is to
1170 * create the image and step 2 is to convert it using special arguments */
1171 if (info.inputPath && convertStep == VIR_STORAGE_VOL_ENCRYPT_NONE)
1172 virCommandAddArgList(cmd, "convert", "-f", info.inputFormatStr,
1173 "-O", info.type, NULL);
1174 else if (info.inputPath && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
1175 virCommandAddArgList(cmd, "convert", "--image-opts", "-n",
1176 "--target-image-opts", NULL);
1177 else
1178 virCommandAddArgList(cmd, "create", "-f", info.type, NULL);
1179
1180 if (info.backingPath)
1181 virCommandAddArgList(cmd, "-b", info.backingPath, NULL);
1182
1183 if (enc) {
1184 if (!secretPath) {
1185 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1186 _("path to secret data file is required"));
1187 goto error;
1188 }
1189 info.secretAlias = g_strdup_printf("%s_encrypt0", vol->name);
1190 if (storageBackendCreateQemuImgSecretObject(cmd, secretPath,
1191 info.secretAlias) < 0)
1192 goto error;
1193 encinfo = &enc->encinfo;
1194 }
1195
1196 if (inputenc && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
1197 if (!inputSecretPath) {
1198 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1199 _("path to inputvol secret data file is required"));
1200 goto error;
1201 }
1202 inputSecretAlias = g_strdup_printf("%s_encrypt0", inputvol->name);
1203 if (storageBackendCreateQemuImgSecretObject(cmd, inputSecretPath,
1204 inputSecretAlias) < 0)
1205 goto error;
1206 }
1207
1208 if (convertStep != VIR_STORAGE_VOL_ENCRYPT_CONVERT) {
1209 if (storageBackendCreateQemuImgSetOptions(cmd, encinfo, &info) < 0)
1210 goto error;
1211 if (info.inputPath)
1212 virCommandAddArg(cmd, info.inputPath);
1213 virCommandAddArg(cmd, info.path);
1214 if (!info.inputPath && (info.size_arg || !info.backingPath))
1215 virCommandAddArgFormat(cmd, "%lluK", info.size_arg);
1216 } else {
1217 /* source */
1218 if (inputenc) {
1219 if (inputvol->target.format == VIR_STORAGE_FILE_QCOW2)
1220 inputencprefix = "encrypt.";
1221 else
1222 inputencprefix = "";
1223 virCommandAddArgFormat(cmd,
1224 "driver=%s,file.filename=%s,%skey-secret=%s",
1225 info.inputType, info.inputPath, inputencprefix, inputSecretAlias);
1226 } else {
1227 virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s",
1228 info.inputType ? info.inputType : "raw",
1229 info.inputPath);
1230 }
1231
1232 /* dest */
1233 if (enc) {
1234 if (vol->target.format == VIR_STORAGE_FILE_QCOW2)
1235 encprefix = "encrypt.";
1236 else
1237 encprefix = "";
1238
1239 virCommandAddArgFormat(cmd,
1240 "driver=%s,file.filename=%s,%skey-secret=%s",
1241 info.type, info.path, encprefix, info.secretAlias);
1242 } else {
1243 virCommandAddArgFormat(cmd, "driver=%s,file.filename=%s",
1244 info.type, info.path);
1245 }
1246 }
1247 VIR_FREE(info.secretAlias);
1248
1249 return cmd;
1250
1251 error:
1252 VIR_FREE(info.secretAlias);
1253 virCommandFree(cmd);
1254 return NULL;
1255 }
1256
1257
1258 static char *
storageBackendCreateQemuImgSecretPath(virStoragePoolObj * pool,virStorageVolDef * vol)1259 storageBackendCreateQemuImgSecretPath(virStoragePoolObj *pool,
1260 virStorageVolDef *vol)
1261 {
1262 virStorageEncryption *enc = vol->target.encryption;
1263 char *secretPath = NULL;
1264 uint8_t *secret = NULL;
1265 size_t secretlen = 0;
1266 virConnectPtr conn = NULL;
1267 VIR_AUTOCLOSE fd = -1;
1268 VIR_IDENTITY_AUTORESTORE virIdentity *oldident = NULL;
1269
1270 if (!enc) {
1271 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1272 _("missing encryption description"));
1273 return NULL;
1274 }
1275
1276 if (enc->nsecrets != 1) {
1277 virReportError(VIR_ERR_INVALID_ARG, "%s",
1278 _("A single <secret type='passphrase'...> "
1279 "element is expected in encryption description"));
1280 return NULL;
1281 }
1282
1283 if (!(oldident = virIdentityElevateCurrent()))
1284 return NULL;
1285
1286 conn = virGetConnectSecret();
1287 if (!conn)
1288 return NULL;
1289
1290 if (!(secretPath = virStoragePoolObjBuildTempFilePath(pool, vol)))
1291 goto cleanup;
1292
1293 if ((fd = g_mkstemp_full(secretPath, O_RDWR | O_CLOEXEC, S_IRUSR | S_IWUSR)) < 0) {
1294 virReportSystemError(errno, "%s",
1295 _("failed to open secret file for write"));
1296 goto error;
1297 }
1298
1299 if (virSecretGetSecretString(conn, &enc->secrets[0]->seclookupdef,
1300 VIR_SECRET_USAGE_TYPE_VOLUME,
1301 &secret, &secretlen) < 0)
1302 goto error;
1303
1304 if (safewrite(fd, secret, secretlen) < 0) {
1305 virReportSystemError(errno, "%s",
1306 _("failed to write secret file"));
1307 goto error;
1308 }
1309
1310 if ((vol->target.perms->uid != (uid_t)-1) &&
1311 (vol->target.perms->gid != (gid_t)-1)) {
1312 if (chown(secretPath, vol->target.perms->uid,
1313 vol->target.perms->gid) < 0) {
1314 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1315 _("failed to chown secret file"));
1316 goto error;
1317 }
1318 }
1319
1320 cleanup:
1321 virObjectUnref(conn);
1322 virSecureErase(secret, secretlen);
1323 g_free(secret);
1324
1325 return secretPath;
1326
1327 error:
1328 unlink(secretPath);
1329 VIR_FREE(secretPath);
1330 goto cleanup;
1331 }
1332
1333
1334 static int
storageBackendDoCreateQemuImg(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags,const char * create_tool,const char * secretPath,const char * inputSecretPath,virStorageVolEncryptConvertStep convertStep)1335 storageBackendDoCreateQemuImg(virStoragePoolObj *pool,
1336 virStorageVolDef *vol,
1337 virStorageVolDef *inputvol,
1338 unsigned int flags,
1339 const char *create_tool,
1340 const char *secretPath,
1341 const char *inputSecretPath,
1342 virStorageVolEncryptConvertStep convertStep)
1343 {
1344 g_autoptr(virCommand) cmd = NULL;
1345
1346 cmd = virStorageBackendCreateQemuImgCmdFromVol(pool, vol, inputvol,
1347 flags, create_tool,
1348 secretPath, inputSecretPath,
1349 convertStep);
1350 if (!cmd)
1351 return -1;
1352
1353 return virStorageBackendCreateExecCommand(pool, vol, cmd);
1354 }
1355
1356
1357 static int
storageBackendCreateQemuImg(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)1358 storageBackendCreateQemuImg(virStoragePoolObj *pool,
1359 virStorageVolDef *vol,
1360 virStorageVolDef *inputvol,
1361 unsigned int flags)
1362 {
1363 int ret = -1;
1364 virStorageVolEncryptConvertStep convertStep = VIR_STORAGE_VOL_ENCRYPT_NONE;
1365 g_autofree char *create_tool = NULL;
1366 g_autofree char *secretPath = NULL;
1367 g_autofree char *inputSecretPath = NULL;
1368
1369 virCheckFlags(VIR_STORAGE_VOL_CREATE_PREALLOC_METADATA, -1);
1370
1371 create_tool = virFindFileInPath("qemu-img");
1372 if (!create_tool) {
1373 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1374 _("creation of non-raw file images is "
1375 "not supported without qemu-img."));
1376 return -1;
1377 }
1378
1379 if (vol->target.encryption &&
1380 !(secretPath = storageBackendCreateQemuImgSecretPath(pool, vol)))
1381 goto cleanup;
1382
1383 if (inputvol && inputvol->target.encryption &&
1384 !(inputSecretPath = storageBackendCreateQemuImgSecretPath(pool,
1385 inputvol)))
1386 goto cleanup;
1387
1388 /* Using an input file for encryption requires a multi-step process
1389 * to create an image of the same size as the inputvol and then to
1390 * convert the inputvol afterwards. */
1391 if ((secretPath || inputSecretPath) && inputvol)
1392 convertStep = VIR_STORAGE_VOL_ENCRYPT_CREATE;
1393
1394 do {
1395 ret = storageBackendDoCreateQemuImg(pool, vol, inputvol, flags,
1396 create_tool, secretPath,
1397 inputSecretPath, convertStep);
1398
1399 /* Failure to convert, attempt to delete what we created */
1400 if (ret < 0 && convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
1401 ignore_value(virFileRemove(vol->target.path,
1402 vol->target.perms->uid,
1403 vol->target.perms->gid));
1404
1405 if (ret < 0 || convertStep == VIR_STORAGE_VOL_ENCRYPT_NONE)
1406 goto cleanup;
1407
1408 if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CREATE)
1409 convertStep = VIR_STORAGE_VOL_ENCRYPT_CONVERT;
1410 else if (convertStep == VIR_STORAGE_VOL_ENCRYPT_CONVERT)
1411 convertStep = VIR_STORAGE_VOL_ENCRYPT_DONE;
1412 } while (convertStep != VIR_STORAGE_VOL_ENCRYPT_DONE);
1413
1414 cleanup:
1415 if (secretPath)
1416 unlink(secretPath);
1417 if (inputSecretPath)
1418 unlink(inputSecretPath);
1419 return ret;
1420 }
1421
1422
1423 /**
1424 * virStorageBackendCreateVolUsingQemuImg
1425 * @pool: Storage Pool Object
1426 * @vol: Volume definition
1427 * @inputvol: Volume to use for creation
1428 * @flags: Flags for creation options
1429 *
1430 * A shim to storageBackendCreateQemuImg to allow other backends to
1431 * utilize qemu-img processing in order to create or alter the volume.
1432 *
1433 * NB: If a volume target format is not supplied (per usual for some
1434 * backends), temporarily adjust the format to be RAW. Once completed,
1435 * reset the format back to NONE.
1436 *
1437 * Returns: 0 on success, -1 on failure.
1438 */
1439 int
virStorageBackendCreateVolUsingQemuImg(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)1440 virStorageBackendCreateVolUsingQemuImg(virStoragePoolObj *pool,
1441 virStorageVolDef *vol,
1442 virStorageVolDef *inputvol,
1443 unsigned int flags)
1444 {
1445 int ret = -1;
1446 bool changeFormat = false;
1447
1448 if (vol->target.format == VIR_STORAGE_FILE_NONE) {
1449 vol->target.format = VIR_STORAGE_FILE_RAW;
1450 changeFormat = true;
1451 }
1452
1453 ret = storageBackendCreateQemuImg(pool, vol, inputvol, flags);
1454
1455 if (changeFormat)
1456 vol->target.format = VIR_STORAGE_FILE_NONE;
1457
1458 return ret;
1459 }
1460
1461
1462 virStorageBackendBuildVolFrom
virStorageBackendGetBuildVolFromFunction(virStorageVolDef * vol,virStorageVolDef * inputvol)1463 virStorageBackendGetBuildVolFromFunction(virStorageVolDef *vol,
1464 virStorageVolDef *inputvol)
1465 {
1466 if (!inputvol)
1467 return NULL;
1468
1469 /* If either volume is a non-raw file vol, or uses encryption,
1470 * we need to use an external tool for converting
1471 */
1472 if ((vol->type == VIR_STORAGE_VOL_FILE &&
1473 (vol->target.format != VIR_STORAGE_FILE_RAW ||
1474 vol->target.encryption)) ||
1475 (inputvol->type == VIR_STORAGE_VOL_FILE &&
1476 (inputvol->target.format != VIR_STORAGE_FILE_RAW ||
1477 inputvol->target.encryption))) {
1478 return storageBackendCreateQemuImg;
1479 }
1480
1481 if (vol->type == VIR_STORAGE_VOL_PLOOP)
1482 return storageBackendCreatePloop;
1483 if (vol->type == VIR_STORAGE_VOL_BLOCK)
1484 return storageBackendCreateBlockFrom;
1485 else
1486 return storageBackendCreateRaw;
1487 }
1488
1489
1490 struct diskType {
1491 int part_table_type;
1492 unsigned short offset;
1493 unsigned short length;
1494 unsigned long long magic;
1495 };
1496
1497
1498 static struct diskType const disk_types[] = {
1499 { VIR_STORAGE_POOL_DISK_LVM2, 0x218, 8, 0x31303020324D564CULL },
1500 { VIR_STORAGE_POOL_DISK_GPT, 0x200, 8, 0x5452415020494645ULL },
1501 { VIR_STORAGE_POOL_DISK_DVH, 0x0, 4, 0x41A9E50BULL },
1502 { VIR_STORAGE_POOL_DISK_MAC, 0x0, 2, 0x5245ULL },
1503 { VIR_STORAGE_POOL_DISK_BSD, 0x40, 4, 0x82564557ULL },
1504 { VIR_STORAGE_POOL_DISK_SUN, 0x1fc, 2, 0xBEDAULL },
1505 /*
1506 * NOTE: pc98 is funky; the actual signature is 0x55AA (just like dos), so
1507 * we can't use that. At the moment I'm relying on the "dummy" IPL
1508 * bootloader data that comes from parted. Luckily, the chances of running
1509 * into a pc98 machine running libvirt are approximately nil.
1510 */
1511 /*{ 0x1fe, 2, 0xAA55UL },*/
1512 { VIR_STORAGE_POOL_DISK_PC98, 0x0, 8, 0x314C5049000000CBULL },
1513 /*
1514 * NOTE: the order is important here; some other disk types (like GPT and
1515 * and PC98) also have 0x55AA at this offset. For that reason, the DOS
1516 * one must be the last one.
1517 */
1518 { VIR_STORAGE_POOL_DISK_DOS, 0x1fe, 2, 0xAA55ULL },
1519 { -1, 0x0, 0, 0x0ULL },
1520 };
1521
1522
1523 /*
1524 * virStorageBackendDetectBlockVolFormatFD
1525 * @target: target definition ptr of volume to update
1526 * @fd: fd of storage volume to update,
1527 * @readflags: VolReadErrorMode flags to handle read error after open
1528 * is successful, but read is not.
1529 *
1530 * Returns 0 for success, -1 on a legitimate error condition, -2 if
1531 * the read error is desired to be ignored (along with appropriate
1532 * VIR_WARN of the issue).
1533 */
1534 static int
virStorageBackendDetectBlockVolFormatFD(virStorageSource * target,int fd,unsigned int readflags)1535 virStorageBackendDetectBlockVolFormatFD(virStorageSource *target,
1536 int fd,
1537 unsigned int readflags)
1538 {
1539 size_t i;
1540 off_t start;
1541 unsigned char buffer[1024];
1542 ssize_t bytes;
1543
1544 /* make sure to set the target format "unknown" to begin with */
1545 target->format = VIR_STORAGE_POOL_DISK_UNKNOWN;
1546
1547 start = lseek(fd, 0, SEEK_SET);
1548 if (start < 0) {
1549 virReportSystemError(errno,
1550 _("cannot seek to beginning of file '%s'"),
1551 target->path);
1552 return -1;
1553 }
1554 bytes = saferead(fd, buffer, sizeof(buffer));
1555 if (bytes < 0) {
1556 if (readflags & VIR_STORAGE_VOL_READ_NOERROR) {
1557 VIR_WARN("ignoring failed saferead of file '%s'",
1558 target->path);
1559 return -2;
1560 } else {
1561 virReportSystemError(errno,
1562 _("cannot read beginning of file '%s'"),
1563 target->path);
1564 return -1;
1565 }
1566 }
1567
1568 for (i = 0; disk_types[i].part_table_type != -1; i++) {
1569 if (disk_types[i].offset + disk_types[i].length > bytes)
1570 continue;
1571 if (memcmp(buffer+disk_types[i].offset, &disk_types[i].magic,
1572 disk_types[i].length) == 0) {
1573 target->format = disk_types[i].part_table_type;
1574 break;
1575 }
1576 }
1577
1578 if (target->format == VIR_STORAGE_POOL_DISK_UNKNOWN)
1579 VIR_DEBUG("cannot determine the target format for '%s'",
1580 target->path);
1581
1582 return 0;
1583 }
1584
1585
1586 /*
1587 * Allows caller to silently ignore files with improper mode
1588 *
1589 * Returns -1 on error. If VIR_STORAGE_VOL_OPEN_NOERROR is passed, we
1590 * return -2 if file mode is unexpected or the volume is a dangling
1591 * symbolic link.
1592 */
1593 int
virStorageBackendVolOpen(const char * path,struct stat * sb,unsigned int flags)1594 virStorageBackendVolOpen(const char *path, struct stat *sb,
1595 unsigned int flags)
1596 {
1597 int fd, mode = 0;
1598 g_autofree char *base = g_path_get_basename(path);
1599 bool noerror = (flags & VIR_STORAGE_VOL_OPEN_NOERROR);
1600
1601 if (g_lstat(path, sb) < 0) {
1602 if (errno == ENOENT) {
1603 if (noerror) {
1604 VIR_WARN("ignoring missing file '%s'", path);
1605 return -2;
1606 }
1607 virReportError(VIR_ERR_NO_STORAGE_VOL,
1608 _("no storage vol with matching path '%s'"),
1609 path);
1610 return -1;
1611 }
1612 virReportSystemError(errno,
1613 _("cannot stat file '%s'"),
1614 path);
1615 return -1;
1616 }
1617
1618 if (S_ISFIFO(sb->st_mode)) {
1619 if (noerror) {
1620 VIR_WARN("ignoring FIFO '%s'", path);
1621 return -2;
1622 }
1623 virReportError(VIR_ERR_INTERNAL_ERROR,
1624 _("Volume path '%s' is a FIFO"), path);
1625 return -1;
1626 } else if (S_ISSOCK(sb->st_mode)) {
1627 if (noerror) {
1628 VIR_WARN("ignoring socket '%s'", path);
1629 return -2;
1630 }
1631 virReportError(VIR_ERR_INTERNAL_ERROR,
1632 _("Volume path '%s' is a socket"), path);
1633 return -1;
1634 }
1635
1636 /* O_NONBLOCK should only matter during open() for fifos and
1637 * sockets, which we already filtered; but using it prevents a
1638 * TOCTTOU race. However, later on we will want to read() the
1639 * header from this fd, and virFileRead* routines require a
1640 * blocking fd, so fix it up after verifying we avoided a race.
1641 *
1642 * Use of virFileOpenAs allows this path to open a file using
1643 * the uid and gid as it was created in order to open. Since this
1644 * path is not using O_CREAT or O_TMPFILE, mode is meaningless.
1645 * Opening under user/group is especially important in an NFS
1646 * root-squash environment. If the target path isn't on shared
1647 * file system, the open will fail in the OPEN_FORK path.
1648 */
1649 if ((fd = virFileOpenAs(path, O_RDONLY|O_NONBLOCK|O_NOCTTY,
1650 0, sb->st_uid, sb->st_gid,
1651 VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK)) < 0) {
1652 if ((errno == ENOENT || errno == ELOOP) &&
1653 S_ISLNK(sb->st_mode) && noerror) {
1654 VIR_WARN("ignoring dangling symlink '%s'", path);
1655 return -2;
1656 }
1657 if (errno == ENOENT && noerror) {
1658 VIR_WARN("ignoring missing file '%s'", path);
1659 return -2;
1660 }
1661 if (errno == ENXIO && noerror) {
1662 VIR_WARN("ignoring missing fifo '%s'", path);
1663 return -2;
1664 }
1665 if ((errno == EACCES || errno == EPERM) && noerror) {
1666 VIR_WARN("ignoring permission error for '%s'", path);
1667 return -2;
1668 }
1669
1670 virReportSystemError(errno, _("cannot open volume '%s'"), path);
1671 return -1;
1672 }
1673
1674 if (fstat(fd, sb) < 0) {
1675 virReportSystemError(errno, _("cannot stat file '%s'"), path);
1676 VIR_FORCE_CLOSE(fd);
1677 return -1;
1678 }
1679
1680 if (S_ISREG(sb->st_mode)) {
1681 mode = VIR_STORAGE_VOL_OPEN_REG;
1682 } else if (S_ISCHR(sb->st_mode)) {
1683 mode = VIR_STORAGE_VOL_OPEN_CHAR;
1684 } else if (S_ISBLK(sb->st_mode)) {
1685 mode = VIR_STORAGE_VOL_OPEN_BLOCK;
1686 } else if (S_ISDIR(sb->st_mode)) {
1687 mode = VIR_STORAGE_VOL_OPEN_DIR;
1688
1689 if (STREQ(base, ".") ||
1690 STREQ(base, "..")) {
1691 VIR_FORCE_CLOSE(fd);
1692 if (noerror) {
1693 VIR_INFO("Skipping special dir '%s'", base);
1694 return -2;
1695 }
1696 virReportError(VIR_ERR_INTERNAL_ERROR,
1697 _("Cannot use volume path '%s'"), path);
1698 return -1;
1699 }
1700 } else {
1701 VIR_FORCE_CLOSE(fd);
1702 if (noerror) {
1703 VIR_WARN("ignoring unexpected type for file '%s'", path);
1704 return -2;
1705 }
1706 virReportError(VIR_ERR_INTERNAL_ERROR,
1707 _("unexpected type for file '%s'"), path);
1708 return -1;
1709 }
1710
1711 if (virSetBlocking(fd, true) < 0) {
1712 VIR_FORCE_CLOSE(fd);
1713 virReportSystemError(errno, _("unable to set blocking mode for '%s'"),
1714 path);
1715 return -1;
1716 }
1717
1718 if (!(mode & flags)) {
1719 VIR_FORCE_CLOSE(fd);
1720 if (noerror) {
1721 VIR_INFO("Skipping volume '%s'", path);
1722 return -2;
1723 }
1724
1725 virReportError(VIR_ERR_INTERNAL_ERROR,
1726 _("unexpected storage mode for '%s'"), path);
1727 return -1;
1728 }
1729
1730 return fd;
1731 }
1732
1733 /* virStorageIsPloop function checks whether given directory is ploop volume's
1734 * directory.
1735 */
1736 static bool
storageBackendIsPloopDir(char * path)1737 storageBackendIsPloopDir(char *path)
1738 {
1739 g_autofree char *root = NULL;
1740 g_autofree char *desc = NULL;
1741
1742 root = g_strdup_printf("%s/root.hds", path);
1743 if (!virFileExists(root))
1744 return false;
1745 desc = g_strdup_printf("%s/DiskDescriptor.xml", path);
1746 if (!virFileExists(desc))
1747 return false;
1748
1749 return true;
1750 }
1751
1752 /* In case of ploop volumes, path to volume is the path to the ploop
1753 * directory. To get information about allocation, header information
1754 * and etc. we need to perform virStorageBackendVolOpen and
1755 * virStorageBackendUpdateVolTargetFd once again.
1756 */
1757 static int
storageBackendRedoPloopUpdate(virStorageSource * target,struct stat * sb,int * fd,unsigned int flags)1758 storageBackendRedoPloopUpdate(virStorageSource *target, struct stat *sb,
1759 int *fd, unsigned int flags)
1760 {
1761 g_autofree char *path = NULL;
1762
1763 path = g_strdup_printf("%s/root.hds", target->path);
1764 VIR_FORCE_CLOSE(*fd);
1765 if ((*fd = virStorageBackendVolOpen(path, sb, flags)) < 0)
1766 return -1;
1767 return virStorageBackendUpdateVolTargetInfoFD(target, *fd, sb);
1768 }
1769
1770 /*
1771 * storageBackendUpdateVolTargetInfo
1772 * @voltype: Volume type
1773 * @target: target definition ptr of volume to update
1774 * @withBlockVolFormat: true if caller determined a block file
1775 * @openflags: various VolOpenCheckMode flags to handle errors on open
1776 * @readflags: VolReadErrorMode flags to handle read error after open
1777 * is successful, but read is not.
1778 *
1779 * Returns 0 for success, -1 on a legitimate error condition, and -2
1780 * if the openflags used VIR_STORAGE_VOL_OPEN_NOERROR and some sort of
1781 * open error occurred. It is up to the caller to handle. A -2 may also
1782 * be returned if the caller passed a readflagsflag.
1783 */
1784 static int
storageBackendUpdateVolTargetInfo(virStorageVolType voltype,virStorageSource * target,bool withBlockVolFormat,unsigned int openflags,unsigned int readflags)1785 storageBackendUpdateVolTargetInfo(virStorageVolType voltype,
1786 virStorageSource *target,
1787 bool withBlockVolFormat,
1788 unsigned int openflags,
1789 unsigned int readflags)
1790 {
1791 int rc;
1792 struct stat sb;
1793 ssize_t len = VIR_STORAGE_MAX_HEADER;
1794 g_autofree char *buf = NULL;
1795 VIR_AUTOCLOSE fd = -1;
1796
1797 if ((rc = virStorageBackendVolOpen(target->path, &sb, openflags)) < 0)
1798 return rc;
1799 fd = rc;
1800
1801 if ((virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb)) < 0)
1802 return -1;
1803
1804 if ((voltype == VIR_STORAGE_VOL_FILE || voltype == VIR_STORAGE_VOL_BLOCK) &&
1805 target->format != VIR_STORAGE_FILE_NONE) {
1806 if (S_ISDIR(sb.st_mode)) {
1807 if (storageBackendIsPloopDir(target->path)) {
1808 if ((storageBackendRedoPloopUpdate(target, &sb, &fd,
1809 openflags)) < 0)
1810 return -1;
1811 target->format = VIR_STORAGE_FILE_PLOOP;
1812 } else {
1813 return 0;
1814 }
1815 }
1816
1817 if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
1818 virReportSystemError(errno, _("cannot seek to start of '%s'"), target->path);
1819 return -1;
1820 }
1821
1822 if ((len = virFileReadHeaderFD(fd, len, &buf)) < 0) {
1823 if (readflags & VIR_STORAGE_VOL_READ_NOERROR) {
1824 VIR_WARN("ignoring failed header read for '%s'",
1825 target->path);
1826 return -2;
1827 } else {
1828 virReportSystemError(errno,
1829 _("cannot read header '%s'"),
1830 target->path);
1831 return -1;
1832 }
1833 }
1834
1835 if (virStorageSourceUpdateCapacity(target, buf, len) < 0)
1836 return -1;
1837 }
1838
1839 if (withBlockVolFormat)
1840 return virStorageBackendDetectBlockVolFormatFD(target, fd, readflags);
1841
1842 return 0;
1843 }
1844
1845 /*
1846 * virStorageBackendUpdateVolInfo
1847 * @vol: Pointer to a volume storage definition
1848 * @withBlockVolFormat: true if the caller determined a block file
1849 * @openflags: various VolOpenCheckMode flags to handle errors on open
1850 * @readflags: various VolReadErrorMode flags to handle errors on read
1851 *
1852 * Returns 0 for success, -1 on a legitimate error condition, and -2
1853 * if the openflags used VIR_STORAGE_VOL_OPEN_NOERROR and some sort of
1854 * open error occurred. It is up to the caller to handle.
1855 */
1856 int
virStorageBackendUpdateVolInfo(virStorageVolDef * vol,bool withBlockVolFormat,unsigned int openflags,unsigned int readflags)1857 virStorageBackendUpdateVolInfo(virStorageVolDef *vol,
1858 bool withBlockVolFormat,
1859 unsigned int openflags,
1860 unsigned int readflags)
1861 {
1862 int ret;
1863
1864 if ((ret = storageBackendUpdateVolTargetInfo(vol->type,
1865 &vol->target,
1866 withBlockVolFormat,
1867 openflags, readflags)) < 0)
1868 return ret;
1869
1870 if (virStorageSourceHasBacking(&vol->target) &&
1871 (ret = storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
1872 vol->target.backingStore,
1873 withBlockVolFormat,
1874 VIR_STORAGE_VOL_OPEN_DEFAULT |
1875 VIR_STORAGE_VOL_OPEN_NOERROR,
1876 readflags)) == -1)
1877 return ret;
1878
1879 return 0;
1880 }
1881
1882 /*
1883 * virStorageBackendUpdateVolTargetInfoFD:
1884 * @target: target definition ptr of volume to update
1885 * @fd: fd of storage volume to update, via virStorageBackendOpenVol*, or -1
1886 * @sb: details about file (must match @fd, if that is provided)
1887 *
1888 * Returns 0 for success, -1 on a legitimate error condition.
1889 */
1890 int
virStorageBackendUpdateVolTargetInfoFD(virStorageSource * target,int fd,struct stat * sb)1891 virStorageBackendUpdateVolTargetInfoFD(virStorageSource *target,
1892 int fd,
1893 struct stat *sb)
1894 {
1895 #if WITH_SELINUX
1896 char *filecon = NULL;
1897 #endif
1898
1899 if (virStorageSourceUpdateBackingSizes(target, fd, sb) < 0)
1900 return -1;
1901
1902 if (!target->perms)
1903 target->perms = g_new0(virStoragePerms, 1);
1904 target->perms->mode = sb->st_mode & S_IRWXUGO;
1905 target->perms->uid = sb->st_uid;
1906 target->perms->gid = sb->st_gid;
1907
1908 if (!target->timestamps)
1909 target->timestamps = g_new0(virStorageTimestamps, 1);
1910
1911 #ifdef __APPLE__
1912 target->timestamps->atime = sb->st_atimespec;
1913 target->timestamps->btime = sb->st_birthtimespec;
1914 target->timestamps->ctime = sb->st_ctimespec;
1915 target->timestamps->mtime = sb->st_mtimespec;
1916 #else /* ! __APPLE__ */
1917 target->timestamps->atime = sb->st_atim;
1918 # ifdef __linux__
1919 target->timestamps->btime = (struct timespec){0, 0};
1920 # else /* ! __linux__ */
1921 # ifndef __DragonFly__
1922 target->timestamps->btime = sb->st_birthtim;
1923 # endif
1924 # endif /* ! __linux__ */
1925 target->timestamps->ctime = sb->st_ctim;
1926 target->timestamps->mtime = sb->st_mtim;
1927 #endif /* ! __APPLE__ */
1928
1929 target->type = VIR_STORAGE_TYPE_FILE;
1930
1931 VIR_FREE(target->perms->label);
1932
1933 #if WITH_SELINUX
1934 /* XXX: make this a security driver call */
1935 if (fd >= 0) {
1936 if (fgetfilecon_raw(fd, &filecon) == -1) {
1937 if (errno != ENODATA && errno != ENOTSUP) {
1938 virReportSystemError(errno,
1939 _("cannot get file context of '%s'"),
1940 target->path);
1941 return -1;
1942 }
1943 } else {
1944 target->perms->label = g_strdup(filecon);
1945 freecon(filecon);
1946 }
1947 }
1948 #endif
1949
1950 return 0;
1951 }
1952
1953 bool
virStorageBackendPoolPathIsStable(const char * path)1954 virStorageBackendPoolPathIsStable(const char *path)
1955 {
1956 if (path == NULL || STREQ(path, "/dev") || STREQ(path, "/dev/"))
1957 return false;
1958
1959 if (!STRPREFIX(path, "/dev/"))
1960 return false;
1961
1962 return true;
1963 }
1964
1965 /*
1966 * Given a volume path directly in /dev/XXX, iterate over the
1967 * entries in the directory def->target.path and find the
1968 * first symlink pointing to the volume path.
1969 *
1970 * If, the target.path is /dev/, then return the original volume
1971 * path.
1972 *
1973 * If no symlink is found, then return the original volume path
1974 *
1975 * Typically target.path is one of the /dev/disk/by-XXX dirs
1976 * with stable paths.
1977 *
1978 * If 'loop' is true, we use a timeout loop to give dynamic paths
1979 * a change to appear.
1980 */
1981 char *
virStorageBackendStablePath(virStoragePoolObj * pool,const char * devpath,bool loop)1982 virStorageBackendStablePath(virStoragePoolObj *pool,
1983 const char *devpath,
1984 bool loop)
1985 {
1986 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
1987 g_autoptr(DIR) dh = NULL;
1988 struct dirent *dent;
1989 char *stablepath;
1990 int opentries = 0;
1991 int retry = 0;
1992 int direrr;
1993
1994 /* Logical pools are under /dev but already have stable paths */
1995 if (def->type == VIR_STORAGE_POOL_LOGICAL ||
1996 !virStorageBackendPoolPathIsStable(def->target.path))
1997 goto ret_strdup;
1998
1999 /* We loop here because /dev/disk/by-{id,path} may not have existed
2000 * before we started this operation, so we have to give it some time to
2001 * get created.
2002 */
2003 reopen:
2004 if (virDirOpenQuiet(&dh, def->target.path) < 0) {
2005 opentries++;
2006 if (loop && errno == ENOENT && opentries < 50) {
2007 g_usleep(100 * 1000);
2008 goto reopen;
2009 }
2010 virReportSystemError(errno,
2011 _("cannot read dir '%s'"),
2012 def->target.path);
2013 return NULL;
2014 }
2015
2016 /* The pool is pointing somewhere like /dev/disk/by-path
2017 * or /dev/disk/by-id, so we need to check all symlinks in
2018 * the target directory and figure out which one points
2019 * to this device node.
2020 *
2021 * And it might need some time till the stable path shows
2022 * up, so add timeout to retry here. Ignore readdir failures,
2023 * since we have a fallback.
2024 */
2025 retry:
2026 while ((direrr = virDirRead(dh, &dent, NULL)) > 0) {
2027 stablepath = g_strdup_printf("%s/%s", def->target.path, dent->d_name);
2028
2029 if (virFileLinkPointsTo(stablepath, devpath)) {
2030 return stablepath;
2031 }
2032
2033 VIR_FREE(stablepath);
2034 }
2035
2036 if (!direrr && loop && ++retry < 100) {
2037 g_usleep(100 * 1000);
2038 goto retry;
2039 }
2040
2041 ret_strdup:
2042 /* Couldn't find any matching stable link so give back
2043 * the original non-stable dev path
2044 */
2045
2046 stablepath = g_strdup(devpath);
2047
2048 return stablepath;
2049 }
2050
2051 /* Common/Local File System/Directory Volume API's */
2052 static int
createFileDir(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)2053 createFileDir(virStoragePoolObj *pool,
2054 virStorageVolDef *vol,
2055 virStorageVolDef *inputvol,
2056 unsigned int flags)
2057 {
2058 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
2059 mode_t permmode = VIR_STORAGE_DEFAULT_VOL_PERM_MODE;
2060 unsigned int createflags = 0;
2061
2062 virCheckFlags(0, -1);
2063
2064 if (inputvol) {
2065 virReportError(VIR_ERR_INTERNAL_ERROR,
2066 "%s",
2067 _("cannot copy from volume to a directory volume"));
2068 return -1;
2069 }
2070
2071 if (virStorageSourceHasBacking(&vol->target)) {
2072 virReportError(VIR_ERR_NO_SUPPORT, "%s",
2073 _("backing storage not supported for directories volumes"));
2074 return -1;
2075 }
2076
2077 if (vol->target.perms->mode != (mode_t)-1)
2078 permmode = vol->target.perms->mode;
2079
2080 if (def->type == VIR_STORAGE_POOL_NETFS)
2081 createflags |= VIR_DIR_CREATE_AS_UID;
2082
2083 if (virDirCreate(vol->target.path,
2084 permmode,
2085 vol->target.perms->uid,
2086 vol->target.perms->gid,
2087 createflags) < 0) {
2088 return -1;
2089 }
2090
2091 return 0;
2092 }
2093
2094
2095 /**
2096 * Set up a volume definition to be added to a pool's volume list, but
2097 * don't do any file creation or allocation. By separating the two processes,
2098 * we allow allocation progress reporting (by polling the volume's 'info'
2099 * function), and can drop the parent pool lock during the (slow) allocation.
2100 */
2101 int
virStorageBackendVolCreateLocal(virStoragePoolObj * pool,virStorageVolDef * vol)2102 virStorageBackendVolCreateLocal(virStoragePoolObj *pool,
2103 virStorageVolDef *vol)
2104 {
2105 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
2106
2107 if (vol->target.format == VIR_STORAGE_FILE_DIR)
2108 vol->type = VIR_STORAGE_VOL_DIR;
2109 else if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
2110 vol->type = VIR_STORAGE_VOL_PLOOP;
2111 else
2112 vol->type = VIR_STORAGE_VOL_FILE;
2113
2114 /* Volumes within a directory pools are not recursive; do not
2115 * allow escape to ../ or a subdir */
2116 if (strchr(vol->name, '/')) {
2117 virReportError(VIR_ERR_OPERATION_INVALID,
2118 _("volume name '%s' cannot contain '/'"), vol->name);
2119 return -1;
2120 }
2121
2122 VIR_FREE(vol->target.path);
2123 vol->target.path = g_strdup_printf("%s/%s", def->target.path, vol->name);
2124
2125 if (virFileExists(vol->target.path)) {
2126 virReportError(VIR_ERR_OPERATION_INVALID,
2127 _("volume target path '%s' already exists"),
2128 vol->target.path);
2129 return -1;
2130 }
2131
2132 VIR_FREE(vol->key);
2133 vol->key = g_strdup(vol->target.path);
2134 return 0;
2135 }
2136
2137
2138 static int
storageBackendVolBuildLocal(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)2139 storageBackendVolBuildLocal(virStoragePoolObj *pool,
2140 virStorageVolDef *vol,
2141 virStorageVolDef *inputvol,
2142 unsigned int flags)
2143 {
2144 virStorageBackendBuildVolFrom create_func;
2145
2146 if (inputvol) {
2147 if (!(create_func =
2148 virStorageBackendGetBuildVolFromFunction(vol, inputvol)))
2149 return -1;
2150 } else if (vol->target.format == VIR_STORAGE_FILE_RAW &&
2151 vol->target.encryption == NULL) {
2152 create_func = storageBackendCreateRaw;
2153 } else if (vol->target.format == VIR_STORAGE_FILE_DIR) {
2154 create_func = createFileDir;
2155 } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
2156 create_func = storageBackendCreatePloop;
2157 } else {
2158 create_func = storageBackendCreateQemuImg;
2159 }
2160
2161 if (create_func(pool, vol, inputvol, flags) < 0)
2162 return -1;
2163 return 0;
2164 }
2165
2166
2167 /**
2168 * Allocate a new file as a volume. This is either done directly
2169 * for raw/sparse files, or by calling qemu-img for
2170 * special kinds of files
2171 */
2172 int
virStorageBackendVolBuildLocal(virStoragePoolObj * pool,virStorageVolDef * vol,unsigned int flags)2173 virStorageBackendVolBuildLocal(virStoragePoolObj *pool,
2174 virStorageVolDef *vol,
2175 unsigned int flags)
2176 {
2177 return storageBackendVolBuildLocal(pool, vol, NULL, flags);
2178 }
2179
2180
2181 /*
2182 * Create a storage vol using 'inputvol' as input
2183 */
2184 int
virStorageBackendVolBuildFromLocal(virStoragePoolObj * pool,virStorageVolDef * vol,virStorageVolDef * inputvol,unsigned int flags)2185 virStorageBackendVolBuildFromLocal(virStoragePoolObj *pool,
2186 virStorageVolDef *vol,
2187 virStorageVolDef *inputvol,
2188 unsigned int flags)
2189 {
2190 return storageBackendVolBuildLocal(pool, vol, inputvol, flags);
2191 }
2192
2193
2194 /**
2195 * Remove a volume - no support for BLOCK and NETWORK yet
2196 */
2197 int
virStorageBackendVolDeleteLocal(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,unsigned int flags)2198 virStorageBackendVolDeleteLocal(virStoragePoolObj *pool G_GNUC_UNUSED,
2199 virStorageVolDef *vol,
2200 unsigned int flags)
2201 {
2202 virCheckFlags(0, -1);
2203
2204 switch ((virStorageVolType)vol->type) {
2205 case VIR_STORAGE_VOL_FILE:
2206 case VIR_STORAGE_VOL_DIR:
2207 if (virFileRemove(vol->target.path, vol->target.perms->uid,
2208 vol->target.perms->gid) < 0) {
2209 /* Silently ignore failures where the vol has already gone away */
2210 if (errno != ENOENT) {
2211 if (vol->type == VIR_STORAGE_VOL_FILE)
2212 virReportSystemError(errno,
2213 _("cannot unlink file '%s'"),
2214 vol->target.path);
2215 else
2216 virReportSystemError(errno,
2217 _("cannot remove directory '%s'"),
2218 vol->target.path);
2219 return -1;
2220 }
2221 }
2222 break;
2223 case VIR_STORAGE_VOL_PLOOP:
2224 if (virFileDeleteTree(vol->target.path) < 0)
2225 return -1;
2226 break;
2227 case VIR_STORAGE_VOL_BLOCK:
2228 case VIR_STORAGE_VOL_NETWORK:
2229 case VIR_STORAGE_VOL_NETDIR:
2230 case VIR_STORAGE_VOL_LAST:
2231 virReportError(VIR_ERR_NO_SUPPORT,
2232 _("removing block or network volumes is not supported: %s"),
2233 vol->target.path);
2234 return -1;
2235 }
2236 return 0;
2237 }
2238
2239
2240 /* storageBackendLoadDefaultSecrets:
2241 * @vol: volume being refreshed
2242 *
2243 * If the volume had a secret generated, we need to regenerate the
2244 * encryption secret information
2245 *
2246 * Returns 0 if no secret or secret setup was successful,
2247 * -1 on failures w/ error message set
2248 */
2249 static int
storageBackendLoadDefaultSecrets(virStorageVolDef * vol)2250 storageBackendLoadDefaultSecrets(virStorageVolDef *vol)
2251 {
2252 virSecretPtr sec;
2253 virStorageEncryptionSecret *encsec = NULL;
2254 virConnectPtr conn = NULL;
2255
2256 if (!vol->target.encryption || vol->target.encryption->nsecrets != 0)
2257 return 0;
2258
2259 conn = virGetConnectSecret();
2260 if (!conn)
2261 return -1;
2262
2263 /* The encryption secret for qcow2 and luks volumes use the path
2264 * to the volume, so look for a secret with the path. If not found,
2265 * then we cannot generate the secret after a refresh (or restart).
2266 * This may be the case if someone didn't follow instructions and created
2267 * a usage string that although matched with the secret usage string,
2268 * didn't contain the path to the volume. We won't error in that case,
2269 * but we also cannot find the secret. */
2270 sec = virSecretLookupByUsage(conn, VIR_SECRET_USAGE_TYPE_VOLUME,
2271 vol->target.path);
2272 virObjectUnref(conn);
2273 if (!sec)
2274 return 0;
2275
2276 vol->target.encryption->secrets = g_new0(virStorageEncryptionSecret *, 1);
2277 encsec = g_new0(virStorageEncryptionSecret, 1);
2278
2279 vol->target.encryption->nsecrets = 1;
2280 vol->target.encryption->secrets[0] = encsec;
2281
2282 encsec->type = VIR_STORAGE_ENCRYPTION_SECRET_TYPE_PASSPHRASE;
2283 encsec->seclookupdef.type = VIR_SECRET_LOOKUP_TYPE_UUID;
2284 virSecretGetUUID(sec, encsec->seclookupdef.u.uuid);
2285 virObjectUnref(sec);
2286
2287 return 0;
2288 }
2289
2290
2291 /**
2292 * Update info about a volume's capacity/allocation
2293 */
2294 int
virStorageBackendVolRefreshLocal(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol)2295 virStorageBackendVolRefreshLocal(virStoragePoolObj *pool G_GNUC_UNUSED,
2296 virStorageVolDef *vol)
2297 {
2298 int ret;
2299
2300 /* Refresh allocation / capacity / permissions info in case its changed */
2301 if ((ret = virStorageBackendUpdateVolInfo(vol, false,
2302 VIR_STORAGE_VOL_FS_OPEN_FLAGS,
2303 0)) < 0)
2304 return ret;
2305
2306 /* Load any secrets if possible */
2307 return storageBackendLoadDefaultSecrets(vol);
2308 }
2309
2310
2311 static int
storageBackendResizeQemuImg(virStoragePoolObj * pool,virStorageVolDef * vol,unsigned long long capacity)2312 storageBackendResizeQemuImg(virStoragePoolObj *pool,
2313 virStorageVolDef *vol,
2314 unsigned long long capacity)
2315 {
2316 int ret = -1;
2317 const char *type;
2318 virStorageEncryption *enc = vol->target.encryption;
2319 g_autoptr(virCommand) cmd = NULL;
2320 g_autofree char *img_tool = NULL;
2321 g_autofree char *secretPath = NULL;
2322 g_autofree char *secretAlias = NULL;
2323
2324 if (enc && (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_QCOW ||
2325 enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT) &&
2326 (vol->target.format == VIR_STORAGE_FILE_QCOW ||
2327 vol->target.format == VIR_STORAGE_FILE_QCOW2)) {
2328 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
2329 _("resize of qcow2 encrypted image is not supported"));
2330 return -1;
2331 }
2332
2333 img_tool = virFindFileInPath("qemu-img");
2334 if (!img_tool) {
2335 virReportError(VIR_ERR_INTERNAL_ERROR,
2336 "%s", _("unable to find qemu-img"));
2337 return -1;
2338 }
2339
2340 if (vol->target.encryption) {
2341 if (vol->target.format == VIR_STORAGE_FILE_RAW)
2342 type = "luks";
2343 else
2344 type = virStorageFileFormatTypeToString(vol->target.format);
2345
2346 storageBackendLoadDefaultSecrets(vol);
2347
2348 if (storageBackendCreateQemuImgCheckEncryption(vol->target.format,
2349 type, vol) < 0)
2350 goto cleanup;
2351
2352 if (!(secretPath =
2353 storageBackendCreateQemuImgSecretPath(pool, vol)))
2354 goto cleanup;
2355
2356 secretAlias = g_strdup_printf("%s_encrypt0", vol->name);
2357 }
2358
2359 /* Round capacity as qemu-img resize errors out on sizes which are not
2360 * a multiple of 512 */
2361 capacity = VIR_ROUND_UP(capacity, 512);
2362
2363 cmd = virCommandNewArgList(img_tool, "resize", NULL);
2364 if (capacity < vol->target.capacity)
2365 virCommandAddArg(cmd, "--shrink");
2366 if (!vol->target.encryption) {
2367 virCommandAddArg(cmd, vol->target.path);
2368 } else {
2369 if (storageBackendCreateQemuImgSecretObject(cmd, secretPath,
2370 secretAlias) < 0)
2371 goto cleanup;
2372
2373 if (storageBackendResizeQemuImgImageOpts(cmd,
2374 vol->target.format,
2375 vol->target.path,
2376 secretAlias) < 0)
2377 goto cleanup;
2378 }
2379 virCommandAddArgFormat(cmd, "%llu", capacity);
2380
2381 ret = virCommandRun(cmd, NULL);
2382
2383 cleanup:
2384 if (secretPath)
2385 unlink(secretPath);
2386 return ret;
2387 }
2388
2389
2390 /**
2391 * Resize a volume
2392 */
2393 int
virStorageBackendVolResizeLocal(virStoragePoolObj * pool,virStorageVolDef * vol,unsigned long long capacity,unsigned int flags)2394 virStorageBackendVolResizeLocal(virStoragePoolObj *pool,
2395 virStorageVolDef *vol,
2396 unsigned long long capacity,
2397 unsigned int flags)
2398 {
2399 bool pre_allocate = flags & VIR_STORAGE_VOL_RESIZE_ALLOCATE;
2400
2401 virCheckFlags(VIR_STORAGE_VOL_RESIZE_ALLOCATE |
2402 VIR_STORAGE_VOL_RESIZE_SHRINK, -1);
2403
2404 if (vol->target.format == VIR_STORAGE_FILE_RAW && !vol->target.encryption) {
2405 return virFileResize(vol->target.path, capacity, pre_allocate);
2406 } else if (vol->target.format == VIR_STORAGE_FILE_RAW && vol->target.encryption) {
2407 if (pre_allocate) {
2408 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2409 _("preallocate is only supported for an "
2410 "unencrypted raw volume"));
2411 return -1;
2412 }
2413
2414 return storageBackendResizeQemuImg(pool, vol, capacity);
2415 } else if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
2416 return storagePloopResize(vol, capacity);
2417 } else {
2418 if (pre_allocate) {
2419 virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
2420 _("preallocate is only supported for raw "
2421 "type volume"));
2422 return -1;
2423 }
2424
2425 return storageBackendResizeQemuImg(pool, vol, capacity);
2426 }
2427 }
2428
2429
2430 /*
2431 * Check whether the ploop image has snapshots.
2432 * return: -1 - failed to check
2433 * 0 - no snapshots
2434 * 1 - at least one snapshot
2435 */
2436 static int
storageBackendPloopHasSnapshots(char * path)2437 storageBackendPloopHasSnapshots(char *path)
2438 {
2439 char *snap_tool = NULL;
2440 g_autoptr(virCommand) cmd = NULL;
2441 g_autofree char *output = NULL;
2442
2443 snap_tool = virFindFileInPath("ploop");
2444 if (!snap_tool) {
2445 virReportError(VIR_ERR_INTERNAL_ERROR,
2446 "%s", _("unable to find ploop, please install "
2447 "ploop tools"));
2448 return -1;
2449 }
2450
2451 cmd = virCommandNewArgList(snap_tool, "snapshot-list", NULL);
2452 virCommandAddArgFormat(cmd, "%s/DiskDescriptor.xml", path);
2453 virCommandSetOutputBuffer(cmd, &output);
2454
2455 if (virCommandRun(cmd, NULL) < 0)
2456 return -1;
2457
2458 if (!strstr(output, "root.hds."))
2459 return 1;
2460
2461 return 0;
2462 }
2463
2464
2465 int
virStorageBackendVolUploadLocal(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,virStreamPtr stream,unsigned long long offset,unsigned long long len,unsigned int flags)2466 virStorageBackendVolUploadLocal(virStoragePoolObj *pool G_GNUC_UNUSED,
2467 virStorageVolDef *vol,
2468 virStreamPtr stream,
2469 unsigned long long offset,
2470 unsigned long long len,
2471 unsigned int flags)
2472 {
2473 char *target_path = vol->target.path;
2474 bool sparse = flags & VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM;
2475 g_autofree char *path = NULL;
2476
2477 virCheckFlags(VIR_STORAGE_VOL_UPLOAD_SPARSE_STREAM, -1);
2478 /* if volume has target format VIR_STORAGE_FILE_PLOOP
2479 * we need to restore DiskDescriptor.xml, according to
2480 * new contents of volume. This operation will be performed
2481 * when volUpload is fully finished. */
2482 if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
2483 /* Fail if the volume contains snapshots or we failed to check it.*/
2484 int has_snap = storageBackendPloopHasSnapshots(vol->target.path);
2485 if (has_snap < 0) {
2486 return -1;
2487 } else if (!has_snap) {
2488 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2489 _("can't upload volume, all existing snapshots"
2490 " will be lost"));
2491 return -1;
2492 }
2493
2494 path = g_strdup_printf("%s/root.hds", vol->target.path);
2495 target_path = path;
2496 }
2497
2498 /* Not using O_CREAT because the file is required to already exist at
2499 * this point */
2500 return virFDStreamOpenBlockDevice(stream, target_path,
2501 offset, len, sparse, O_WRONLY);
2502 }
2503
2504 int
virStorageBackendVolDownloadLocal(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,virStreamPtr stream,unsigned long long offset,unsigned long long len,unsigned int flags)2505 virStorageBackendVolDownloadLocal(virStoragePoolObj *pool G_GNUC_UNUSED,
2506 virStorageVolDef *vol,
2507 virStreamPtr stream,
2508 unsigned long long offset,
2509 unsigned long long len,
2510 unsigned int flags)
2511 {
2512 char *target_path = vol->target.path;
2513 bool sparse = flags & VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM;
2514 g_autofree char *path = NULL;
2515
2516 virCheckFlags(VIR_STORAGE_VOL_DOWNLOAD_SPARSE_STREAM, -1);
2517 if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
2518 int has_snap = storageBackendPloopHasSnapshots(vol->target.path);
2519 if (has_snap < 0) {
2520 return -1;
2521 } else if (!has_snap) {
2522 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2523 _("can't download volume, all existing snapshots"
2524 " will be lost"));
2525 return -1;
2526 }
2527 path = g_strdup_printf("%s/root.hds", vol->target.path);
2528 target_path = path;
2529 }
2530
2531 return virFDStreamOpenBlockDevice(stream, target_path,
2532 offset, len, sparse, O_RDONLY);
2533 }
2534
2535
2536 /* If the volume we're wiping is already a sparse file, we simply
2537 * truncate and extend it to its original size, filling it with
2538 * zeroes. This behavior is guaranteed by POSIX:
2539 *
2540 * https://www.opengroup.org/onlinepubs/9699919799/functions/ftruncate.html
2541 *
2542 * If fildes refers to a regular file, the ftruncate() function shall
2543 * cause the size of the file to be truncated to length. If the size
2544 * of the file previously exceeded length, the extra data shall no
2545 * longer be available to reads on the file. If the file previously
2546 * was smaller than this size, ftruncate() shall increase the size of
2547 * the file. If the file size is increased, the extended area shall
2548 * appear as if it were zero-filled.
2549 */
2550 static int
storageBackendVolZeroSparseFileLocal(const char * path,off_t size,int fd)2551 storageBackendVolZeroSparseFileLocal(const char *path,
2552 off_t size,
2553 int fd)
2554 {
2555 if (ftruncate(fd, 0) < 0) {
2556 virReportSystemError(errno,
2557 _("Failed to truncate volume with "
2558 "path '%s' to 0 bytes"),
2559 path);
2560 return -1;
2561 }
2562
2563 if (ftruncate(fd, size) < 0) {
2564 virReportSystemError(errno,
2565 _("Failed to truncate volume with "
2566 "path '%s' to %ju bytes"),
2567 path, (uintmax_t)size);
2568 return -1;
2569 }
2570
2571 return 0;
2572 }
2573
2574
2575 static int
storageBackendWipeLocal(const char * path,int fd,unsigned long long wipe_len,size_t writebuf_length,bool zero_end)2576 storageBackendWipeLocal(const char *path,
2577 int fd,
2578 unsigned long long wipe_len,
2579 size_t writebuf_length,
2580 bool zero_end)
2581 {
2582 unsigned long long remaining = 0;
2583 off_t size;
2584 g_autofree char *writebuf = NULL;
2585
2586 writebuf = g_new0(char, writebuf_length);
2587
2588 if (!zero_end) {
2589 if ((size = lseek(fd, 0, SEEK_SET)) < 0) {
2590 virReportSystemError(errno,
2591 _("Failed to seek to the start in volume "
2592 "with path '%s'"),
2593 path);
2594 return -1;
2595 }
2596 } else {
2597 if ((size = lseek(fd, -wipe_len, SEEK_END)) < 0) {
2598 virReportSystemError(errno,
2599 _("Failed to seek to %llu bytes to the end "
2600 "in volume with path '%s'"),
2601 wipe_len, path);
2602 return -1;
2603 }
2604 }
2605
2606 VIR_DEBUG("wiping start: %zd len: %llu", (ssize_t)size, wipe_len);
2607
2608 remaining = wipe_len;
2609 while (remaining > 0) {
2610 size_t write_size = MIN(writebuf_length, remaining);
2611 int written = safewrite(fd, writebuf, write_size);
2612
2613 if (written < 0) {
2614 virReportSystemError(errno,
2615 _("Failed to write %zu bytes to "
2616 "storage volume with path '%s'"),
2617 write_size, path);
2618
2619 return -1;
2620 }
2621
2622 remaining -= written;
2623 }
2624
2625 if (virFileDataSync(fd) < 0) {
2626 virReportSystemError(errno,
2627 _("cannot sync data to volume with path '%s'"),
2628 path);
2629 return -1;
2630 }
2631
2632 VIR_DEBUG("Wrote %llu bytes to volume with path '%s'", wipe_len, path);
2633
2634 return 0;
2635 }
2636
2637
2638 static int
storageBackendVolWipeLocalFile(const char * path,unsigned int algorithm,unsigned long long allocation,bool zero_end)2639 storageBackendVolWipeLocalFile(const char *path,
2640 unsigned int algorithm,
2641 unsigned long long allocation,
2642 bool zero_end)
2643 {
2644 const char *alg_char = NULL;
2645 struct stat st;
2646 VIR_AUTOCLOSE fd = -1;
2647 g_autoptr(virCommand) cmd = NULL;
2648
2649 fd = open(path, O_RDWR);
2650 if (fd == -1) {
2651 virReportSystemError(errno,
2652 _("Failed to open storage volume with path '%s'"),
2653 path);
2654 return -1;
2655 }
2656
2657 if (fstat(fd, &st) == -1) {
2658 virReportSystemError(errno,
2659 _("Failed to stat storage volume with path '%s'"),
2660 path);
2661 return -1;
2662 }
2663
2664 switch ((virStorageVolWipeAlgorithm) algorithm) {
2665 case VIR_STORAGE_VOL_WIPE_ALG_ZERO:
2666 alg_char = "zero";
2667 break;
2668 case VIR_STORAGE_VOL_WIPE_ALG_NNSA:
2669 alg_char = "nnsa";
2670 break;
2671 case VIR_STORAGE_VOL_WIPE_ALG_DOD:
2672 alg_char = "dod";
2673 break;
2674 case VIR_STORAGE_VOL_WIPE_ALG_BSI:
2675 alg_char = "bsi";
2676 break;
2677 case VIR_STORAGE_VOL_WIPE_ALG_GUTMANN:
2678 alg_char = "gutmann";
2679 break;
2680 case VIR_STORAGE_VOL_WIPE_ALG_SCHNEIER:
2681 alg_char = "schneier";
2682 break;
2683 case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER7:
2684 alg_char = "pfitzner7";
2685 break;
2686 case VIR_STORAGE_VOL_WIPE_ALG_PFITZNER33:
2687 alg_char = "pfitzner33";
2688 break;
2689 case VIR_STORAGE_VOL_WIPE_ALG_RANDOM:
2690 alg_char = "random";
2691 break;
2692 case VIR_STORAGE_VOL_WIPE_ALG_TRIM:
2693 virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
2694 _("'trim' algorithm not supported"));
2695 return -1;
2696 case VIR_STORAGE_VOL_WIPE_ALG_LAST:
2697 virReportError(VIR_ERR_INVALID_ARG,
2698 _("unsupported algorithm %d"),
2699 algorithm);
2700 return -1;
2701 }
2702
2703 VIR_DEBUG("Wiping file '%s' with algorithm '%s'", path, alg_char);
2704
2705 if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
2706 cmd = virCommandNew(SCRUB);
2707 virCommandAddArgList(cmd, "-f", "-p", alg_char, path, NULL);
2708
2709 return virCommandRun(cmd, NULL);
2710 }
2711
2712 if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE))
2713 return storageBackendVolZeroSparseFileLocal(path, st.st_size, fd);
2714
2715 return storageBackendWipeLocal(path, fd, allocation, st.st_blksize,
2716 zero_end);
2717 }
2718
2719
2720 static int
storageBackendVolWipePloop(virStorageVolDef * vol,unsigned int algorithm)2721 storageBackendVolWipePloop(virStorageVolDef *vol,
2722 unsigned int algorithm)
2723 {
2724 g_autoptr(virCommand) cmd = NULL;
2725 g_autofree char *target_path = NULL;
2726 g_autofree char *disk_desc = NULL;
2727 g_autofree char *create_tool = NULL;
2728
2729 create_tool = virFindFileInPath("ploop");
2730 if (!create_tool) {
2731 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2732 _("unable to find ploop tools, please install them"));
2733 return -1;
2734 }
2735
2736 target_path = g_strdup_printf("%s/root.hds", vol->target.path);
2737
2738 disk_desc = g_strdup_printf("%s/DiskDescriptor.xml", vol->target.path);
2739
2740 if (storageBackendVolWipeLocalFile(target_path, algorithm,
2741 vol->target.allocation, false) < 0)
2742 return -1;
2743
2744 if (virFileRemove(disk_desc, 0, 0) < 0) {
2745 virReportError(errno, _("Failed to delete DiskDescriptor.xml of volume '%s'"),
2746 vol->target.path);
2747 return -1;
2748 }
2749 if (virFileRemove(target_path, 0, 0) < 0) {
2750 virReportError(errno, _("failed to delete root.hds of volume '%s'"),
2751 vol->target.path);
2752 return -1;
2753 }
2754
2755 cmd = virCommandNewArgList(create_tool, "init", "-s", NULL);
2756
2757 virCommandAddArgFormat(cmd, "%lluM", VIR_DIV_UP(vol->target.capacity,
2758 (1024 * 1024)));
2759 virCommandAddArgList(cmd, "-t", "ext4", NULL);
2760 virCommandAddArg(cmd, target_path);
2761 return virCommandRun(cmd, NULL);
2762 }
2763
2764
2765 int
virStorageBackendVolWipeLocal(virStoragePoolObj * pool G_GNUC_UNUSED,virStorageVolDef * vol,unsigned int algorithm,unsigned int flags)2766 virStorageBackendVolWipeLocal(virStoragePoolObj *pool G_GNUC_UNUSED,
2767 virStorageVolDef *vol,
2768 unsigned int algorithm,
2769 unsigned int flags)
2770 {
2771 int ret = -1;
2772
2773 virCheckFlags(0, -1);
2774
2775 VIR_DEBUG("Wiping volume with path '%s' and algorithm %u",
2776 vol->target.path, algorithm);
2777
2778 if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
2779 ret = storageBackendVolWipePloop(vol, algorithm);
2780 } else {
2781 ret = storageBackendVolWipeLocalFile(vol->target.path, algorithm,
2782 vol->target.allocation, false);
2783 }
2784
2785 return ret;
2786 }
2787
2788
2789 /**
2790 * @pool: storage pool to build
2791 * @dir_create_flags: flags for directory creation
2792 *
2793 * Common code to build a directory based storage pool
2794 *
2795 * Returns 0 on success, -1 on failure
2796 */
2797 int
virStorageBackendBuildLocal(virStoragePoolObj * pool)2798 virStorageBackendBuildLocal(virStoragePoolObj *pool)
2799 {
2800 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
2801 char *p = NULL;
2802 mode_t mode;
2803 bool needs_create_as_uid;
2804 unsigned int dir_create_flags;
2805 g_autofree char *parent = NULL;
2806 int ret;
2807
2808 parent = g_strdup(def->target.path);
2809 if (!(p = strrchr(parent, '/'))) {
2810 virReportError(VIR_ERR_INVALID_ARG,
2811 _("path '%s' is not absolute"),
2812 def->target.path);
2813 return -1;
2814 }
2815
2816 if (p != parent) {
2817 /* assure all directories in the path prior to the final dir
2818 * exist, with default uid/gid/mode. */
2819 *p = '\0';
2820 if (g_mkdir_with_parents(parent, 0777) < 0) {
2821 virReportSystemError(errno, _("cannot create path '%s'"),
2822 parent);
2823 return -1;
2824 }
2825 }
2826
2827 dir_create_flags = VIR_DIR_CREATE_ALLOW_EXIST;
2828 needs_create_as_uid = (def->type == VIR_STORAGE_POOL_NETFS);
2829 mode = def->target.perms.mode;
2830
2831 if (mode == (mode_t)-1 &&
2832 (needs_create_as_uid || !virFileExists(def->target.path)))
2833 mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE;
2834 if (needs_create_as_uid)
2835 dir_create_flags |= VIR_DIR_CREATE_AS_UID;
2836
2837 /* Now create the final dir in the path with the uid/gid/mode
2838 * requested in the config. If the dir already exists, just set
2839 * the perms. */
2840 ret = virDirCreate(def->target.path,
2841 mode,
2842 def->target.perms.uid,
2843 def->target.perms.gid,
2844 dir_create_flags);
2845 if (ret < 0)
2846 return -1;
2847
2848 if (virFileSetCOW(def->target.path,
2849 def->features.cow) < 0)
2850 return -1;
2851
2852 return 0;
2853 }
2854
2855
2856 /**
2857 * @conn connection to report errors against
2858 * @pool storage pool to delete
2859 *
2860 * Delete a directory based storage pool
2861 *
2862 * Returns 0 on success, -1 on error
2863 */
2864 int
virStorageBackendDeleteLocal(virStoragePoolObj * pool,unsigned int flags)2865 virStorageBackendDeleteLocal(virStoragePoolObj *pool,
2866 unsigned int flags)
2867 {
2868 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
2869
2870 virCheckFlags(0, -1);
2871
2872 /* XXX delete all vols first ? */
2873
2874 if (rmdir(def->target.path) < 0) {
2875 virReportSystemError(errno,
2876 _("failed to remove pool '%s'"),
2877 def->target.path);
2878 return -1;
2879 }
2880
2881 return 0;
2882 }
2883
2884
2885 int
virStorageUtilGlusterExtractPoolSources(const char * host,const char * xml,virStoragePoolSourceList * list,virStoragePoolType pooltype)2886 virStorageUtilGlusterExtractPoolSources(const char *host,
2887 const char *xml,
2888 virStoragePoolSourceList *list,
2889 virStoragePoolType pooltype)
2890 {
2891 g_autoptr(xmlDoc) doc = NULL;
2892 g_autoptr(xmlXPathContext) ctxt = NULL;
2893 virStoragePoolSource *src = NULL;
2894 size_t i;
2895 int nnodes;
2896 g_autofree xmlNodePtr *nodes = NULL;
2897 g_autofree char *volname = NULL;
2898
2899 if (!(doc = virXMLParseStringCtxt(xml, _("(gluster_cli_output)"), &ctxt)))
2900 return -1;
2901
2902 if ((nnodes = virXPathNodeSet("//volumes/volume", ctxt, &nodes)) < 0)
2903 return -1;
2904
2905 for (i = 0; i < nnodes; i++) {
2906 ctxt->node = nodes[i];
2907
2908 if (!(src = virStoragePoolSourceListNewSource(list)))
2909 return -1;
2910
2911 if (!(volname = virXPathString("string(./name)", ctxt))) {
2912 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2913 _("failed to extract gluster volume name"));
2914 return -1;
2915 }
2916
2917 if (pooltype == VIR_STORAGE_POOL_NETFS) {
2918 src->format = VIR_STORAGE_POOL_NETFS_GLUSTERFS;
2919 src->dir = g_steal_pointer(&volname);
2920 } else if (pooltype == VIR_STORAGE_POOL_GLUSTER) {
2921 src->dir = g_strdup("/");
2922 src->name = g_steal_pointer(&volname);
2923 } else {
2924 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2925 _("unsupported gluster lookup"));
2926 return -1;
2927 }
2928
2929 src->hosts = g_new0(virStoragePoolSourceHost, 1);
2930 src->nhost = 1;
2931
2932 src->hosts[0].name = g_strdup(host);
2933 }
2934
2935 return nnodes;
2936 }
2937
2938
2939 /**
2940 * virStorageBackendFindGlusterPoolSources:
2941 * @host: host to detect volumes on
2942 * @pooltype: type of the pool
2943 * @list: list of storage pool sources to be filled
2944 * @report: report error if the 'gluster' cli tool is missing
2945 *
2946 * Looks up gluster volumes on @host and fills them to @list.
2947 *
2948 * @pooltype allows to influence the specific differences between netfs and
2949 * native gluster pools. Users should pass only VIR_STORAGE_POOL_NETFS or
2950 * VIR_STORAGE_POOL_GLUSTER.
2951 *
2952 * Returns number of volumes on the host on success, or -1 on error.
2953 */
2954 int
virStorageBackendFindGlusterPoolSources(const char * host,virStoragePoolType pooltype,virStoragePoolSourceList * list,bool report)2955 virStorageBackendFindGlusterPoolSources(const char *host,
2956 virStoragePoolType pooltype,
2957 virStoragePoolSourceList *list,
2958 bool report)
2959 {
2960 int rc;
2961 g_autoptr(virCommand) cmd = NULL;
2962 g_autofree char *glusterpath = NULL;
2963 g_autofree char *outbuf = NULL;
2964
2965 if (!(glusterpath = virFindFileInPath("gluster"))) {
2966 if (report) {
2967 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
2968 _("'gluster' command line tool not found"));
2969 return -1;
2970 } else {
2971 return 0;
2972 }
2973 }
2974
2975 cmd = virCommandNewArgList(glusterpath,
2976 "--xml",
2977 "--log-file=/dev/null",
2978 "volume", "info", "all", NULL);
2979
2980 virCommandAddArgFormat(cmd, "--remote-host=%s", host);
2981 virCommandSetOutputBuffer(cmd, &outbuf);
2982
2983 if (virCommandRun(cmd, &rc) < 0)
2984 return -1;
2985
2986 if (rc != 0)
2987 return 0;
2988
2989 return virStorageUtilGlusterExtractPoolSources(host, outbuf, list, pooltype);
2990 }
2991
2992
2993 #if WITH_BLKID
2994
2995 typedef enum {
2996 VIR_STORAGE_BLKID_PROBE_ERROR = -1,
2997 VIR_STORAGE_BLKID_PROBE_UNDEFINED, /* Nothing found */
2998 VIR_STORAGE_BLKID_PROBE_UNKNOWN, /* Don't know libvirt fs/part type */
2999 VIR_STORAGE_BLKID_PROBE_MATCH, /* Matches the on disk format */
3000 VIR_STORAGE_BLKID_PROBE_DIFFERENT, /* Format doesn't match on disk format */
3001 } virStorageBackendBLKIDProbeResult;
3002
3003 /*
3004 * Utility function to probe for a file system on the device using the
3005 * blkid "superblock" (e.g. default) APIs.
3006 *
3007 * NB: In general this helper will handle the virStoragePoolFormatFileSystem
3008 * format types; however, if called from the Disk path, the initial fstype
3009 * check will fail forcing the usage of the ProbePart helper.
3010 *
3011 * Returns virStorageBackendBLKIDProbeResult enum
3012 */
3013 static virStorageBackendBLKIDProbeResult
virStorageBackendBLKIDFindFS(blkid_probe probe,const char * device,const char * format)3014 virStorageBackendBLKIDFindFS(blkid_probe probe,
3015 const char *device,
3016 const char *format)
3017 {
3018 const char *fstype = NULL;
3019
3020 /* Make sure we're doing a superblock probe from the start */
3021 blkid_probe_enable_superblocks(probe, true);
3022 blkid_probe_reset_superblocks_filter(probe);
3023
3024 if (blkid_do_probe(probe) != 0) {
3025 VIR_INFO("No filesystem found on device '%s'", device);
3026 return VIR_STORAGE_BLKID_PROBE_UNDEFINED;
3027 }
3028
3029 if (blkid_probe_lookup_value(probe, "TYPE", &fstype, NULL) == 0) {
3030 if (STREQ(fstype, format))
3031 return VIR_STORAGE_BLKID_PROBE_MATCH;
3032
3033 return VIR_STORAGE_BLKID_PROBE_DIFFERENT;
3034 }
3035
3036 if (blkid_known_fstype(format) == 0)
3037 return VIR_STORAGE_BLKID_PROBE_UNKNOWN;
3038
3039 return VIR_STORAGE_BLKID_PROBE_ERROR;
3040 }
3041
3042
3043 /*
3044 * Utility function to probe for a partition on the device using the
3045 * blkid "partitions" APIs.
3046 *
3047 * NB: In general, this API will be validating the virStoragePoolFormatDisk
3048 * format types.
3049 *
3050 * Returns virStorageBackendBLKIDProbeResult enum
3051 */
3052 static virStorageBackendBLKIDProbeResult
virStorageBackendBLKIDFindPart(blkid_probe probe,const char * device,const char * format)3053 virStorageBackendBLKIDFindPart(blkid_probe probe,
3054 const char *device,
3055 const char *format)
3056 {
3057 const char *pttype = NULL;
3058
3059 /* A blkid_known_pttype on "dvh" and "pc98" returns a failure;
3060 * however, the blkid_do_probe for "dvh" returns "sgi" and
3061 * for "pc98" it returns "dos". Although "bsd" is recognized,
3062 * it seems that the parted created partition table is not being
3063 * properly recognized. Since each of these will cause problems
3064 * with startup comparison, let's just treat them as UNKNOWN causing
3065 * the caller to fallback to using PARTED */
3066 if (STREQ(format, "dvh") || STREQ(format, "pc98") || STREQ(format, "bsd"))
3067 return VIR_STORAGE_BLKID_PROBE_UNKNOWN;
3068
3069 /* Make sure we're doing a partitions probe from the start */
3070 blkid_probe_enable_partitions(probe, true);
3071 blkid_probe_reset_partitions_filter(probe);
3072
3073 if (blkid_do_probe(probe) != 0) {
3074 VIR_INFO("No partition found on device '%s'", device);
3075 return VIR_STORAGE_BLKID_PROBE_UNDEFINED;
3076 }
3077
3078 if (blkid_probe_lookup_value(probe, "PTTYPE", &pttype, NULL) == 0) {
3079 if (STREQ(pttype, format))
3080 return VIR_STORAGE_BLKID_PROBE_MATCH;
3081
3082 return VIR_STORAGE_BLKID_PROBE_DIFFERENT;
3083 }
3084
3085 if (blkid_known_pttype(format) == 0)
3086 return VIR_STORAGE_BLKID_PROBE_UNKNOWN;
3087
3088 return VIR_STORAGE_BLKID_PROBE_ERROR;
3089 }
3090
3091
3092 /*
3093 * @device: Path to device
3094 * @format: Desired format
3095 * @writelabel: True if desire to write the label
3096 *
3097 * Use the blkid_ APIs in order to get details regarding whether a file
3098 * system or partition exists on the disk already.
3099 *
3100 * Returns:
3101 * -2: Force usage of PARTED for unknown types
3102 * -1: An error was encountered, with error message set
3103 * 0: No file system found
3104 */
3105 static int
virStorageBackendBLKIDFindEmpty(const char * device,const char * format,bool writelabel)3106 virStorageBackendBLKIDFindEmpty(const char *device,
3107 const char *format,
3108 bool writelabel)
3109 {
3110 int ret = -1;
3111 int rc;
3112 blkid_probe probe = NULL;
3113
3114 VIR_DEBUG("Probe for existing filesystem/partition format %s on device %s",
3115 format, device);
3116
3117 if (!(probe = blkid_new_probe_from_filename(device))) {
3118 virReportError(VIR_ERR_STORAGE_PROBE_FAILED,
3119 _("Failed to create filesystem probe for device %s"),
3120 device);
3121 return -1;
3122 }
3123
3124 /* Look for something on FS, if it either doesn't recognize the
3125 * format type as a valid FS format type or it doesn't find a valid
3126 * format type on the device, then perform the same check using
3127 * partition probing. */
3128 rc = virStorageBackendBLKIDFindFS(probe, device, format);
3129 if (rc == VIR_STORAGE_BLKID_PROBE_UNDEFINED ||
3130 rc == VIR_STORAGE_BLKID_PROBE_UNKNOWN) {
3131
3132 rc = virStorageBackendBLKIDFindPart(probe, device, format);
3133 }
3134
3135 switch (rc) {
3136 case VIR_STORAGE_BLKID_PROBE_UNDEFINED:
3137 if (writelabel)
3138 ret = 0;
3139 else
3140 virReportError(VIR_ERR_STORAGE_PROBE_FAILED,
3141 _("Device '%s' is unrecognized, requires build"),
3142 device);
3143 break;
3144
3145 case VIR_STORAGE_BLKID_PROBE_ERROR:
3146 virReportError(VIR_ERR_STORAGE_PROBE_FAILED,
3147 _("Failed to probe for format type '%s'"), format);
3148 break;
3149
3150 case VIR_STORAGE_BLKID_PROBE_UNKNOWN:
3151 ret = -2;
3152 break;
3153
3154 case VIR_STORAGE_BLKID_PROBE_MATCH:
3155 if (writelabel)
3156 virReportError(VIR_ERR_STORAGE_POOL_BUILT,
3157 _("Device '%s' already formatted using '%s'"),
3158 device, format);
3159 else
3160 ret = 0;
3161 break;
3162
3163 case VIR_STORAGE_BLKID_PROBE_DIFFERENT:
3164 if (writelabel)
3165 virReportError(VIR_ERR_STORAGE_POOL_BUILT,
3166 _("Format of device '%s' does not match the "
3167 "expected format '%s', forced overwrite is "
3168 "necessary"),
3169 device, format);
3170 else
3171 virReportError(VIR_ERR_OPERATION_INVALID,
3172 _("Format of device '%s' does not match the "
3173 "expected format '%s'"),
3174 device, format);
3175 break;
3176 }
3177
3178 if (ret == 0 && blkid_do_probe(probe) != 1) {
3179 virReportError(VIR_ERR_STORAGE_PROBE_FAILED, "%s",
3180 _("Found additional probes to run, probing may "
3181 "be incorrect"));
3182 ret = -1;
3183 }
3184
3185 blkid_free_probe(probe);
3186
3187 return ret;
3188 }
3189
3190 #else /* #if WITH_BLKID */
3191
3192 static int
virStorageBackendBLKIDFindEmpty(const char * device G_GNUC_UNUSED,const char * format G_GNUC_UNUSED,bool writelabel G_GNUC_UNUSED)3193 virStorageBackendBLKIDFindEmpty(const char *device G_GNUC_UNUSED,
3194 const char *format G_GNUC_UNUSED,
3195 bool writelabel G_GNUC_UNUSED)
3196 {
3197 return -2;
3198 }
3199
3200 #endif /* #if WITH_BLKID */
3201
3202
3203 #if WITH_STORAGE_DISK
3204
3205 typedef enum {
3206 VIR_STORAGE_PARTED_ERROR = -1,
3207 VIR_STORAGE_PARTED_MATCH, /* Valid label found and matches format */
3208 VIR_STORAGE_PARTED_DIFFERENT, /* Valid label found but not match format */
3209 VIR_STORAGE_PARTED_UNKNOWN, /* No or unrecognized label */
3210 VIR_STORAGE_PARTED_NOPTTYPE, /* Did not find the Partition Table type */
3211 VIR_STORAGE_PARTED_PTTYPE_UNK, /* Partition Table type unknown */
3212 } virStorageBackendPARTEDResult;
3213
3214 /**
3215 * Check for a valid disk label (partition table) on device using
3216 * the PARTED command
3217 *
3218 * returns virStorageBackendPARTEDResult
3219 */
3220 static virStorageBackendPARTEDResult
virStorageBackendPARTEDFindLabel(const char * device,const char * format)3221 virStorageBackendPARTEDFindLabel(const char *device,
3222 const char *format)
3223 {
3224 const char *const args[] = {
3225 device, "print", "--script", NULL,
3226 };
3227 char *start, *end;
3228 int ret = VIR_STORAGE_PARTED_ERROR;
3229 g_autoptr(virCommand) cmd = NULL;
3230 g_autofree char *output = NULL;
3231 g_autofree char *error = NULL;
3232
3233 cmd = virCommandNew(PARTED);
3234 virCommandAddArgSet(cmd, args);
3235 virCommandAddEnvString(cmd, "LC_ALL=C");
3236 virCommandSetOutputBuffer(cmd, &output);
3237 virCommandSetErrorBuffer(cmd, &error);
3238
3239 /* if parted succeeds we have a valid partition table */
3240 ret = virCommandRun(cmd, NULL);
3241 if (ret < 0) {
3242 if ((output && strstr(output, "unrecognised disk label")) ||
3243 (error && strstr(error, "unrecognised disk label"))) {
3244 ret = VIR_STORAGE_PARTED_UNKNOWN;
3245 }
3246 return ret;
3247 }
3248
3249 /* Search for "Partition Table:" in the output. If not present,
3250 * then we cannot validate the partition table type.
3251 */
3252 if (!(start = strstr(output, "Partition Table: ")) ||
3253 !(end = strstr(start, "\n"))) {
3254 VIR_DEBUG("Unable to find tag in output: %s", output);
3255 return VIR_STORAGE_PARTED_NOPTTYPE;
3256 }
3257 start += strlen("Partition Table: ");
3258 *end = '\0';
3259
3260 /* on disk it's "msdos", but we document/use "dos" so deal with it here */
3261 if (STREQ(start, "msdos"))
3262 start += 2;
3263
3264 /* Make sure we know about this type */
3265 if (virStoragePoolFormatDiskTypeFromString(start) < 0)
3266 return VIR_STORAGE_PARTED_PTTYPE_UNK;
3267
3268 /* Does the on disk match what the pool desired? */
3269 if (STREQ(start, format))
3270 return VIR_STORAGE_PARTED_MATCH;
3271
3272 return VIR_STORAGE_PARTED_DIFFERENT;
3273 }
3274
3275
3276 /**
3277 * Determine whether the label on the disk is valid or in a known format
3278 * for the purpose of rewriting the label during build or being able to
3279 * start a pool on a device.
3280 *
3281 * When 'writelabel' is true, if we find a valid disk label on the device,
3282 * then we shouldn't be attempting to write as the volume may contain
3283 * data. Force the usage of the overwrite flag to the build command in
3284 * order to be certain. When the disk label is unrecognized, then it
3285 * should be safe to write.
3286 *
3287 * When 'writelabel' is false, only if we find a valid disk label on the
3288 * device should we allow the start since for this path we won't be
3289 * rewriting the label.
3290 *
3291 * Return: 0 if it's OK
3292 * -1 if something's wrong
3293 */
3294 static int
virStorageBackendPARTEDValidLabel(const char * device,const char * format,bool writelabel)3295 virStorageBackendPARTEDValidLabel(const char *device,
3296 const char *format,
3297 bool writelabel)
3298 {
3299 int ret = -1;
3300 virStorageBackendPARTEDResult check;
3301
3302 check = virStorageBackendPARTEDFindLabel(device, format);
3303 switch (check) {
3304 case VIR_STORAGE_PARTED_ERROR:
3305 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3306 _("Error checking for disk label, failed to get "
3307 "disk partition information"));
3308 break;
3309
3310 case VIR_STORAGE_PARTED_MATCH:
3311 if (writelabel)
3312 virReportError(VIR_ERR_OPERATION_INVALID,
3313 _("Disk label already formatted using '%s'"),
3314 format);
3315 else
3316 ret = 0;
3317 break;
3318
3319 case VIR_STORAGE_PARTED_DIFFERENT:
3320 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3321 _("Known, but different label format present, "
3322 "requires build --overwrite"));
3323 break;
3324
3325 case VIR_STORAGE_PARTED_UNKNOWN:
3326 if (writelabel)
3327 ret = 0;
3328 else
3329 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3330 _("Unrecognized disk label found, requires build"));
3331 break;
3332
3333 case VIR_STORAGE_PARTED_NOPTTYPE:
3334 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3335 _("Unable to determine Partition Type, "
3336 "requires build --overwrite"));
3337 break;
3338
3339 case VIR_STORAGE_PARTED_PTTYPE_UNK:
3340 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
3341 _("Unknown Partition Type, requires build --overwrite"));
3342 break;
3343 }
3344
3345 return ret;
3346 }
3347
3348 #else
3349
3350 static int
virStorageBackendPARTEDValidLabel(const char * device G_GNUC_UNUSED,const char * format G_GNUC_UNUSED,bool writelabel G_GNUC_UNUSED)3351 virStorageBackendPARTEDValidLabel(const char *device G_GNUC_UNUSED,
3352 const char *format G_GNUC_UNUSED,
3353 bool writelabel G_GNUC_UNUSED)
3354 {
3355 return -2;
3356 }
3357
3358
3359 #endif /* #if WITH_STORAGE_DISK */
3360
3361
3362 /* virStorageBackendDeviceIsEmpty:
3363 * @devpath: Path to the device to check
3364 * @format: Desired format string
3365 * @writelabel: True if the caller expects to write the label
3366 *
3367 * Check if the @devpath has some sort of known file system using the
3368 * BLKID API if available.
3369 *
3370 * Returns true if the probe deems the device has nothing valid on it
3371 * or when we cannot check and we're not writing the label.
3372 *
3373 * Returns false if the probe finds something
3374 */
3375 bool
virStorageBackendDeviceIsEmpty(const char * devpath,const char * format,bool writelabel)3376 virStorageBackendDeviceIsEmpty(const char *devpath,
3377 const char *format,
3378 bool writelabel)
3379 {
3380 int ret;
3381
3382 if ((ret = virStorageBackendBLKIDFindEmpty(devpath, format,
3383 writelabel)) == -2)
3384 ret = virStorageBackendPARTEDValidLabel(devpath, format, writelabel);
3385
3386 if (ret == -2 && !writelabel)
3387 ret = 0;
3388
3389 if (ret == -2) {
3390 virReportError(VIR_ERR_OPERATION_INVALID,
3391 _("Unable to probe '%s' for existing data, "
3392 "forced overwrite is necessary"),
3393 devpath);
3394 }
3395
3396 return ret == 0;
3397 }
3398
3399
3400 static int
storageBackendProbeTarget(virStorageSource * target,virStorageEncryption ** encryption)3401 storageBackendProbeTarget(virStorageSource *target,
3402 virStorageEncryption **encryption)
3403 {
3404 int rc;
3405 struct stat sb;
3406 g_autoptr(virStorageSource) meta = NULL;
3407 VIR_AUTOCLOSE fd = -1;
3408
3409 if (encryption)
3410 *encryption = NULL;
3411
3412 if ((rc = virStorageBackendVolOpen(target->path, &sb,
3413 VIR_STORAGE_VOL_FS_PROBE_FLAGS)) < 0)
3414 return rc; /* Take care to propagate rc, it is not always -1 */
3415 fd = rc;
3416
3417 if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &sb) < 0)
3418 return -1;
3419
3420 if (S_ISDIR(sb.st_mode)) {
3421 if (storageBackendIsPloopDir(target->path)) {
3422 if (storageBackendRedoPloopUpdate(target, &sb, &fd,
3423 VIR_STORAGE_VOL_FS_PROBE_FLAGS) < 0)
3424 return -1;
3425 } else {
3426 target->format = VIR_STORAGE_FILE_DIR;
3427 return 0;
3428 }
3429 }
3430
3431 if (!(meta = virStorageSourceGetMetadataFromFD(target->path,
3432 fd,
3433 VIR_STORAGE_FILE_AUTO)))
3434 return -1;
3435
3436 if (meta->backingStoreRaw) {
3437 /* XXX: Remote storage doesn't play nicely with volumes backed by
3438 * remote storage. To avoid trouble, just fake the backing store is RAW
3439 * and put the string from the metadata as the path of the target. */
3440 if (virStorageSourceNewFromBacking(meta, &target->backingStore) < 0 ||
3441 !virStorageSourceIsLocalStorage(target->backingStore)) {
3442 virObjectUnref(target->backingStore);
3443
3444 target->backingStore = virStorageSourceNew();
3445 target->backingStore->type = VIR_STORAGE_TYPE_NETWORK;
3446 target->backingStore->path = meta->backingStoreRaw;
3447 meta->backingStoreRaw = NULL;
3448 target->backingStore->format = VIR_STORAGE_FILE_RAW;
3449 }
3450
3451 if (target->backingStore->format == VIR_STORAGE_FILE_AUTO) {
3452 if ((rc = virStorageFileProbeFormat(target->backingStore->path,
3453 -1, -1)) < 0) {
3454 /* If the backing file is currently unavailable or is
3455 * accessed via remote protocol only log an error, fake the
3456 * format as RAW and continue. Returning -1 here would
3457 * disable the whole storage pool, making it unavailable for
3458 * even maintenance. */
3459 target->backingStore->format = VIR_STORAGE_FILE_RAW;
3460 virReportError(VIR_ERR_INTERNAL_ERROR,
3461 _("cannot probe backing volume format: %s"),
3462 target->backingStore->path);
3463 } else {
3464 target->backingStore->format = rc;
3465 }
3466 }
3467 }
3468
3469 target->format = meta->format;
3470
3471 /* Default to success below this point */
3472 if (meta->capacity)
3473 target->capacity = meta->capacity;
3474
3475 if (meta->clusterSize > 0)
3476 target->clusterSize = meta->clusterSize;
3477
3478 if (encryption && meta->encryption) {
3479 if (meta->encryption->payload_offset != -1)
3480 target->capacity -= meta->encryption->payload_offset * 512;
3481
3482 *encryption = meta->encryption;
3483 meta->encryption = NULL;
3484
3485 /* XXX ideally we'd fill in secret UUID here
3486 * but we cannot guarantee 'conn' is non-NULL
3487 * at this point in time :-( So we only fill
3488 * in secrets when someone first queries a vol
3489 */
3490 }
3491
3492 virBitmapFree(target->features);
3493 target->features = g_steal_pointer(&meta->features);
3494
3495 if (meta->compat) {
3496 VIR_FREE(target->compat);
3497 target->compat = g_steal_pointer(&meta->compat);
3498 }
3499
3500 return 0;
3501 }
3502
3503
3504 /**
3505 * virStorageBackendRefreshVolTargetUpdate:
3506 * @vol: Volume def that needs updating
3507 *
3508 * Attempt to probe the volume in order to get more details.
3509 *
3510 * Returns 0 on success, -2 to ignore failure, -1 on failure
3511 */
3512 int
virStorageBackendRefreshVolTargetUpdate(virStorageVolDef * vol)3513 virStorageBackendRefreshVolTargetUpdate(virStorageVolDef *vol)
3514 {
3515 int err;
3516
3517 /* Real value is filled in during probe */
3518 vol->target.format = VIR_STORAGE_FILE_RAW;
3519
3520 if ((err = storageBackendProbeTarget(&vol->target,
3521 &vol->target.encryption)) < 0) {
3522 if (err == -2) {
3523 return -2;
3524 } else if (err == -3) {
3525 /* The backing file is currently unavailable, its format is not
3526 * explicitly specified, the probe to auto detect the format
3527 * failed: continue with faked RAW format, since AUTO will
3528 * break virStorageVolTargetDefFormat() generating the line
3529 * <format type='...'/>. */
3530 } else {
3531 return -1;
3532 }
3533 }
3534
3535 /* directory based volume */
3536 if (vol->target.format == VIR_STORAGE_FILE_DIR)
3537 vol->type = VIR_STORAGE_VOL_DIR;
3538
3539 if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
3540 vol->type = VIR_STORAGE_VOL_PLOOP;
3541
3542 if (virStorageSourceHasBacking(&vol->target)) {
3543 ignore_value(storageBackendUpdateVolTargetInfo(VIR_STORAGE_VOL_FILE,
3544 vol->target.backingStore,
3545 false,
3546 VIR_STORAGE_VOL_OPEN_DEFAULT, 0));
3547 /* If this failed, the backing file is currently unavailable,
3548 * the capacity, allocation, owner, group and mode are unknown.
3549 * An error message was raised, but we just continue. */
3550 }
3551
3552 return 0;
3553 }
3554
3555
3556 /**
3557 * Iterate over the pool's directory and enumerate all disk images
3558 * within it. This is non-recursive.
3559 */
3560 int
virStorageBackendRefreshLocal(virStoragePoolObj * pool)3561 virStorageBackendRefreshLocal(virStoragePoolObj *pool)
3562 {
3563 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
3564 g_autoptr(DIR) dir = NULL;
3565 struct dirent *ent;
3566 struct statvfs sb;
3567 struct stat statbuf;
3568 int direrr;
3569 g_autoptr(virStorageVolDef) vol = NULL;
3570 VIR_AUTOCLOSE fd = -1;
3571 g_autoptr(virStorageSource) target = NULL;
3572
3573 if (virDirOpen(&dir, def->target.path) < 0)
3574 return -1;
3575
3576 while ((direrr = virDirRead(dir, &ent, def->target.path)) > 0) {
3577 int err;
3578
3579 if (virStringHasControlChars(ent->d_name)) {
3580 VIR_WARN("Ignoring file '%s' with control characters under '%s'",
3581 ent->d_name, def->target.path);
3582 continue;
3583 }
3584
3585 vol = g_new0(virStorageVolDef, 1);
3586
3587 vol->name = g_strdup(ent->d_name);
3588
3589 vol->type = VIR_STORAGE_VOL_FILE;
3590 vol->target.path = g_strdup_printf("%s/%s", def->target.path, vol->name);
3591
3592 vol->key = g_strdup(vol->target.path);
3593
3594 if ((err = virStorageBackendRefreshVolTargetUpdate(vol)) < 0) {
3595 if (err == -2) {
3596 /* Silently ignore non-regular files,
3597 * eg 'lost+found', dangling symbolic link */
3598 virStorageVolDefFree(vol);
3599 vol = NULL;
3600 continue;
3601 }
3602 return -1;
3603 }
3604
3605 if (virStoragePoolObjAddVol(pool, vol) < 0)
3606 return -1;
3607 vol = NULL;
3608 }
3609 if (direrr < 0)
3610 return -1;
3611
3612 target = virStorageSourceNew();
3613
3614 if ((fd = open(def->target.path, O_RDONLY)) < 0) {
3615 virReportSystemError(errno,
3616 _("cannot open path '%s'"),
3617 def->target.path);
3618 return -1;
3619 }
3620
3621 if (fstat(fd, &statbuf) < 0) {
3622 virReportSystemError(errno,
3623 _("cannot stat path '%s'"),
3624 def->target.path);
3625 return -1;
3626 }
3627
3628 if (virStorageBackendUpdateVolTargetInfoFD(target, fd, &statbuf) < 0)
3629 return -1;
3630
3631 /* VolTargetInfoFD doesn't update capacity correctly for the pool case */
3632 if (statvfs(def->target.path, &sb) < 0) {
3633 virReportSystemError(errno,
3634 _("cannot statvfs path '%s'"),
3635 def->target.path);
3636 return -1;
3637 }
3638
3639 def->capacity = ((unsigned long long)sb.f_frsize *
3640 (unsigned long long)sb.f_blocks);
3641 def->available = ((unsigned long long)sb.f_bfree *
3642 (unsigned long long)sb.f_frsize);
3643 def->allocation = def->capacity - def->available;
3644
3645 def->target.perms.mode = target->perms->mode;
3646 def->target.perms.uid = target->perms->uid;
3647 def->target.perms.gid = target->perms->gid;
3648 VIR_FREE(def->target.perms.label);
3649 def->target.perms.label = g_strdup(target->perms->label);
3650
3651 return 0;
3652 }
3653
3654
3655 static char *
virStorageBackendSCSISerial(const char * dev,bool isNPIV)3656 virStorageBackendSCSISerial(const char *dev,
3657 bool isNPIV)
3658 {
3659 int rc;
3660 char *serial = NULL;
3661
3662 if (isNPIV)
3663 rc = virStorageFileGetNPIVKey(dev, &serial);
3664 else
3665 rc = virStorageFileGetSCSIKey(dev, &serial, true);
3666 if (rc == 0 && serial)
3667 return serial;
3668
3669 if (rc == -2)
3670 return NULL;
3671
3672 serial = g_strdup(dev);
3673 return serial;
3674 }
3675
3676
3677 /*
3678 * Attempt to create a new LUN
3679 *
3680 * Returns:
3681 *
3682 * 0 => Success
3683 * -1 => Failure due to some sort of OOM or other fatal issue found when
3684 * attempting to get/update information about a found volume
3685 * -2 => Failure to find a stable path, not fatal, caller can try another
3686 */
3687 static int
virStorageBackendSCSINewLun(virStoragePoolObj * pool,uint32_t host G_GNUC_UNUSED,uint32_t bus,uint32_t target,uint32_t lun,const char * dev)3688 virStorageBackendSCSINewLun(virStoragePoolObj *pool,
3689 uint32_t host G_GNUC_UNUSED,
3690 uint32_t bus,
3691 uint32_t target,
3692 uint32_t lun,
3693 const char *dev)
3694 {
3695 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
3696 int retval = -1;
3697 g_autoptr(virStorageVolDef) vol = NULL;
3698 g_autofree char *devpath = NULL;
3699
3700 /* Check if the pool is using a stable target path. The call to
3701 * virStorageBackendStablePath will fail if the pool target path
3702 * isn't stable and just return the strdup'd 'devpath' anyway.
3703 * This would be indistinguishable to failing to find the stable
3704 * path to the device if the virDirRead loop to search the
3705 * target pool path for our devpath had failed.
3706 */
3707 if (!virStorageBackendPoolPathIsStable(def->target.path) &&
3708 !(STREQ(def->target.path, "/dev") ||
3709 STREQ(def->target.path, "/dev/"))) {
3710 virReportError(VIR_ERR_INVALID_ARG,
3711 _("unable to use target path '%s' for dev '%s'"),
3712 NULLSTR(def->target.path), dev);
3713 return -1;
3714 }
3715
3716 vol = g_new0(virStorageVolDef, 1);
3717
3718 vol->type = VIR_STORAGE_VOL_BLOCK;
3719
3720 /* 'host' is dynamically allocated by the kernel, first come,
3721 * first served, per HBA. As such it isn't suitable for use
3722 * in the volume name. We only need uniqueness per-pool, so
3723 * just leave 'host' out
3724 */
3725 vol->name = g_strdup_printf("unit:%u:%u:%u", bus, target, lun);
3726
3727 devpath = g_strdup_printf("/dev/%s", dev);
3728
3729 VIR_DEBUG("Trying to create volume for '%s'", devpath);
3730
3731 /* Now figure out the stable path
3732 *
3733 * XXX this method is O(N) because it scans the pool target
3734 * dir every time its run. Should figure out a more efficient
3735 * way of doing this...
3736 */
3737 if ((vol->target.path = virStorageBackendStablePath(pool,
3738 devpath,
3739 true)) == NULL)
3740 return -1;
3741
3742 if (STREQ(devpath, vol->target.path) &&
3743 !(STREQ(def->target.path, "/dev") ||
3744 STREQ(def->target.path, "/dev/"))) {
3745
3746 VIR_DEBUG("No stable path found for '%s' in '%s'",
3747 devpath, def->target.path);
3748
3749 return -2;
3750 }
3751
3752 /* Allow a volume read failure to ignore or skip this block file */
3753 if ((retval = virStorageBackendUpdateVolInfo(vol, true,
3754 VIR_STORAGE_VOL_OPEN_DEFAULT,
3755 VIR_STORAGE_VOL_READ_NOERROR)) < 0)
3756 return retval;
3757
3758 vol->key = virStorageBackendSCSISerial(vol->target.path,
3759 (def->source.adapter.type ==
3760 VIR_STORAGE_ADAPTER_TYPE_FC_HOST));
3761 if (!vol->key)
3762 return -1;
3763
3764 def->capacity += vol->target.capacity;
3765 def->allocation += vol->target.allocation;
3766
3767 if (virStoragePoolObjAddVol(pool, vol) < 0)
3768 return -1;
3769 vol = NULL;
3770
3771 return 0;
3772 }
3773
3774
3775
3776 static int
getNewStyleBlockDevice(const char * lun_path,const char * block_name G_GNUC_UNUSED,char ** block_device)3777 getNewStyleBlockDevice(const char *lun_path,
3778 const char *block_name G_GNUC_UNUSED,
3779 char **block_device)
3780 {
3781 g_autoptr(DIR) block_dir = NULL;
3782 struct dirent *block_dirent = NULL;
3783 int direrr;
3784 g_autofree char *block_path = NULL;
3785
3786 block_path = g_strdup_printf("%s/block", lun_path);
3787
3788 VIR_DEBUG("Looking for block device in '%s'", block_path);
3789
3790 if (virDirOpen(&block_dir, block_path) < 0)
3791 return -1;
3792
3793 while ((direrr = virDirRead(block_dir, &block_dirent, block_path)) > 0) {
3794 *block_device = g_strdup(block_dirent->d_name);
3795
3796 VIR_DEBUG("Block device is '%s'", *block_device);
3797
3798 break;
3799 }
3800
3801 if (direrr < 0)
3802 return -1;
3803
3804 return 0;
3805 }
3806
3807
3808 static int
getOldStyleBlockDevice(const char * lun_path G_GNUC_UNUSED,const char * block_name,char ** block_device)3809 getOldStyleBlockDevice(const char *lun_path G_GNUC_UNUSED,
3810 const char *block_name,
3811 char **block_device)
3812 {
3813 char *blockp = NULL;
3814
3815 /* old-style; just parse out the sd */
3816 if (!(blockp = strrchr(block_name, ':'))) {
3817 /* Hm, wasn't what we were expecting; have to give up */
3818 virReportError(VIR_ERR_INTERNAL_ERROR,
3819 _("Failed to parse block name %s"),
3820 block_name);
3821 return -1;
3822 } else {
3823 blockp++;
3824 *block_device = g_strdup(blockp);
3825
3826 VIR_DEBUG("Block device is '%s'", *block_device);
3827 }
3828
3829 return 0;
3830 }
3831
3832
3833 /*
3834 * Search a device entry for the "block" file
3835 *
3836 * Returns
3837 *
3838 * 0 => Found it
3839 * -1 => Fatal error
3840 * -2 => Didn't find in lun_path directory
3841 */
3842 static int
getBlockDevice(uint32_t host,uint32_t bus,uint32_t target,uint32_t lun,char ** block_device)3843 getBlockDevice(uint32_t host,
3844 uint32_t bus,
3845 uint32_t target,
3846 uint32_t lun,
3847 char **block_device)
3848 {
3849 g_autoptr(DIR) lun_dir = NULL;
3850 struct dirent *lun_dirent = NULL;
3851 int direrr;
3852 g_autofree char *lun_path = NULL;
3853
3854 *block_device = NULL;
3855
3856 lun_path = g_strdup_printf("/sys/bus/scsi/devices/%u:%u:%u:%u", host, bus,
3857 target, lun);
3858
3859 if (virDirOpen(&lun_dir, lun_path) < 0)
3860 return -1;
3861
3862 while ((direrr = virDirRead(lun_dir, &lun_dirent, lun_path)) > 0) {
3863 if (STRPREFIX(lun_dirent->d_name, "block")) {
3864 if (strlen(lun_dirent->d_name) == 5) {
3865 if (getNewStyleBlockDevice(lun_path,
3866 lun_dirent->d_name,
3867 block_device) < 0)
3868 return -1;
3869 } else {
3870 if (getOldStyleBlockDevice(lun_path,
3871 lun_dirent->d_name,
3872 block_device) < 0)
3873 return -1;
3874 }
3875 break;
3876 }
3877 }
3878 if (direrr < 0)
3879 return -1;
3880
3881 if (!*block_device)
3882 return -2;
3883
3884 return 0;
3885 }
3886
3887
3888 /* Function to check if the type file in the given sysfs_path is a
3889 * Direct-Access device (i.e. type 0). Return -1 on failure, type of
3890 * the device otherwise.
3891 */
3892 static int
getDeviceType(uint32_t host,uint32_t bus,uint32_t target,uint32_t lun,int * type)3893 getDeviceType(uint32_t host,
3894 uint32_t bus,
3895 uint32_t target,
3896 uint32_t lun,
3897 int *type)
3898 {
3899 char typestr[3];
3900 char *gottype, *p;
3901 FILE *typefile;
3902 g_autofree char *type_path = NULL;
3903
3904 type_path = g_strdup_printf("/sys/bus/scsi/devices/%u:%u:%u:%u/type", host,
3905 bus, target, lun);
3906
3907 typefile = fopen(type_path, "r");
3908 if (typefile == NULL) {
3909 virReportSystemError(errno,
3910 _("Could not find typefile '%s'"),
3911 type_path);
3912 /* there was no type file; that doesn't seem right */
3913 return -1;
3914 }
3915
3916 gottype = fgets(typestr, 3, typefile);
3917 VIR_FORCE_FCLOSE(typefile);
3918
3919 if (gottype == NULL) {
3920 virReportSystemError(errno,
3921 _("Could not read typefile '%s'"),
3922 type_path);
3923 /* we couldn't read the type file; have to give up */
3924 return -1;
3925 }
3926
3927 /* we don't actually care about p, but if you pass NULL and the last
3928 * character is not \0, virStrToLong_i complains
3929 */
3930 if (virStrToLong_i(typestr, &p, 10, type) < 0) {
3931 virReportError(VIR_ERR_INTERNAL_ERROR,
3932 _("Device type '%s' is not an integer"),
3933 typestr);
3934 /* Hm, type wasn't an integer; seems strange */
3935 return -1;
3936 }
3937
3938 VIR_DEBUG("Device type is %d", *type);
3939
3940 return 0;
3941 }
3942
3943
3944 /*
3945 * Process a Logical Unit entry from the scsi host device directory
3946 *
3947 * Returns:
3948 *
3949 * 0 => Found a valid entry
3950 * -1 => Some sort of fatal error
3951 * -2 => non-fatal error or a non-disk entry
3952 */
3953 static int
processLU(virStoragePoolObj * pool,uint32_t host,uint32_t bus,uint32_t target,uint32_t lun)3954 processLU(virStoragePoolObj *pool,
3955 uint32_t host,
3956 uint32_t bus,
3957 uint32_t target,
3958 uint32_t lun)
3959 {
3960 int retval = -1;
3961 int device_type;
3962 g_autofree char *block_device = NULL;
3963
3964 VIR_DEBUG("Processing LU %u:%u:%u:%u",
3965 host, bus, target, lun);
3966
3967 if (getDeviceType(host, bus, target, lun, &device_type) < 0) {
3968 virReportError(VIR_ERR_INTERNAL_ERROR,
3969 _("Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"),
3970 host, bus, target, lun);
3971 return -1;
3972 }
3973
3974 /* We don't create volumes for devices other than disk and cdrom
3975 * devices, but finding a device that isn't one of those types
3976 * isn't an error, either. */
3977 if (!(device_type == VIR_STORAGE_DEVICE_TYPE_DISK ||
3978 device_type == VIR_STORAGE_DEVICE_TYPE_ROM))
3979 return -2;
3980
3981 VIR_DEBUG("%u:%u:%u:%u is a Direct-Access LUN",
3982 host, bus, target, lun);
3983
3984 if ((retval = getBlockDevice(host, bus, target, lun, &block_device)) < 0) {
3985 VIR_DEBUG("Failed to find block device for this LUN");
3986 return retval;
3987 }
3988
3989 retval = virStorageBackendSCSINewLun(pool, host, bus, target, lun,
3990 block_device);
3991 if (retval < 0) {
3992 VIR_DEBUG("Failed to create new storage volume for %u:%u:%u:%u",
3993 host, bus, target, lun);
3994 return retval;
3995 }
3996
3997 VIR_DEBUG("Created new storage volume for %u:%u:%u:%u successfully",
3998 host, bus, target, lun);
3999
4000 return retval;
4001 }
4002
4003
4004 int
virStorageBackendSCSIFindLUs(virStoragePoolObj * pool,uint32_t scanhost)4005 virStorageBackendSCSIFindLUs(virStoragePoolObj *pool,
4006 uint32_t scanhost)
4007 {
4008 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
4009 int retval = 0;
4010 uint32_t bus, target, lun;
4011 const char *device_path = "/sys/bus/scsi/devices";
4012 g_autoptr(DIR) devicedir = NULL;
4013 struct dirent *lun_dirent = NULL;
4014 char devicepattern[64];
4015 int found = 0;
4016
4017 VIR_DEBUG("Discovering LUs on host %u", scanhost);
4018
4019 virWaitForDevices();
4020
4021 if (virDirOpen(&devicedir, device_path) < 0)
4022 return -1;
4023
4024 g_snprintf(devicepattern, sizeof(devicepattern), "%u:%%u:%%u:%%u\n", scanhost);
4025
4026 while ((retval = virDirRead(devicedir, &lun_dirent, device_path)) > 0) {
4027 int rc;
4028
4029 if (sscanf(lun_dirent->d_name, devicepattern,
4030 &bus, &target, &lun) != 3) {
4031 continue;
4032 }
4033
4034 VIR_DEBUG("Found possible LU '%s'", lun_dirent->d_name);
4035
4036 rc = processLU(pool, scanhost, bus, target, lun);
4037 if (rc == -1) {
4038 retval = -1;
4039 break;
4040 }
4041 if (rc == 0)
4042 found++;
4043 }
4044
4045 if (retval < 0)
4046 return -1;
4047
4048 VIR_DEBUG("Found %d LUs for pool %s", found, def->name);
4049
4050 return found;
4051 }
4052
4053
4054 /*
4055 * @path: Path to the device to initialize
4056 * @size: Size to be cleared
4057 *
4058 * Zero out possible partition table information for the specified
4059 * bytes from the start of the @path and from the end of @path
4060 *
4061 * Returns 0 on success, -1 on failure with error message set
4062 */
4063 int
virStorageBackendZeroPartitionTable(const char * path,unsigned long long size)4064 virStorageBackendZeroPartitionTable(const char *path,
4065 unsigned long long size)
4066 {
4067 if (storageBackendVolWipeLocalFile(path, VIR_STORAGE_VOL_WIPE_ALG_ZERO,
4068 size, false) < 0)
4069 return -1;
4070
4071 return storageBackendVolWipeLocalFile(path, VIR_STORAGE_VOL_WIPE_ALG_ZERO,
4072 size, true);
4073 }
4074
4075
4076 /**
4077 * virStorageBackendFileSystemGetPoolSource
4078 * @pool: storage pool object pointer
4079 *
4080 * Allocate/return a string representing the FS storage pool source.
4081 * It is up to the caller to VIR_FREE the allocated string
4082 */
4083 char *
virStorageBackendFileSystemGetPoolSource(virStoragePoolObj * pool)4084 virStorageBackendFileSystemGetPoolSource(virStoragePoolObj *pool)
4085 {
4086 virStoragePoolDef *def = virStoragePoolObjGetDef(pool);
4087 char *src = NULL;
4088
4089 if (def->type == VIR_STORAGE_POOL_NETFS) {
4090 if (def->source.format == VIR_STORAGE_POOL_NETFS_CIFS) {
4091 src = g_strdup_printf("//%s/%s", def->source.hosts[0].name,
4092 def->source.dir);
4093 } else {
4094 src = g_strdup_printf("%s:%s", def->source.hosts[0].name,
4095 def->source.dir);
4096 }
4097 } else {
4098 src = g_strdup(def->source.devices[0].path);
4099 }
4100 return src;
4101 }
4102
4103
4104 static void
virStorageBackendFileSystemMountAddOptions(virCommand * cmd,virStoragePoolDef * def,const char * providedOpts)4105 virStorageBackendFileSystemMountAddOptions(virCommand *cmd,
4106 virStoragePoolDef *def,
4107 const char *providedOpts)
4108 {
4109 g_autofree char *mountOpts = NULL;
4110 g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
4111
4112 if (*default_mount_opts != '\0')
4113 virBufferAsprintf(&buf, "%s,", default_mount_opts);
4114
4115 if (providedOpts)
4116 virBufferAsprintf(&buf, "%s,", providedOpts);
4117
4118 if (def->namespaceData) {
4119 size_t i;
4120 virStoragePoolFSMountOptionsDef *opts = def->namespaceData;
4121 char uuidstr[VIR_UUID_STRING_BUFLEN];
4122
4123 for (i = 0; i < opts->noptions; i++)
4124 virBufferAsprintf(&buf, "%s,", opts->options[i]);
4125
4126 virUUIDFormat(def->uuid, uuidstr);
4127 VIR_WARN("Storage Pool name='%s' uuid='%s' is tainted by custom "
4128 "mount_opts from XML", def->name, uuidstr);
4129 }
4130
4131 virBufferTrim(&buf, ",");
4132 mountOpts = virBufferContentAndReset(&buf);
4133
4134 if (mountOpts)
4135 virCommandAddArgList(cmd, "-o", mountOpts, NULL);
4136 }
4137
4138
4139 static void
virStorageBackendFileSystemMountNFSArgs(virCommand * cmd,const char * src,virStoragePoolDef * def,const char * nfsVers)4140 virStorageBackendFileSystemMountNFSArgs(virCommand *cmd,
4141 const char *src,
4142 virStoragePoolDef *def,
4143 const char *nfsVers)
4144 {
4145 virStorageBackendFileSystemMountAddOptions(cmd, def, nfsVers);
4146 virCommandAddArgList(cmd, src, def->target.path, NULL);
4147 }
4148
4149
4150 static void
virStorageBackendFileSystemMountGlusterArgs(virCommand * cmd,const char * src,virStoragePoolDef * def)4151 virStorageBackendFileSystemMountGlusterArgs(virCommand *cmd,
4152 const char *src,
4153 virStoragePoolDef *def)
4154 {
4155 const char *fmt;
4156
4157 fmt = virStoragePoolFormatFileSystemNetTypeToString(def->source.format);
4158 virStorageBackendFileSystemMountAddOptions(cmd, def, "direct-io-mode=1");
4159 virCommandAddArgList(cmd, "-t", fmt, src, def->target.path, NULL);
4160 }
4161
4162
4163 static void
virStorageBackendFileSystemMountCIFSArgs(virCommand * cmd,const char * src,virStoragePoolDef * def)4164 virStorageBackendFileSystemMountCIFSArgs(virCommand *cmd,
4165 const char *src,
4166 virStoragePoolDef *def)
4167 {
4168 const char *fmt;
4169
4170 fmt = virStoragePoolFormatFileSystemNetTypeToString(def->source.format);
4171 virStorageBackendFileSystemMountAddOptions(cmd, def, "guest");
4172 virCommandAddArgList(cmd, "-t", fmt, src, def->target.path, NULL);
4173 }
4174
4175
4176 static void
virStorageBackendFileSystemMountDefaultArgs(virCommand * cmd,const char * src,virStoragePoolDef * def,const char * nfsVers)4177 virStorageBackendFileSystemMountDefaultArgs(virCommand *cmd,
4178 const char *src,
4179 virStoragePoolDef *def,
4180 const char *nfsVers)
4181 {
4182 const char *fmt;
4183
4184 if (def->type == VIR_STORAGE_POOL_FS)
4185 fmt = virStoragePoolFormatFileSystemTypeToString(def->source.format);
4186 else
4187 fmt = virStoragePoolFormatFileSystemNetTypeToString(def->source.format);
4188 virStorageBackendFileSystemMountAddOptions(cmd, def, nfsVers);
4189 virCommandAddArgList(cmd, "-t", fmt, src, def->target.path, NULL);
4190 }
4191
4192
4193 virCommand *
virStorageBackendFileSystemMountCmd(const char * cmdstr,virStoragePoolDef * def,const char * src)4194 virStorageBackendFileSystemMountCmd(const char *cmdstr,
4195 virStoragePoolDef *def,
4196 const char *src)
4197 {
4198 /* 'mount -t auto' doesn't seem to auto determine nfs (or cifs),
4199 * while plain 'mount' does. We have to craft separate argvs to
4200 * accommodate this */
4201 bool netauto = (def->type == VIR_STORAGE_POOL_NETFS &&
4202 def->source.format == VIR_STORAGE_POOL_NETFS_AUTO);
4203 bool glusterfs = (def->type == VIR_STORAGE_POOL_NETFS &&
4204 def->source.format == VIR_STORAGE_POOL_NETFS_GLUSTERFS);
4205 bool cifsfs = (def->type == VIR_STORAGE_POOL_NETFS &&
4206 def->source.format == VIR_STORAGE_POOL_NETFS_CIFS);
4207 virCommand *cmd = NULL;
4208 g_autofree char *nfsVers = NULL;
4209
4210 if (def->type == VIR_STORAGE_POOL_NETFS && def->source.protocolVer > 0)
4211 nfsVers = g_strdup_printf("nfsvers=%u", def->source.protocolVer);
4212
4213 cmd = virCommandNew(cmdstr);
4214 if (netauto)
4215 virStorageBackendFileSystemMountNFSArgs(cmd, src, def, nfsVers);
4216 else if (glusterfs)
4217 virStorageBackendFileSystemMountGlusterArgs(cmd, src, def);
4218 else if (cifsfs)
4219 virStorageBackendFileSystemMountCIFSArgs(cmd, src, def);
4220 else
4221 virStorageBackendFileSystemMountDefaultArgs(cmd, src, def, nfsVers);
4222 return cmd;
4223 }
4224
4225
4226 virCommand *
virStorageBackendLogicalChangeCmd(const char * cmdstr,virStoragePoolDef * def,bool on)4227 virStorageBackendLogicalChangeCmd(const char *cmdstr,
4228 virStoragePoolDef *def,
4229 bool on)
4230 {
4231 return virCommandNewArgList(cmdstr,
4232 on ? "-aly" : "-aln",
4233 def->source.name,
4234 NULL);
4235 }
4236