~ubuntu-branches/ubuntu/maverick/libvirt/maverick

« back to all changes in this revision

Viewing changes to src/storage_backend_fs.c

Tags: upstream-0.6.4
Import upstream version 0.6.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
62
62
static int vmdk4GetBackingStore(virConnectPtr, char **,
63
63
                                const unsigned char *, size_t);
64
64
 
 
65
typedef int (*createFile)(virConnectPtr conn,
 
66
                          virStorageVolDefPtr vol,
 
67
                          virStorageVolDefPtr inputvol);
 
68
 
65
69
static int track_allocation_progress = 0;
66
70
 
67
71
/* Either 'magic' or 'extension' *must* be provided */
89
93
struct FileTypeInfo const fileTypeInfo[] = {
90
94
    /* Bochs */
91
95
    /* XXX Untested
92
 
    { VIR_STORAGE_VOL_BOCHS, "Bochs Virtual HD Image", NULL,
 
96
    { VIR_STORAGE_VOL_FILE_BOCHS, "Bochs Virtual HD Image", NULL,
93
97
      LV_LITTLE_ENDIAN, 64, 0x20000,
94
98
      32+16+16+4+4+4+4+4, 8, 1, NULL },*/
95
99
    /* CLoop */
666
670
    }
667
671
 
668
672
    if (pool->def->type == VIR_STORAGE_POOL_NETFS) {
669
 
        if (VIR_ALLOC_N(src, strlen(pool->def->source.host.name) +
670
 
                        1 + strlen(pool->def->source.dir) + 1) < 0) {
 
673
        if (virAsprintf(&src, "%s:%s",
 
674
                        pool->def->source.host.name,
 
675
                        pool->def->source.dir) == -1) {
671
676
            virReportOOMError(conn);
672
677
            return -1;
673
678
        }
674
 
        strcpy(src, pool->def->source.host.name);
675
 
        strcat(src, ":");
676
 
        strcat(src, pool->def->source.dir);
 
679
 
677
680
    } else {
678
681
        if ((src = strdup(pool->def->source.devices[0].path)) == NULL) {
679
682
            virReportOOMError(conn);
827
830
 
828
831
        vol->type = VIR_STORAGE_VOL_FILE;
829
832
        vol->target.format = VIR_STORAGE_VOL_FILE_RAW; /* Real value is filled in during probe */
830
 
        if (VIR_ALLOC_N(vol->target.path, strlen(pool->def->target.path) +
831
 
                        1 + strlen(vol->name) + 1) < 0)
 
833
        if (virAsprintf(&vol->target.path, "%s/%s",
 
834
                        pool->def->target.path,
 
835
                        vol->name) == -1)
832
836
            goto no_memory;
833
837
 
834
 
        strcpy(vol->target.path, pool->def->target.path);
835
 
        strcat(vol->target.path, "/");
836
 
        strcat(vol->target.path, vol->name);
837
838
        if ((vol->key = strdup(vol->target.path)) == NULL)
838
839
            goto no_memory;
839
840
 
843
844
                                                &vol->allocation,
844
845
                                                &vol->capacity) < 0)) {
845
846
            if (ret == -1)
846
 
                goto no_memory;
 
847
                goto cleanup;
847
848
            else {
848
849
                /* Silently ignore non-regular files,
849
850
                 * eg '.' '..', 'lost+found' */
883
884
                                                        &vol->backingStore,
884
885
                                                        NULL, NULL, NULL)) < 0) {
885
886
                    if (ret == -1)
886
 
                        goto no_memory;
 
887
                        goto cleanup;
887
888
                    else {
888
889
                        /* Silently ignore non-regular files,
889
890
                         * eg '.' '..', 'lost+found' */
982
983
 
983
984
 
984
985
/**
985
 
 * Allocate a new file as a volume. This is either done directly
986
 
 * for raw/sparse files, or by calling qemu-img/qcow-create for
987
 
 * special kinds of files
 
986
 * Set up a volume definition to be added to a pool's volume list, but
 
987
 * don't do any file creation or allocation. By separating the two processes,
 
988
 * we allow allocation progress reporting (by polling the volume's 'info'
 
989
 * function), and can drop the parent pool lock during the (slow) allocation.
988
990
 */
989
991
static int
990
992
virStorageBackendFileSystemVolCreate(virConnectPtr conn,
991
993
                                     virStoragePoolObjPtr pool,
992
994
                                     virStorageVolDefPtr vol)
993
995
{
994
 
    int fd;
995
996
 
996
 
    if (VIR_ALLOC_N(vol->target.path, strlen(pool->def->target.path) +
997
 
                    1 + strlen(vol->name) + 1) < 0) {
998
 
        virReportOOMError(conn);
999
 
        return -1;
1000
 
    }
1001
997
    vol->type = VIR_STORAGE_VOL_FILE;
1002
 
    strcpy(vol->target.path, pool->def->target.path);
1003
 
    strcat(vol->target.path, "/");
1004
 
    strcat(vol->target.path, vol->name);
 
998
 
 
999
    if (virAsprintf(&vol->target.path, "%s/%s",
 
1000
                    pool->def->target.path,
 
1001
                    vol->name) == -1) {
 
1002
        virReportOOMError(conn);
 
1003
        return -1;
 
1004
    }
 
1005
 
1005
1006
    vol->key = strdup(vol->target.path);
1006
1007
    if (vol->key == NULL) {
1007
1008
        virReportOOMError(conn);
1008
1009
        return -1;
1009
1010
    }
1010
1011
 
1011
 
    if (vol->target.format == VIR_STORAGE_VOL_FILE_RAW) {
1012
 
        if ((fd = open(vol->target.path, O_RDWR | O_CREAT | O_EXCL,
1013
 
                       vol->target.perms.mode)) < 0) {
 
1012
    return 0;
 
1013
}
 
1014
 
 
1015
static int createRaw(virConnectPtr conn,
 
1016
                     virStorageVolDefPtr vol,
 
1017
                     virStorageVolDefPtr inputvol) {
 
1018
    int fd = -1;
 
1019
    int inputfd = -1;
 
1020
    int ret = -1;
 
1021
    unsigned long long remain;
 
1022
    char *buf = NULL;
 
1023
 
 
1024
    if ((fd = open(vol->target.path, O_RDWR | O_CREAT | O_EXCL,
 
1025
                   vol->target.perms.mode)) < 0) {
 
1026
        virReportSystemError(conn, errno,
 
1027
                             _("cannot create path '%s'"),
 
1028
                             vol->target.path);
 
1029
        goto cleanup;
 
1030
    }
 
1031
 
 
1032
    if (inputvol) {
 
1033
        if ((inputfd = open(inputvol->target.path, O_RDONLY)) < 0) {
1014
1034
            virReportSystemError(conn, errno,
1015
 
                                 _("cannot create path '%s'"),
1016
 
                                 vol->target.path);
1017
 
            return -1;
1018
 
        }
1019
 
 
1020
 
        /* Pre-allocate any data if requested */
1021
 
        /* XXX slooooooooooooooooow on non-extents-based file systems */
1022
 
        /* FIXME: Add in progress bars & bg thread if progress bar requested */
1023
 
        if (vol->allocation) {
1024
 
            if (track_allocation_progress) {
1025
 
                unsigned long long remain = vol->allocation;
1026
 
 
1027
 
                while (remain) {
1028
 
                    /* Allocate in chunks of 512MiB: big-enough chunk
1029
 
                     * size and takes approx. 9s on ext3. A progress
1030
 
                     * update every 9s is a fair-enough trade-off
1031
 
                     */
1032
 
                    unsigned long long bytes = 512 * 1024 * 1024;
1033
 
                    int r;
1034
 
 
1035
 
                    if (bytes > remain)
1036
 
                        bytes = remain;
1037
 
                    if ((r = safezero(fd, 0, vol->allocation - remain,
1038
 
                                      bytes)) != 0) {
1039
 
                        virReportSystemError(conn, r,
1040
 
                                             _("cannot fill file '%s'"),
 
1035
                                 _("could not open input path '%s'"),
 
1036
                                 inputvol->target.path);
 
1037
            goto cleanup;
 
1038
        }
 
1039
    }
 
1040
 
 
1041
    /* Seek to the final size, so the capacity is available upfront
 
1042
     * for progress reporting */
 
1043
    if (ftruncate(fd, vol->capacity) < 0) {
 
1044
        virReportSystemError(conn, errno,
 
1045
                             _("cannot extend file '%s'"),
 
1046
                             vol->target.path);
 
1047
        goto cleanup;
 
1048
    }
 
1049
 
 
1050
    remain = vol->capacity;
 
1051
 
 
1052
    if (inputfd != -1) {
 
1053
        int amtread = -1;
 
1054
        size_t bytes = 1024 * 1024;
 
1055
        char zerobuf[512];
 
1056
 
 
1057
        bzero(&zerobuf, sizeof(zerobuf));
 
1058
 
 
1059
        if (VIR_ALLOC_N(buf, bytes) < 0) {
 
1060
            virReportOOMError(conn);
 
1061
            goto cleanup;
 
1062
        }
 
1063
 
 
1064
        while (amtread != 0) {
 
1065
            int amtleft;
 
1066
 
 
1067
            if (remain < bytes)
 
1068
                bytes = remain;
 
1069
 
 
1070
            if ((amtread = saferead(inputfd, buf, bytes)) < 0) {
 
1071
                virReportSystemError(conn, errno,
 
1072
                                     _("failed reading from file '%s'"),
 
1073
                                     inputvol->target.path);
 
1074
                goto cleanup;
 
1075
            }
 
1076
            remain -= amtread;
 
1077
 
 
1078
            /* Loop over amt read in 512 byte increments, looking for sparse
 
1079
             * blocks */
 
1080
            amtleft = amtread;
 
1081
            do {
 
1082
                int interval = ((512 > amtleft) ? amtleft : 512);
 
1083
                int offset = amtread - amtleft;
 
1084
 
 
1085
                if (memcmp(buf+offset, zerobuf, interval) == 0) {
 
1086
                    if (lseek(fd, interval, SEEK_CUR) < 0) {
 
1087
                        virReportSystemError(conn, errno,
 
1088
                                             _("cannot extend file '%s'"),
1041
1089
                                             vol->target.path);
1042
 
                        unlink(vol->target.path);
1043
 
                        close(fd);
1044
 
                        return -1;
 
1090
                        goto cleanup;
1045
1091
                    }
1046
 
                    remain -= bytes;
 
1092
                } else if (safewrite(fd, buf+offset, interval) < 0) {
 
1093
                    virReportSystemError(conn, errno,
 
1094
                                         _("failed writing to file '%s'"),
 
1095
                                         vol->target.path);
 
1096
                    goto cleanup;
 
1097
 
1047
1098
                }
1048
 
            } else { /* No progress bars to be shown */
 
1099
            } while ((amtleft -= 512) > 0);
 
1100
        }
 
1101
    }
 
1102
 
 
1103
    /* Pre-allocate any data if requested */
 
1104
    /* XXX slooooooooooooooooow on non-extents-based file systems */
 
1105
    if (remain) {
 
1106
        if (track_allocation_progress) {
 
1107
 
 
1108
            while (remain) {
 
1109
                /* Allocate in chunks of 512MiB: big-enough chunk
 
1110
                 * size and takes approx. 9s on ext3. A progress
 
1111
                 * update every 9s is a fair-enough trade-off
 
1112
                 */
 
1113
                unsigned long long bytes = 512 * 1024 * 1024;
1049
1114
                int r;
1050
1115
 
1051
 
                if ((r = safezero(fd, 0, 0, vol->allocation)) != 0) {
 
1116
                if (bytes > remain)
 
1117
                    bytes = remain;
 
1118
                if ((r = safezero(fd, 0, vol->allocation - remain,
 
1119
                                  bytes)) != 0) {
1052
1120
                    virReportSystemError(conn, r,
1053
1121
                                         _("cannot fill file '%s'"),
1054
1122
                                         vol->target.path);
1055
 
                    unlink(vol->target.path);
1056
 
                    close(fd);
1057
 
                    return -1;
 
1123
                    goto cleanup;
1058
1124
                }
1059
 
            }
1060
 
        }
1061
 
 
1062
 
        /* Now seek to final size, possibly making the file sparse */
1063
 
        if (ftruncate(fd, vol->capacity) < 0) {
 
1125
                remain -= bytes;
 
1126
            }
 
1127
        } else { /* No progress bars to be shown */
 
1128
            int r;
 
1129
 
 
1130
            if ((r = safezero(fd, 0, 0, remain)) != 0) {
 
1131
                virReportSystemError(conn, r,
 
1132
                                     _("cannot fill file '%s'"),
 
1133
                                     vol->target.path);
 
1134
                goto cleanup;
 
1135
            }
 
1136
        }
 
1137
    }
 
1138
 
 
1139
    if (close(fd) < 0) {
 
1140
        virReportSystemError(conn, errno,
 
1141
                             _("cannot close file '%s'"),
 
1142
                             vol->target.path);
 
1143
        goto cleanup;
 
1144
    }
 
1145
    fd = -1;
 
1146
 
 
1147
    if (inputfd != -1 && close(inputfd) < 0) {
 
1148
        virReportSystemError(conn, errno,
 
1149
                             _("cannot close file '%s'"),
 
1150
                             inputvol->target.path);
 
1151
        goto cleanup;
 
1152
    }
 
1153
    inputfd = -1;
 
1154
 
 
1155
    ret = 0;
 
1156
cleanup:
 
1157
    if (fd != -1)
 
1158
        close(fd);
 
1159
    if (inputfd != -1)
 
1160
        close(inputfd);
 
1161
    VIR_FREE(buf);
 
1162
 
 
1163
    return ret;
 
1164
}
 
1165
 
 
1166
static int createFileDir(virConnectPtr conn,
 
1167
                         virStorageVolDefPtr vol,
 
1168
                         virStorageVolDefPtr inputvol) {
 
1169
    if (inputvol) {
 
1170
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1171
                              "%s",
 
1172
                              _("cannot copy from volume to a directory volume"));
 
1173
        return -1;
 
1174
    }
 
1175
 
 
1176
    if (mkdir(vol->target.path, vol->target.perms.mode) < 0) {
 
1177
        virReportSystemError(conn, errno,
 
1178
                             _("cannot create path '%s'"),
 
1179
                             vol->target.path);
 
1180
        return -1;
 
1181
    }
 
1182
 
 
1183
    return 0;
 
1184
}
 
1185
 
 
1186
#if HAVE_QEMU_IMG
 
1187
static int createQemuImg(virConnectPtr conn,
 
1188
                         virStorageVolDefPtr vol,
 
1189
                         virStorageVolDefPtr inputvol) {
 
1190
    char size[100];
 
1191
 
 
1192
    const char *type = virStorageVolFormatFileSystemTypeToString(vol->target.format);
 
1193
    const char *backingType = vol->backingStore.path ?
 
1194
        virStorageVolFormatFileSystemTypeToString(vol->backingStore.format) : NULL;
 
1195
 
 
1196
    const char *inputBackingPath = (inputvol ? inputvol->backingStore.path
 
1197
                                             : NULL);
 
1198
    const char *inputPath = inputvol ? inputvol->target.path : NULL;
 
1199
    /* Treat input block devices as 'raw' format */
 
1200
    const char *inputType = inputPath ?
 
1201
                            virStorageVolFormatFileSystemTypeToString(inputvol->type == VIR_STORAGE_VOL_BLOCK ? VIR_STORAGE_VOL_FILE_RAW : inputvol->target.format) :
 
1202
                            NULL;
 
1203
 
 
1204
    const char **imgargv;
 
1205
    const char *imgargvnormal[] = {
 
1206
        QEMU_IMG, "create",
 
1207
        "-f", type,
 
1208
        vol->target.path,
 
1209
        size,
 
1210
        NULL,
 
1211
    };
 
1212
    /* XXX including "backingType" here too, once QEMU accepts
 
1213
     * the patches to specify it. It'll probably be -F backingType */
 
1214
    const char *imgargvbacking[] = {
 
1215
        QEMU_IMG, "create",
 
1216
        "-f", type,
 
1217
        "-b", vol->backingStore.path,
 
1218
        vol->target.path,
 
1219
        size,
 
1220
        NULL,
 
1221
    };
 
1222
    const char *convargv[] = {
 
1223
        QEMU_IMG, "convert",
 
1224
        "-f", inputType,
 
1225
        "-O", type,
 
1226
        inputPath,
 
1227
        vol->target.path,
 
1228
        NULL,
 
1229
    };
 
1230
 
 
1231
    if (inputvol) {
 
1232
        imgargv = convargv;
 
1233
    } else if (vol->backingStore.path) {
 
1234
        imgargv = imgargvbacking;
 
1235
    } else {
 
1236
        imgargv = imgargvnormal;
 
1237
    }
 
1238
 
 
1239
    if (type == NULL) {
 
1240
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1241
                              _("unknown storage vol type %d"),
 
1242
                              vol->target.format);
 
1243
        return -1;
 
1244
    }
 
1245
    if (inputvol && inputType == NULL) {
 
1246
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1247
                              _("unknown storage vol type %d"),
 
1248
                              inputvol->target.format);
 
1249
        return -1;
 
1250
    }
 
1251
 
 
1252
    if (vol->backingStore.path) {
 
1253
 
 
1254
        /* XXX: Not strictly required: qemu-img has an option a different
 
1255
         * backing store, not really sure what use it serves though, and it
 
1256
         * may cause issues with lvm. Untested essentially.
 
1257
         */
 
1258
        if (!inputBackingPath ||
 
1259
            !STREQ(inputBackingPath, vol->backingStore.path)) {
 
1260
            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1261
                                  "%s", _("a different backing store can not "
 
1262
                                          "be specified."));
 
1263
            return -1;
 
1264
        }
 
1265
 
 
1266
        if (backingType == NULL) {
 
1267
            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1268
                                  _("unknown storage vol backing store type %d"),
 
1269
                                  vol->backingStore.format);
 
1270
            return -1;
 
1271
        }
 
1272
        if (access(vol->backingStore.path, R_OK) != 0) {
1064
1273
            virReportSystemError(conn, errno,
1065
 
                                 _("cannot extend file '%s'"),
1066
 
                                 vol->target.path);
1067
 
            unlink(vol->target.path);
1068
 
            close(fd);
 
1274
                                 _("inaccessible backing store volume %s"),
 
1275
                                 vol->backingStore.path);
1069
1276
            return -1;
1070
1277
        }
 
1278
    }
 
1279
 
 
1280
    /* Size in KB */
 
1281
    snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
 
1282
 
 
1283
    if (virRun(conn, imgargv, NULL) < 0) {
 
1284
        return -1;
 
1285
    }
 
1286
 
 
1287
    return 0;
 
1288
}
 
1289
 
 
1290
#elif HAVE_QCOW_CREATE
 
1291
/*
 
1292
 * Xen removed the fully-functional qemu-img, and replaced it
 
1293
 * with a partially functional qcow-create. Go figure ??!?
 
1294
 */
 
1295
static int createQemuCreate(virConnectPtr conn,
 
1296
                            virStorageVolDefPtr vol,
 
1297
                            virStorageVolDefPtr inputvol) {
 
1298
    char size[100];
 
1299
    const char *imgargv[4];
 
1300
 
 
1301
    if (inputvol) {
 
1302
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1303
                              "%s",
 
1304
                              _("cannot copy from volume with qcow-create"));
 
1305
        return -1;
 
1306
    }
 
1307
 
 
1308
    if (vol->target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
 
1309
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1310
                              _("unsupported storage vol type %d"),
 
1311
                              vol->target.format);
 
1312
        return -1;
 
1313
    }
 
