Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
View | Details | Raw Unified | Return to bug 700960 | Differences between
and this patch

Collapse All | Expand All

(-)libldm-libldm-0.2.4/src/ldm.c (-149 / +316 lines)
Lines 39-44 Link Here
39
#include "gpt.h"
39
#include "gpt.h"
40
#include "ldm.h"
40
#include "ldm.h"
41
41
42
#define DM_UUID_PREFIX "LDM-"
43
42
#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-" \
44
#define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-" \
43
                 "%02x%02x-%02x%02x%02x%02x%02x%02x"
45
                 "%02x%02x-%02x%02x%02x%02x%02x%02x"
44
#define UUID_VALS(uuid) (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], \
46
#define UUID_VALS(uuid) (uuid)[0], (uuid)[1], (uuid)[2], (uuid)[3], \
Lines 234-239 Link Here
234
    return etype;
236
    return etype;
235
}
237
}
236
238
239
/* We catch log messages generated by device mapper with errno != 0 and store
240
 * them here */
241
static int _dm_err_last_level = 0;
242
static const char *_dm_err_last_file = NULL;
243
static int _dm_err_last_line = 0;
244
static int _dm_err_last_errno = 0;
245
static char *_dm_err_last_msg = NULL;
246
247
static void
248
_dm_log_fn(const int level, const char * const file, const int line,
249
           const int dm_errno, const char *f, ...)
250
{
251
    if (dm_errno == 0) return;
252
253
    _dm_err_last_level = level;
254
    _dm_err_last_file = file;
255
    _dm_err_last_line = line;
256
257
    /* device-mapper doesn't set dm_errno usefully (it only seems to use
258
     * EUNCLASSIFIED), so we capture errno directly and cross our fingers */
259
    _dm_err_last_errno = errno;
260
261
    if (_dm_err_last_msg) {
262
        free(_dm_err_last_msg);
263
        _dm_err_last_msg = NULL;
264
    }
265
266
    va_list ap;
267
    va_start(ap, f);
268
    if (vasprintf(&_dm_err_last_msg, f, ap) == -1) {
269
        g_error("vasprintf");
270
    }
271
    va_end(ap);
272
}
273
237
/* Macros for exporting object properties */
274
/* Macros for exporting object properties */
238
275
239
#define EXPORT_PROP_STRING(object, klass, property)                            \
276
#define EXPORT_PROP_STRING(object, klass, property)                            \
Lines 267-281 Link Here
267
304
268
/* LDM */
305
/* LDM */
269
306
270
#define LDM_GET_PRIVATE(obj)       (G_TYPE_INSTANCE_GET_PRIVATE \
271
        ((obj), LDM_TYPE, LDMPrivate))
272
273
struct _LDMPrivate
307
struct _LDMPrivate
274
{
308
{
275
    GArray *disk_groups;
309
    GArray *disk_groups;
276
};
310
};
277
311
278
G_DEFINE_TYPE(LDM, ldm, G_TYPE_OBJECT)
312
G_DEFINE_TYPE_WITH_PRIVATE(LDM, ldm, G_TYPE_OBJECT)
279
313
280
static void
314
static void
281
ldm_dispose(GObject * const object)
315
ldm_dispose(GObject * const object)
Lines 285-297 Link Here
285
    if (ldm->priv->disk_groups) {
319
    if (ldm->priv->disk_groups) {
286
        g_array_unref(ldm->priv->disk_groups); ldm->priv->disk_groups = NULL;
320
        g_array_unref(ldm->priv->disk_groups); ldm->priv->disk_groups = NULL;
287
    }
321
    }
322
323
    /* Restore default logging function. */
324
    dm_log_with_errno_init(NULL);
288
}
325
}
289
326
290
static void
327
static void
291
ldm_init(LDM * const o)
328
ldm_init(LDM * const o)
292
{
329
{
293
    o->priv = LDM_GET_PRIVATE(o);
330
    o->priv = ldm_get_instance_private(o);
294
    bzero(o->priv, sizeof(*o->priv));
331
    bzero(o->priv, sizeof(*o->priv));
332
333
    /* Provide our logging function. */
334
    dm_log_with_errno_init(_dm_log_fn);
335
    dm_set_name_mangling_mode(DM_STRING_MANGLING_AUTO);
336
    dm_set_uuid_prefix(DM_UUID_PREFIX);
295
}
337
}
296
338
297
static void
339
static void
Lines 300-313 Link Here
300
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
342
    GObjectClass *object_class = G_OBJECT_CLASS(klass);
301
    object_class->dispose = ldm_dispose;
343
    object_class->dispose = ldm_dispose;
302
344
303
    g_type_class_add_private(klass, sizeof(LDMPrivate));
304
}
345
}
305
346
306
/* LDMDiskGroup */
347
/* LDMDiskGroup */
307
348
308
#define LDM_DISK_GROUP_GET_PRIVATE(obj)    (G_TYPE_INSTANCE_GET_PRIVATE \
309
        ((obj), LDM_TYPE_DISK_GROUP, LDMDiskGroupPrivate))