1314
    if (vol->backingStore.path != NULL) {
 
1315
        virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
 
1316
                              _("copy-on-write image not supported with "
 
1317
                              "qcow-create"));
 
1318
        return -1;
 
1319
    }
 
1320
 
 
1321
    /* Size in MB - yes different units to qemu-img :-( */
 
1322
    snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
 
1323
 
 
1324
    imgargv[0] = QCOW_CREATE;
 
1325
    imgargv[1] = size;
 
1326
    imgargv[2] = vol->target.path;
 
1327
    imgargv[3] = NULL;
 
1328
 
 
1329
    if (virRun(conn, imgargv, NULL) < 0) {
 
1330
        return -1;
 
1331
    }
 
1332
 
 
1333
    return 0;
 
1334
}
 
1335
#endif /* HAVE_QEMU_IMG, elif HAVE_QCOW_CREATE */
 
1336
 
 
1337
static int
 
1338
_virStorageBackendFileSystemVolBuild(virConnectPtr conn,
 
1339
                                     virStorageVolDefPtr vol,
 
1340
                                     virStorageVolDefPtr inputvol)
 
1341
{
 
1342
    int fd;
 
1343
    createFile create_func;
 
1344
 
 
1345
    if (vol->target.format == VIR_STORAGE_VOL_FILE_RAW &&
 
1346
        (!inputvol ||
 
1347
         (inputvol->type == VIR_STORAGE_VOL_BLOCK ||
 
1348
          inputvol->target.format == VIR_STORAGE_VOL_FILE_RAW))) {
 
1349
          /* Raw file creation
 
1350
           * Raw -> Raw copying
 
1351
           * Block dev -> Raw copying
 
1352
           */
 
1353
        create_func = createRaw;
1071
1354
    } else if (vol->target.format == VIR_STORAGE_VOL_FILE_DIR) {
1072
 
        if (mkdir(vol->target.path, vol->target.perms.mode) < 0) {
1073
 
            virReportSystemError(conn, errno,
1074
 
                                 _("cannot create path '%s'"),
1075
 
                                 vol->target.path);
1076
 
            return -1;
1077
 
        }
1078
 
 
1079
 
        if ((fd = open(vol->target.path, O_RDWR)) < 0) {
1080
 
            virReportSystemError(conn, errno,
1081
 
                                 _("cannot read path '%s'"),
1082
 
                                 vol->target.path);
1083
 
            return -1;
1084
 
        }
 
1355
        create_func = createFileDir;
1085
1356
    } else {
1086
1357
#if HAVE_QEMU_IMG
1087
 
        const char *type = virStorageVolFormatFileSystemTypeToString(vol->target.format);
1088
 
        const char *backingType = vol->backingStore.path ?
1089
 
            virStorageVolFormatFileSystemTypeToString(vol->backingStore.format) : NULL;
1090
 
        char size[100];
1091
 
        const char **imgargv;
1092
 
        const char *imgargvnormal[] = {
1093
 
            QEMU_IMG, "create", "-f", type, vol->target.path, size, NULL,
1094
 
        };
1095
 
        /* XXX including "backingType" here too, once QEMU accepts
1096
 
         * the patches to specify it. It'll probably be -F backingType */
1097
 
        const char *imgargvbacking[] = {
1098
 
            QEMU_IMG, "create", "-f", type, "-b", vol->backingStore.path, vol->target.path, size, NULL,
1099
 
        };
1100
 
 
1101
 
        if (type == NULL) {
1102
 
            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
1103
 
                                  _("unknown storage vol type %d"),
1104
 
                                  vol->target.format);
1105
 
            return -1;
1106
 
        }
1107
 
        if (vol->backingStore.path == NULL) {
1108
 
            imgargv = imgargvnormal;
1109
 
        } else {
1110
 
            if (backingType == NULL) {
1111
 
                virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
1112
 
                                      _("unknown storage vol backing store type %d"),
1113
 
                                      vol->backingStore.format);
1114
 
                return -1;
1115
 
            }
1116
 
            if (access(vol->backingStore.path, R_OK) != 0) {
1117
 
                virReportSystemError(conn, errno,
1118
 
                                     _("inaccessible backing store volume %s"),
1119
 
                                     vol->backingStore.path);
1120
 
                return -1;
1121
 
            }
1122
 
 
1123
 
            imgargv = imgargvbacking;
1124
 
        }
1125
 
 
1126
 
        /* Size in KB */
1127
 
        snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
1128
 
 
1129
 
        if (virRun(conn, imgargv, NULL) < 0) {
1130
 
            unlink(vol->target.path);
1131
 
            return -1;
1132
 
        }
1133
 
 
1134
 
        if ((fd = open(vol->target.path, O_RDONLY)) < 0) {
1135
 
            virReportSystemError(conn, errno,
1136
 
                                 _("cannot read path '%s'"),
1137
 
                                 vol->target.path);
1138
 
            unlink(vol->target.path);
1139
 
            return -1;
1140
 
        }
 
1358
        create_func = createQemuImg;
1141
1359
#elif HAVE_QCOW_CREATE
1142
 
        /*
1143
 
         * Xen removed the fully-functional qemu-img, and replaced it
1144
 
         * with a partially functional qcow-create. Go figure ??!?
1145
 
         */
1146
 
        char size[100];
1147
 
        const char *imgargv[4];
1148
 
 
1149
 
        if (vol->target.format != VIR_STORAGE_VOL_FILE_QCOW2) {
1150
 
            virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
1151
 
                                  _("unsupported storage vol type %d"),
1152
 
                                  vol->target.format);
1153
 
            return -1;
1154
 
        }
1155
 
        if (vol->backingStore.path != NULL) {
1156
 
            virStorageReportError(conn, VIR_ERR_NO_SUPPORT,
1157
 
                                  _("copy-on-write image not supported with "
1158
 
                                    "qcow-create"));
1159
 
            return -1;
1160
 
        }