310
311
struct _LDMDiskGroupPrivate
349
struct _LDMDiskGroupPrivate
312
{
350
{
313
    uuid_t guid;
351
    uuid_t guid;
Lines 326-332 Link Here
326
    GArray *comps;
364
    GArray *comps;
327
};
365
};
328
366
329
G_DEFINE_TYPE(LDMDiskGroup, ldm_disk_group, G_TYPE_OBJECT)
367
G_DEFINE_TYPE_WITH_PRIVATE(LDMDiskGroup, ldm_disk_group, G_TYPE_OBJECT)
330
368
331
enum {
369
enum {
332
    PROP_LDM_DISK_GROUP_PROP0,
370
    PROP_LDM_DISK_GROUP_PROP0,
Lines 396-402 Link Here
396
    object_class->finalize = ldm_disk_group_finalize;
434
    object_class->finalize = ldm_disk_group_finalize;
397
    object_class->get_property = ldm_disk_group_get_property;
435
    object_class->get_property = ldm_disk_group_get_property;
398
436
399
    g_type_class_add_private(klass, sizeof(LDMDiskGroupPrivate));
400
437
401
    /**
438
    /**
402
     * LDMDiskGroup:guid:
439
     * LDMDiskGroup:guid:
Lines 431-437 Link Here
431
static void
468
static void
432
ldm_disk_group_init(LDMDiskGroup * const o)
469
ldm_disk_group_init(LDMDiskGroup * const o)
433
{
470
{
434
    o->priv = LDM_DISK_GROUP_GET_PRIVATE(o);
471
    o->priv = ldm_disk_group_get_instance_private(o);
435
    bzero(o->priv, sizeof(*o->priv));
472
    bzero(o->priv, sizeof(*o->priv));
436
}
473
}
437
474
Lines 457-465 Link Here
457
494
458
/* LDMVolume */
495
/* LDMVolume */
459
496
460
#define LDM_VOLUME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \
461
        ((obj), LDM_TYPE_VOLUME, LDMVolumePrivate))
462
463
typedef enum {
497
typedef enum {
464
    _VOLUME_TYPE_GEN = 0x3,
498
    _VOLUME_TYPE_GEN = 0x3,
465
    _VOLUME_TYPE_RAID5 = 0x4
499
    _VOLUME_TYPE_RAID5 = 0x4
Lines 469-474 Link Here
469
{
503
{
470
    guint32 id;
504
    guint32 id;
471
    gchar *name;
505
    gchar *name;
506
    uuid_t guid;
472
    gchar *dgname;
507
    gchar *dgname;
473
508
474
    guint64 size;
509
    guint64 size;
Lines 491-501 Link Here
491
    guint32 _n_comps_i;
526
    guint32 _n_comps_i;
492
};
527
};
493
528
494
G_DEFINE_TYPE(LDMVolume, ldm_volume, G_TYPE_OBJECT)
529
G_DEFINE_TYPE_WITH_PRIVATE(LDMVolume, ldm_volume, G_TYPE_OBJECT)
495
530
496
enum {
531
enum {
497
    PROP_LDM_VOLUME_PROP0,
532
    PROP_LDM_VOLUME_PROP0,
498
    PROP_LDM_VOLUME_NAME,
533
    PROP_LDM_VOLUME_NAME,
534
    PROP_LDM_VOLUME_GUID,
499
    PROP_LDM_VOLUME_TYPE,
535
    PROP_LDM_VOLUME_TYPE,
500
    PROP_LDM_VOLUME_SIZE,
536
    PROP_LDM_VOLUME_SIZE,
501
    PROP_LDM_VOLUME_PART_TYPE,
537
    PROP_LDM_VOLUME_PART_TYPE,
Lines 514-519 Link Here
514
    case PROP_LDM_VOLUME_NAME:
550
    case PROP_LDM_VOLUME_NAME:
515
        g_value_set_string(value, priv->name); break;
551
        g_value_set_string(value, priv->name); break;
516
552
553
    case PROP_LDM_VOLUME_GUID:
554
        {
555
            char guid_str[37];
556
            uuid_unparse(priv->guid, guid_str);
557
            g_value_set_string(value, guid_str);
558
        }
559
        break;
560
517
    case PROP_LDM_VOLUME_TYPE:
561
    case PROP_LDM_VOLUME_TYPE:
518
        g_value_set_enum(value, priv->type); break;
562
        g_value_set_enum(value, priv->type); break;
519
563
Lines 535-540 Link Here
535
}
579
}
536
580
537
EXPORT_PROP_STRING(volume, LDMVolume, name)
581
EXPORT_PROP_STRING(volume, LDMVolume, name)
582
EXPORT_PROP_GUID(volume, LDMVolume)
538
EXPORT_PROP_SCALAR(volume, LDMVolume, size, guint64)
583
EXPORT_PROP_SCALAR(volume, LDMVolume, size, guint64)
539
EXPORT_PROP_SCALAR(volume, LDMVolume, part_type, guint8)
584
EXPORT_PROP_SCALAR(volume, LDMVolume, part_type, guint8)
540
EXPORT_PROP_STRING(volume, LDMVolume, hint)
585
EXPORT_PROP_STRING(volume, LDMVolume, hint)
Lines 577-583 Link Here
577
    object_class->finalize = ldm_volume_finalize;
622
    object_class->finalize = ldm_volume_finalize;
578
    object_class->get_property = ldm_volume_get_property;
623
    object_class->get_property = ldm_volume_get_property;
579
624
580
    g_type_class_add_private(klass, sizeof(LDMVolumePrivate));
581
625
582
    /**
626
    /**
583
     * LDMVolume:name:
627
     * LDMVolume:name:
Lines 594-599 Link Here
594
    );
638
    );
595
639
596
    /**
640
    /**
641
    * LDMVolume:guid:
642
    *
643
    * The GUID of the volume.
644
    */
645
    g_object_class_install_property(
646
        object_class,
647
        PROP_LDM_VOLUME_GUID,
648
        g_param_spec_string(
649
            "guid", "GUID", "The GUID of the volume",
650
            NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS
651
        )
652
    );
653
654
    /**
597
     * LDMVolume:type:
655
     * LDMVolume:type:
598
     *
656
     *
599
     * The volume type: simple, spanned, striped, mirrored or raid5.
657
     * The volume type: simple, spanned, striped, mirrored or raid5.
Lines 677-683 Link Here
677
static void
735
static void
678
ldm_volume_init(LDMVolume * const o)
736
ldm_volume_init(LDMVolume * const o)
679
{
737
{
680
    o->priv = LDM_VOLUME_GET_PRIVATE(o);
738
    o->priv = ldm_volume_get_instance_private(o);
681
    bzero(o->priv, sizeof(*o->priv));
739
    bzero(o->priv, sizeof(*o->priv));
682
740
683
    /* We don't have a trivial way to initialize this array to the correct size
741
    /* We don't have a trivial way to initialize this array to the correct size
Lines 717-725 Link Here
717
775
718
/* LDMPartition */
776
/* LDMPartition */
719
777
720
#define LDM_PARTITION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \
721
        ((obj), LDM_TYPE_PARTITION, LDMPartitionPrivate))
722
723
struct _LDMPartitionPrivate
778
struct _LDMPartitionPrivate
724
{
779
{
725
    guint32 id;
780
    guint32 id;
Lines 735-741 Link Here
735
    LDMDisk *disk;
790
    LDMDisk *disk;
736
};
791
};
737
792
738
G_DEFINE_TYPE(LDMPartition, ldm_partition, G_TYPE_OBJECT)
793
G_DEFINE_TYPE_WITH_PRIVATE(LDMPartition, ldm_partition, G_TYPE_OBJECT)
739
794
740
enum {
795
enum {
741
    PROP_LDM_PARTITION_PROP0,
796
    PROP_LDM_PARTITION_PROP0,
Lines 796-802 Link Here
796
    object_class->finalize = ldm_partition_finalize;
851
    object_class->finalize = ldm_partition_finalize;
797
    object_class->get_property = ldm_partition_get_property;
852
    object_class->get_property = ldm_partition_get_property;
798
853
799
    g_type_class_add_private(klass, sizeof(LDMPartitionPrivate));
800
854
801
    /**
855
    /**
802
     * LDMPartition:name:
856
     * LDMPartition:name:
Lines 846-860 Link Here
846
static void
900
static void
847
ldm_partition_init(LDMPartition * const o)
901
ldm_partition_init(LDMPartition * const o)
848
{
902
{
849
    o->priv = LDM_PARTITION_GET_PRIVATE(o);
903
    o->priv = ldm_partition_get_instance_private(o);
850
    bzero(o->priv, sizeof(*o->priv));
904
    bzero(o->priv, sizeof(*o->priv));
851
}
905
}
852
906
853
/* LDMDisk */
907
/* LDMDisk */
854
908
855
#define LDM_DISK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE \
856
        ((obj), LDM_TYPE_DISK, LDMDiskPrivate))
857
858
struct _LDMDiskPrivate
909
struct _LDMDiskPrivate
859
{
910
{
860
    guint32 id;
911
    guint32 id;
Lines 870-876 Link Here
870
    gchar *device; // NULL until device is found
921
    gchar *device; // NULL until device is found
871
};
922
};
872
923
873
G_DEFINE_TYPE(LDMDisk, ldm_disk, G_TYPE_OBJECT)
924
G_DEFINE_TYPE_WITH_PRIVATE(LDMDisk, ldm_disk, G_TYPE_OBJECT)
874
925
875
enum {
926
enum {
876
    PROP_LDM_DISK_PROP0,
927
    PROP_LDM_DISK_PROP0,
Lines 948-954 Link Here
948
    object_class->finalize = ldm_disk_finalize;
999
    object_class->finalize = ldm_disk_finalize;
949
    object_class->get_property = ldm_disk_get_property;
1000
    object_class->get_property = ldm_disk_get_property;
950
1001
951
    g_type_class_add_private(klass, sizeof(LDMDiskPrivate));
952
1002
953
    /**
1003
    /**
954
     * LDMDisk:name:
1004
     * LDMDisk:name:
Lines 1062-1068 Link Here
1062
static void
1112
static void
1063
ldm_disk_init(LDMDisk * const o)
1113
ldm_disk_init(LDMDisk * const o)
1064
{
1114
{
1065
    o->priv = LDM_DISK_GET_PRIVATE(o);
1115
    o->priv = ldm_disk_get_instance_private(o);
1066
    bzero(o->priv, sizeof(*o->priv));
1116
    bzero(o->priv, sizeof(*o->priv));
1067
}
1117
}
1068
1118
Lines 1514-1521 Link Here
1514
1564
1515
    vol->part_type = *((uint8_t *)vblk); vblk++;
1565
    vol->part_type = *((uint8_t *)vblk); vblk++;
1516
1566
1517
    /* Volume id */
1567
    /* Volume GUID */
1518
    vblk += 16;
1568
    memcpy(&vol->guid, vblk, 16); vblk += 16;
1519
1569
1520
    if (flags & 0x08) vol->id1 = _parse_var_string(&vblk);
1570
    if (flags & 0x08) vol->id1 = _parse_var_string(&vblk);
1521
    if (flags & 0x20) vol->id2 = _parse_var_string(&vblk);
1571
    if (flags & 0x20) vol->id2 = _parse_var_string(&vblk);
Lines 2354-2359 Link Here
2354
}
2404
}
2355
2405
2356
static GString *
2406
static GString *
2407
_dm_part_name(const LDMPartitionPrivate * const part)
2408
{
2409
    const LDMDiskPrivate * const disk = part->disk->priv;
2410
2411
    GString * name = g_string_new("");
2412
    g_string_printf(name, "ldm_part_%s_%s", disk->dgname, part->name);
2413
2414
    return name;
2415
}
2416
2417
static GString *
2418
_dm_part_uuid(const LDMPartitionPrivate * const part)
2419
{
2420
    const LDMDiskPrivate * const disk = part->disk->priv;
2421
2422
    char ldm_disk_guid[37];
2423
    uuid_unparse_lower(disk->guid, ldm_disk_guid);
2424
2425
    GString * dm_uuid = g_string_new("");
2426
    g_string_printf(dm_uuid, "%s%s-%s",
2427
                    DM_UUID_PREFIX, part->name, ldm_disk_guid);
2428
2429
    return dm_uuid;
2430
}
2431
2432
static GString *
2357
_dm_vol_name(const LDMVolumePrivate * const vol)
2433
_dm_vol_name(const LDMVolumePrivate * const vol)
2358
{
2434
{
2359
    GString * r = g_string_new("");
2435
    GString * r = g_string_new("");
Lines 2361-2373 Link Here
2361
    return r;
2437
    return r;
2362
}
2438
}
2363
2439
2364
/* We catch log messages generated by device mapper with errno != 0 and store
2440
static GString *
2365
 * them here */
2441
_dm_vol_uuid(const LDMVolumePrivate * const vol)
2366
static int _dm_err_last_level = 0;
2442
{
2367
static const char *_dm_err_last_file = NULL;
2443
    char ldm_vol_uuid[37];
2368
static int _dm_err_last_line = 0;
2444
    uuid_unparse_lower(vol->guid, ldm_vol_uuid);
2369
static int _dm_err_last_errno = 0;
2445
2370
static char *_dm_err_last_msg = NULL;
2446
    GString * dm_uuid = g_string_new("");
2447
    g_string_printf(dm_uuid, "%s%s-%s",
2448
                    DM_UUID_PREFIX, vol->name, ldm_vol_uuid);
2449
2450
    return dm_uuid;
2451
}
2371
2452
2372
struct dm_target {
2453
struct dm_target {
2373
    guint64 start;
2454
    guint64 start;
Lines 2377-2383 Link Here
2377
};
2458
};
2378
2459
2379
static struct dm_tree *
2460
static struct dm_tree *
2380
_get_device_tree(GError **err)
2461
_dm_get_device_tree(GError **err)
2381
{
2462
{
2382
    struct dm_tree *tree;
2463
    struct dm_tree *tree;
2383
    tree = dm_tree_create();
2464
    tree = dm_tree_create();
Lines 2432-2476 Link Here
2432
    return NULL;
2513
    return NULL;
2433
}
2514
}
2434
2515
2435
static struct dm_tree_node *
2516
/* Returns TRUE if device with specified UUID is found or FALSE otherwise.
2436
_walk_tree(const struct dm_tree * const tree,
2517
 *
2437
           const struct dm_tree_node * const node,
2518
 * Found device node is returned if dm_node is not NULL. In this case dm_tree
2438
           const char * const search)
2519
 * MUST not be NULL as well. And the caller is responsible to free device tree
2520
 * by calling dm_tree_free function.
2521
 */
2522
gboolean
2523
_dm_find_tree_node_by_uuid(const gchar * const uuid,
2524
                                struct dm_tree_node ** dm_node,
2525
                                struct dm_tree ** dm_tree,
2526
                                GError ** const err)
2439
{
2527
{
2440
    void *handle = NULL;
2528
    gboolean r = FALSE;
2441
    struct dm_tree_node *child;
2442
    for (;;) {
2443
        child = dm_tree_next_child(&handle, node, 0);
2444
        if (!child) return NULL;
2445
2446
        const char * const name = dm_tree_node_get_name(child);
2447
        if (!name || *name == '\0') continue;
2448
2529
2449
        if (g_strcmp0(search, name) == 0) return child;
2530
    if (dm_node) {
2531
        g_assert(dm_tree != NULL);
2532
        *dm_node = NULL;
2533
    }
2534
    if (dm_tree) *dm_tree = NULL;
2535
2536
    struct dm_tree *tree = _dm_get_device_tree(err);
2537
    if (tree) {
2538
        struct dm_tree_node *node = dm_tree_find_node_by_uuid(tree, uuid);
2539
        if (node) r = TRUE;
2540
2541
        if (dm_tree)
2542
            *dm_tree = tree;
2543
        else
2544
            dm_tree_free(tree);
2450
2545
2451
        if (dm_tree_node_num_children(child, 0) > 0) {
2546
        if (dm_node) *dm_node = node;
2452
            struct dm_tree_node * const r_search =
2453
                _walk_tree(tree, child, search);
2454
            if (r_search) return r_search;
2455
        }
2456
    }
2547
    }
2548
2549
    return r;
2457
}
2550
}
2458
2551
2459
static struct dm_tree_node *
2552
gchar *
2460
_find_device_tree_node(struct dm_tree * const tree,
2553
_dm_get_device(const gchar * const uuid, GError ** const err)
2461
                       const char * const name)
2462
{
2554
{
2463
    const struct dm_tree_node * const root = dm_tree_find_node(tree, 0, 0);
2555
    GString *r = NULL;
2464
    return _walk_tree(tree, root, name);
2556
2557
    struct dm_tree_node *node = NULL;
2558
    struct dm_tree *tree = NULL;
2559
    struct dm_task *task = NULL;
2560
2561
    if (_dm_find_tree_node_by_uuid(uuid, &node, &tree, err)) {
2562
        const struct dm_info *info = dm_tree_node_get_info(node);
2563
2564
        task = dm_task_create(DM_DEVICE_INFO);
2565
        if (!task) {
2566
            g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2567
                        "dm_task_create: %s", _dm_err_last_msg);
2568
            goto error;
2569
        }
2570
2571
        if (!dm_task_set_major(task, info->major)) {
2572
            g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2573
                        "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s",
2574
                        info->major, _dm_err_last_msg);
2575
            goto error;
2576
        }
2577
2578
        if (!dm_task_set_minor(task, info->minor)) {
2579
            g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2580
                        "DM_DEVICE_INFO: dm_task_set_major(%d) failed: %s",
2581
                        info->minor, _dm_err_last_msg);
2582
            goto error;
2583
        }
2584
2585
        if (!dm_task_run(task)) {
2586
            g_set_error_literal(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2587
                                _dm_err_last_msg);
2588
            goto error;
2589
        }
2590
2591
        const char *dir = dm_dir();
2592
        char *mangled_name = dm_task_get_name_mangled(task);
2593
        r = g_string_new("");
2594
        g_string_printf(r, "%s/%s", dir, mangled_name);
2595
        dm_free(mangled_name);
2596
    }
2597
2598
error:
2599
    if (tree) dm_tree_free(tree);
2600
    if (task) dm_task_destroy(task);
2601
2602
    /* Really FALSE here - don't free but return the character data. */
2603
    return r ? g_string_free(r, FALSE) : NULL;
2465
}
2604
}
2466
2605
2467
gboolean
2606
gboolean
2468
_dm_create(const gchar * const name, uint32_t udev_cookie,
2607
_dm_create(const gchar * const name, const gchar * const uuid,
2469
           const guint n_targets, const struct dm_target * const targets,
2608
           uint32_t udev_cookie, const guint n_targets,
2470
           GError ** const err)
2609
           const struct dm_target * const targets,
2610
           GString **mangled_name, GError ** const err)