1161
 
 
1162
 
        /* Size in MB - yes different units to qemu-img :-( */
1163
 
        snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
1164
 
 
1165
 
        imgargv[0] = QCOW_CREATE;
1166
 
        imgargv[1] = size;
1167
 
        imgargv[2] = vol->target.path;
1168
 
        imgargv[3] = NULL;
1169
 
 
1170
 
        if (virRun(conn, imgargv, NULL) < 0) {
1171
 
            unlink(vol->target.path);
1172
 
            return -1;
1173
 
        }
1174
 
 
1175
 
        if ((fd = open(vol->target.path, O_RDONLY)) < 0) {
1176
 
            virReportSystemError(conn, errno,
1177
 
                                 _("cannot read path '%s'"),
1178
 
                                 vol->target.path);
1179
 
            unlink(vol->target.path);
1180
 
            return -1;
1181
 
        }
 
1360
        create_func = createQemuCreate;
1182
1361
#else
1183
1362
        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
1184
1363
                              "%s", _("creation of non-raw images "
1187
1366
#endif
1188
1367
    }
1189
1368
 
 
1369
    if (create_func(conn, vol, inputvol) < 0)
 
1370
        return -1;
 
1371
 
 
1372
    if ((fd = open(vol->target.path, O_RDONLY)) < 0) {
 
1373
        virReportSystemError(conn, errno,
 
1374
                             _("cannot read path '%s'"),
 
1375
                             vol->target.path);
 
1376
        return -1;
 
1377
    }
 
1378
 
1190
1379
    /* We can only chown/grp if root */
1191
1380
    if (getuid() == 0) {
1192
1381
        if (fchown(fd, vol->target.perms.uid, vol->target.perms.gid) < 0) {
1193
1382
            virReportSystemError(conn, errno,
1194
1383
                                 _("cannot set file owner '%s'"),
1195
1384
                                 vol->target.path);
1196
 
            unlink(vol->target.path);
1197
1385
            close(fd);
1198
1386
            return -1;
1199
1387
        }
1202
1390
        virReportSystemError(conn, errno,
1203
1391
                             _("cannot set file mode '%s'"),
1204
1392
                             vol->target.path);
1205
 
        unlink(vol->target.path);
1206
1393
        close(fd);
1207
1394
        return -1;
1208
1395
    }
1211
1398
    if (virStorageBackendUpdateVolTargetInfoFD(conn, &vol->target, fd,
1212
1399
                                               &vol->allocation,
1213
1400
                                               NULL) < 0) {
1214
 
        unlink(vol->target.path);
1215
1401
        close(fd);
1216
1402
        return -1;
1217
1403
    }
1220
1406
        virReportSystemError(conn, errno,
1221
1407
                             _("cannot close file '%s'"),
1222
1408
                             vol->target.path);