2471
{
2611
{
2472
    gboolean r = TRUE;
2612
    gboolean r = TRUE;
2473
2613
2614
    if (mangled_name) *mangled_name = NULL;
2615
2474
    struct dm_task * const task = dm_task_create(DM_DEVICE_CREATE);
2616
    struct dm_task * const task = dm_task_create(DM_DEVICE_CREATE);
2475
    if (!task) {
2617
    if (!task) {
2476
        g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2618
        g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
Lines 2486-2491 Link Here
2486
        r = FALSE; goto out;
2628
        r = FALSE; goto out;
2487
    }
2629
    }
2488
2630
2631
    if (!dm_task_set_uuid(task, uuid)) {
2632
        g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
2633
                    "DM_DEVICE_CREATE: dm_task_set_uuid(%s) failed: %s",
2634
                    uuid, _dm_err_last_msg);
2635
        r = FALSE; goto out;
2636
    }
2637
2489
    for (guint i = 0; i < n_targets; i++) {
2638
    for (guint i = 0; i < n_targets; i++) {
2490
        const struct dm_target * const target = &targets[i];
2639
        const struct dm_target * const target = &targets[i];
2491
2640
Lines 2515-2520 Link Here
2515
        r = FALSE; goto out;
2664
        r = FALSE; goto out;
2516
    }
2665
    }
2517
2666
2667
    if (mangled_name) {
2668
        char *tmp = dm_task_get_name_mangled(task);
2669
        *mangled_name = g_string_new(tmp);
2670
        dm_free(tmp);
2671
    }
2672
2518
out:
2673
out:
2519
    dm_task_destroy(task);
2674
    dm_task_destroy(task);
2520
    return r;
2675
    return r;
Lines 2588-2624 Link Here
2588
    g_string_printf(target.params, "%s %" PRIu64,
2743
    g_string_printf(target.params, "%s %" PRIu64,
2589
                    disk->device, disk->data_start + part->start);
2744
                    disk->device, disk->data_start + part->start);
2590
2745
2591
    /* Ensure we sanitise table names */
2746
    GString *name = _dm_part_name(part);
2592
    char * dgname_esc =
2747
    GString *uuid = _dm_part_uuid(part);
2593
        g_uri_escape_string(disk->dgname,
2748
    GString *mangled_name = NULL;
2594
                            G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT,
2749
2595
                            FALSE);
2750
    if (!_dm_create(name->str, uuid->str, cookie, 1, &target,
2596
    char * partname_esc =
2751
                    &mangled_name, err)) {
2597
        g_uri_escape_string(part->name,
2752
        mangled_name = NULL;
2598
                            G_URI_RESERVED_CHARS_ALLOWED_IN_PATH_ELEMENT,
2599
                            FALSE);
2600
2601
    GString *name = g_string_new("");
2602
    g_string_printf(name, "ldm_part_%s_%s", dgname_esc, partname_esc);
2603
    g_free(dgname_esc);
2604
    g_free(partname_esc);
2605
2606
    if (!_dm_create(name->str, cookie, 1, &target, err)) {
2607
        g_string_free(name, TRUE);
2608
        name = NULL;
2609
    }
2753
    }
2610
2754
2755
    g_string_free(name, TRUE);
2756
    g_string_free(uuid, TRUE);
2611
    g_string_free(target.params, TRUE);
2757
    g_string_free(target.params, TRUE);
2612
    return name;
2758
2759
    return mangled_name;
2760
}
2761
2762
gint
2763
_cmp_component_vol_offset(gconstpointer a, gconstpointer b)
2764
{
2765
    const LDMPartition * const ao = LDM_PARTITION(*(LDMPartition **)a);
2766
    const LDMPartition * const bo = LDM_PARTITION(*(LDMPartition **)b);
2767
2768
    return ao->priv->vol_offset - bo->priv->vol_offset;
2613
}
2769
}
2614
2770
2615
static GString *
2771
static GString *
2616
_dm_create_spanned(const LDMVolumePrivate * const vol, GError ** const err)
2772
_dm_create_spanned(const LDMVolumePrivate * const vol, GError ** const err)
2617
{
2773
{
2618
    static GString *name = NULL;
2774
    GString *name = NULL;
2619
    guint i = 0;
2775
    guint i = 0;
2620
    struct dm_target *targets = g_malloc(sizeof(*targets) * vol->parts->len);
2776
    struct dm_target *targets = g_malloc(sizeof(*targets) * vol->parts->len);
2621
2777
2778
    g_array_sort(vol->parts, _cmp_component_vol_offset);
2779
2622
    uint64_t pos = 0;
2780
    uint64_t pos = 0;
2623
    for (; i < vol->parts->len; i++) {
2781
    for (; i < vol->parts->len; i++) {
2624
        const LDMPartition * const part_o =
2782
        const LDMPartition * const part_o =
Lines 2661-2672 Link Here
2661
    }
2819
    }
2662
2820
2663
    name = _dm_vol_name(vol);
2821
    name = _dm_vol_name(vol);
2822
    GString *uuid = _dm_vol_uuid(vol);
2664
2823
2665
    if (!_dm_create(name->str, cookie, vol->parts->len, targets, err)) {
2824
    if (!_dm_create(name->str, uuid->str, cookie, vol->parts->len, targets,
2825
                    NULL, err)) {
2666
        g_string_free(name, TRUE);
2826
        g_string_free(name, TRUE);
2667
        name = NULL;
2827
        name = NULL;
2668
    }
2828
    }
2669
2829
2830
    g_string_free(uuid, TRUE);
2670
    dm_udev_wait(cookie);
2831
    dm_udev_wait(cookie);
2671
2832
2672
out:
2833
out:
Lines 2682-2688 Link Here
2682
static GString *
2843
static GString *
2683
_dm_create_striped(const LDMVolumePrivate * const vol, GError ** const err)
2844
_dm_create_striped(const LDMVolumePrivate * const vol, GError ** const err)
2684
{
2845
{
2685
    static GString *name = NULL;
2846
    GString *name = NULL;
2686
    struct dm_target target;
2847
    struct dm_target target;
2687
2848
2688
    target.start = 0;
2849
    target.start = 0;
Lines 2718-2729 Link Here
2718
    }
2879
    }
2719
2880
2720
    name = _dm_vol_name(vol);
2881
    name = _dm_vol_name(vol);
2882
    GString *uuid = _dm_vol_uuid(vol);
2721
2883
2722
    if (!_dm_create(name->str, cookie, 1, &target, err)) {
2884
    if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) {
2723
        g_string_free(name, TRUE);
2885
        g_string_free(name, TRUE);
2724
        name = NULL;
2886
        name = NULL;
2725
    }
2887
    }
2726
2888
2889
    g_string_free(uuid, TRUE);
2727
    dm_udev_wait(cookie);
2890
    dm_udev_wait(cookie);
2728
2891
2729
out:
2892
out:
Lines 2754-2759 Link Here
2754
        goto out;
2917
        goto out;
2755
    }
2918
    }
2756
2919
2920
    const char *dir = dm_dir();
2921
2757
    int found = 0;
2922
    int found = 0;
2758
    for (guint i = 0; i < vol->parts->len; i++) {
2923
    for (guint i = 0; i < vol->parts->len; i++) {
2759
        const LDMPartition * const part_o =
2924
        const LDMPartition * const part_o =
Lines 2774-2780 Link Here
2774
2939
2775
        found++;
2940
        found++;
2776
        g_array_append_val(devices, chunk);
2941
        g_array_append_val(devices, chunk);
2777
        g_string_append_printf(target.params, " - /dev/mapper/%s", chunk->str);
2942
        g_string_append_printf(target.params, " - %s/%s", dir, chunk->str);
2778
    }
2943
    }
2779
2944
2780
    if (found == 0) {
2945
    if (found == 0) {
Lines 2792-2803 Link Here
2792
    }
2957
    }
2793
2958
2794
    name = _dm_vol_name(vol);
2959
    name = _dm_vol_name(vol);
2960
    GString *uuid = _dm_vol_uuid(vol);
2795
2961
2796
    if (!_dm_create(name->str, cookie, 1, &target, err)) {
2962
    if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) {
2797
        g_string_free(name, TRUE);
2963
        g_string_free(name, TRUE);
2798
        name = NULL;
2964
        name = NULL;
2799
    }