1223
 
        unlink(vol->target.path);
1224
1409
        return -1;
1225
1410
    }
1226
1411
 
1227
1412
    return 0;
1228
1413
}
1229
1414
 
 
1415
/**
 
1416
 * Allocate a new file as a volume. This is either done directly
 
1417
 * for raw/sparse files, or by calling qemu-img/qcow-create for
 
1418
 * special kinds of files
 
1419
 */
 
1420
static int
 
1421
virStorageBackendFileSystemVolBuild(virConnectPtr conn,
 
1422
                                    virStorageVolDefPtr vol) {
 
1423
    return _virStorageBackendFileSystemVolBuild(conn, vol, NULL);
 
1424
}
 
1425
 
 
1426
/*
 
1427
 * Create a storage vol using 'inputvol' as input
 
1428
 */
 
1429
static int
 
1430
virStorageBackendFileSystemVolBuildFrom(virConnectPtr conn,
 
1431
                                        virStorageVolDefPtr vol,
 
1432
                                        virStorageVolDefPtr inputvol,
 
1433
                                        unsigned int flags ATTRIBUTE_UNUSED) {
 
1434
    return _virStorageBackendFileSystemVolBuild(conn, vol, inputvol);
 
1435
}
1230
1436
 
1231
1437
/**
1232
1438
 * Remove a volume - just unlinks for now
1268
1474
    .buildPool = virStorageBackendFileSystemBuild,
1269
1475
    .refreshPool = virStorageBackendFileSystemRefresh,
1270
1476
    .deletePool = virStorageBackendFileSystemDelete,
 
1477
    .buildVol = virStorageBackendFileSystemVolBuild,
 
1478
    .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
1271
1479
    .createVol = virStorageBackendFileSystemVolCreate,
1272
1480
    .refreshVol = virStorageBackendFileSystemVolRefresh,
1273
1481
    .deleteVol = virStorageBackendFileSystemVolDelete,
1282
1490
    .refreshPool = virStorageBackendFileSystemRefresh,
1283
1491
    .stopPool = virStorageBackendFileSystemStop,
1284
1492
    .deletePool = virStorageBackendFileSystemDelete,
 
1493
    .buildVol = virStorageBackendFileSystemVolBuild,
 
1494
    .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
1285
1495
    .createVol = virStorageBackendFileSystemVolCreate,
1286
1496
    .refreshVol = virStorageBackendFileSystemVolRefresh,
1287
1497
    .deleteVol = virStorageBackendFileSystemVolDelete,
1295
1505
    .refreshPool = virStorageBackendFileSystemRefresh,
1296
1506
    .stopPool = virStorageBackendFileSystemStop,
1297
1507
    .deletePool = virStorageBackendFileSystemDelete,
 
1508
    .buildVol = virStorageBackendFileSystemVolBuild,
 
1509
    .buildVolFrom = virStorageBackendFileSystemVolBuildFrom,
1298
1510
    .createVol = virStorageBackendFileSystemVolCreate,
1299
1511
    .refreshVol = virStorageBackendFileSystemVolRefresh,
1300
1512
    .deleteVol = virStorageBackendFileSystemVolDelete,