2965
    }
2800
2966
2967
    g_string_free(uuid, TRUE);
2801
    dm_udev_wait(cookie);
2968
    dm_udev_wait(cookie);
2802
2969
2803
    g_array_unref(devices); devices = NULL;
2970
    g_array_unref(devices); devices = NULL;
Lines 2816-2821 Link Here
2816
    }
2983
    }
2817
2984
2818
    g_string_free(target.params, TRUE);
2985
    g_string_free(target.params, TRUE);
2986
2819
    return name;
2987
    return name;
2820
}
2988
}
2821
2989
Lines 2823-2828 Link Here
2823
_dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err)
2991
_dm_create_raid5(const LDMVolumePrivate * const vol, GError ** const err)
2824
{
2992
{
2825
    GString *name = NULL;
2993
    GString *name = NULL;
2994
    GString *uuid = NULL;
2826
    struct dm_target target;
2995
    struct dm_target target;
2827
2996
2828
    target.start = 0;
2997
    target.start = 0;
Lines 2842-2847 Link Here
2842
        goto out;
3011
        goto out;
2843
    }
3012
    }
2844
3013
3014
    const char *dir = dm_dir();
3015
2845
    guint n_found = 0;
3016
    guint n_found = 0;
2846
    for (guint i = 0; i < vol->parts->len; i++) {
3017
    for (guint i = 0; i < vol->parts->len; i++) {
2847
        const LDMPartition * const part_o =
3018
        const LDMPartition * const part_o =
Lines 2862-2868 Link Here
2862
3033
2863
        n_found++;
3034
        n_found++;
2864
        g_array_append_val(devices, chunk);
3035
        g_array_append_val(devices, chunk);
2865
        g_string_append_printf(target.params, " - /dev/mapper/%s", chunk->str);
3036
        g_string_append_printf(target.params, " - %s/%s", dir, chunk->str);
2866
    }
3037
    }
2867
3038
2868
    if (n_found < vol->parts->len - 1) {
3039
    if (n_found < vol->parts->len - 1) {
Lines 2880-2891 Link Here
2880
    }
3051
    }
2881
3052
2882
    name = _dm_vol_name(vol);
3053
    name = _dm_vol_name(vol);
3054
    uuid = _dm_vol_uuid(vol);
2883
3055
2884
    if (!_dm_create(name->str, cookie, 1, &target, err)) {
3056
    if (!_dm_create(name->str, uuid->str, cookie, 1, &target, NULL, err)) {
2885
        g_string_free(name, TRUE); name = NULL;
3057
        g_string_free(name, TRUE); name = NULL;
3058
        g_string_free(uuid, TRUE);
2886
        goto out;
3059
        goto out;
2887
    }
3060
    }
2888
3061
3062
    g_string_free(uuid, TRUE);
2889
    dm_udev_wait(cookie);
3063
    dm_udev_wait(cookie);
2890
3064
2891
    g_array_unref(devices); devices = NULL;
3065
    g_array_unref(devices); devices = NULL;
Lines 2904-2968 Link Here
2904
    }
3078
    }
2905
3079
2906
    g_string_free(target.params, TRUE);
3080
    g_string_free(target.params, TRUE);
3081
2907
    return name;
3082
    return name;
2908
}
3083
}
2909
3084
2910
static void
3085
GString *
2911
_dm_log_fn(const int level, const char * const file, const int line,
3086
ldm_volume_dm_get_name(const LDMVolume * const o)
2912
           const int dm_errno, const char *f, ...)
2913
{
3087
{
2914
    if (dm_errno == 0) return;
3088
    return _dm_vol_name(o->priv);
2915
3089
}
2916
    _dm_err_last_level = level;
2917
    _dm_err_last_file = file;
2918
    _dm_err_last_line = line;
2919
2920
    /* device-mapper doesn't set dm_errno usefully (it only seems to use
2921
     * EUNCLASSIFIED), so we capture errno directly and cross our fingers */
2922
    _dm_err_last_errno = errno;
2923
3090
2924
    if (_dm_err_last_msg) {
3091
gchar *
2925
        free(_dm_err_last_msg);
3092
ldm_partition_dm_get_device(const LDMPartition * const o, GError ** const err)
2926
        _dm_err_last_msg = NULL;
3093
{
2927
    }
3094
    GString *uuid = _dm_part_uuid(o->priv);
3095
    gchar* r = _dm_get_device(uuid->str, err);
3096
    g_string_free(uuid, TRUE);
2928
3097
2929
    va_list ap;
3098
    return r;
2930
    va_start(ap, f);
2931
    if (vasprintf(&_dm_err_last_msg, f, ap) == -1) {
2932
        g_error("vasprintf");
2933
    }
2934
    va_end(ap);
2935
}
3099
}
2936
3100
2937
GString *
3101
gchar *
2938
ldm_volume_dm_get_name(const LDMVolume * const o)
3102
ldm_volume_dm_get_device(const LDMVolume * const o, GError ** const err)
2939
{
3103
{
2940
    return _dm_vol_name(o->priv);
3104
    GString *uuid = _dm_vol_uuid(o->priv);
3105
    gchar* r = _dm_get_device(uuid->str, err);
3106
    g_string_free(uuid, TRUE);
3107
3108
    return r;
2941
}
3109
}
2942
3110
2943
gboolean
3111
gboolean
2944
ldm_volume_dm_create(const LDMVolume * const o, GString **created,
3112
ldm_volume_dm_create(const LDMVolume * const o, GString **created,
2945
                     GError ** const err)
3113
                     GError ** const err)
2946
{
3114
{
2947
    const LDMVolumePrivate * const vol = o->priv;
3115
    if (created) *created = NULL;
2948
3116
2949
    /* We should really store the previous logging function and restore it
3117
    const LDMVolumePrivate * const vol = o->priv;
2950
     * afterwards, but the API doesn't allow this. */
2951
    dm_log_with_errno_init(_dm_log_fn);
2952
3118
2953
    /* Check if the device already exists */
3119
    /* Check if the device already exists */
2954
    struct dm_tree *tree = _get_device_tree(err);
3120
    GString *uuid = _dm_vol_uuid(vol);
2955
    if (!tree) return FALSE;
3121
    if (_dm_find_tree_node_by_uuid(uuid->str, NULL, NULL, err)) {
2956
3122
        g_string_free(uuid, TRUE);
2957
    GString *name = _dm_vol_name(vol);
2958
    struct dm_tree_node *node = _find_device_tree_node(tree, name->str);
2959
    if (node) {
2960
        dm_tree_free(tree); tree = NULL;
2961
        return TRUE;
3123
        return TRUE;
2962
    }
3124
    }
2963
    dm_tree_free(tree); tree = NULL;
3125
    g_string_free(uuid, TRUE);
2964
    g_string_free(name, TRUE);
2965
3126
3127
    GString *name = NULL;
2966
    switch (vol->type) {
3128
    switch (vol->type) {
2967
    case LDM_VOLUME_TYPE_SIMPLE:
3129
    case LDM_VOLUME_TYPE_SIMPLE:
2968
    case LDM_VOLUME_TYPE_SPANNED:
3130
    case LDM_VOLUME_TYPE_SPANNED:
Lines 2986-3023 Link Here
2986
        g_error("Unexpected volume type: %u", vol->type);
3148
        g_error("Unexpected volume type: %u", vol->type);
2987
    }
3149
    }
2988
3150
2989
    dm_log_with_errno_init(NULL);
3151
    gboolean r = name != NULL;
3152
    
3153
    if (created)
3154
        *created = name;
3155
    else if (name)
3156
        g_string_free(name, TRUE);
2990
3157
2991
    if (created && name) *created = name;
3158
    return r;
2992
    return name == NULL ? FALSE : TRUE;
2993
}
3159
}
2994
3160
2995
gboolean
3161
gboolean
2996
ldm_volume_dm_remove(const LDMVolume * const o, GString **removed,
3162
ldm_volume_dm_remove(const LDMVolume * const o, GString **removed,
2997
                     GError ** const err)
3163
                     GError ** const err)
2998
{
3164
{
3165
    if (removed) *removed = NULL;
3166
2999
    const LDMVolumePrivate * const vol = o->priv;
3167
    const LDMVolumePrivate * const vol = o->priv;
3000
3168
3001
    /* We should really store the previous logging function and restore it
3169
    gboolean r = FALSE;
3002
     * afterwards, but the API doesn't allow this. */
3003
    dm_log_with_errno_init(_dm_log_fn);
3004
3170
3005
    struct dm_tree *tree = _get_device_tree(err);
3171
    struct dm_tree *tree = NULL;
3006
    if (!tree) return FALSE;
3172
    struct dm_tree_node *node = NULL;
3007
3173
3008
    gboolean r = FALSE;
3174
    GString *uuid = _dm_vol_uuid(vol);
3175
    gboolean found = _dm_find_tree_node_by_uuid(uuid->str, &node, &tree, err);
3176
    g_string_free(uuid, TRUE);
3009
3177
3010
    GString *name = _dm_vol_name(vol);
3178
    GString *name = NULL;
3011
    struct dm_tree_node *node = _find_device_tree_node(tree, name->str);
3179
    if (found) {
3012
    if (node) {
3013
        uint32_t cookie;
3180
        uint32_t cookie;
3014
        if (!dm_udev_create_cookie(&cookie)) {
3181
        if (!dm_udev_create_cookie(&cookie)) {
3015
            g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
3182
            g_set_error(err, LDM_ERROR, LDM_ERROR_EXTERNAL,
3016
                        "dm_udev_create_cookie: %s", _dm_err_last_msg);
3183
                        "dm_udev_create_cookie: %s", _dm_err_last_msg);
3017
            g_string_free(name, TRUE); name = NULL;
3018
            goto out;
3184
            goto out;
3019
        }
3185
        }
3020
3186
3187
        name = _dm_vol_name(vol);
3021
        if (!_dm_remove(name->str, cookie, err)) {
3188
        if (!_dm_remove(name->str, cookie, err)) {
3022
            g_string_free(name, TRUE); name = NULL;
3189
            g_string_free(name, TRUE); name = NULL;
3023
            goto out;
3190
            goto out;
Lines 3032-3048 Link Here
3032
        }
3199
        }
3033
3200
3034
        dm_udev_wait(cookie);
3201
        dm_udev_wait(cookie);
3035
    } else {
3036
        g_string_free(name, TRUE); name = NULL;
3037
    }
3202
    }
3038
3203
3039
    r = TRUE;
3204
    r = TRUE;
3040
3205
3041
out:
3206
out:
3042
    dm_tree_free(tree);
3207
    if (tree) dm_tree_free(tree);
3043
    if (removed && name) *removed = name;
3044
3208
3045
    dm_log_with_errno_init(NULL);
3209
    if (removed)
3210
        *removed = name;
3211
    else if (name)
3212
        g_string_free(name, TRUE);
3046
3213
3047
    return r;
3214
    return r;
3048
}
3215
}

Return to bug 700960