glusterfs

Форк
0
/
glusterd-lvm-snapshot.c 
968 строк · 29.0 Кб
1
/*
2
   Copyright (c) 2013-2014 Red Hat, Inc. <http://www.redhat.com>
3
   This file is part of GlusterFS.
4

5
   This file is licensed to you under your choice of the GNU Lesser
6
   General Public License, version 3 or any later version (LGPLv3 or
7
   later), or the GNU General Public License, version 2 (GPLv2), in all
8
   cases as published by the Free Software Foundation.
9
*/
10

11
#include <inttypes.h>
12
#include <sys/types.h>
13
#include <unistd.h>
14

15
#include "glusterd-messages.h"
16

17
#include "glusterd-utils.h"
18
#include "glusterd-snapshot-utils.h"
19

20
#include <glusterfs/dict.h>
21
#include <glusterfs/run.h>
22

23
#include <glusterfs/syscall.h>
24
#include <glusterfs/lvm-defaults.h>
25

26
#if defined(GF_LINUX_HOST_OS)
27
#include <mntent.h>
28
#else
29
#include "mntent_compat.h"
30
#endif
31

32
extern char snap_mount_dir[VALID_GLUSTERD_PATHMAX];
33

34
static int32_t
35
glusterd_origin_device(char *device, char **origin_device)
36
{
37
    int ret = -1;
38
    char msg[4096] = "";
39
    char origin_name[PATH_MAX] = "";
40
    char *ptr = NULL;
41
    char *snap_device = NULL;
42
    xlator_t *this = NULL;
43
    runner_t runner = {
44
        0,
45
    };
46
    int32_t len = 0;
47

48
    this = THIS;
49
    GF_ASSERT(this);
50

51
    snprintf(msg, sizeof(msg), "Get origin device for the device %s", device);
52

53
    runinit(&runner);
54

55
    runner_add_args(&runner, "/sbin/lvs", "--noheadings", "-o", "origin",
56
                    device, NULL);
57
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
58
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
59

60
    ret = runner_start(&runner);
61
    if (ret == -1) {
62
        gf_msg(this->name, GF_LOG_DEBUG, errno, GD_MSG_TPOOL_GET_FAIL,
63
               "Failed to get thin pool "
64
               "name for device %s",
65
               device);
66
        runner_end(&runner);
67
        goto out;
68
    }
69

70
    ptr = fgets(origin_name, sizeof(origin_name),
71
                runner_chio(&runner, STDOUT_FILENO));
72
    if (!ptr || !strlen(origin_name)) {
73
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_TPOOL_GET_FAIL,
74
               "Failed to get origin device "
75
               "for device %s",
76
               device);
77
        runner_end(&runner);
78
        ret = -1;
79
        goto out;
80
    }
81

82
    runner_end(&runner);
83

84
    snap_device = gf_strdup(device);
85
    len = gf_asprintf(origin_device, "%s/%s", dirname(snap_device),
86
                      origin_name);
87

88
    if (len < 0) {
89
        ret = -1;
90
        goto out;
91
    }
92

93
    ret = 0;
94

95
out:
96
    if (snap_device)
97
        GF_FREE(snap_device);
98

99
    return ret;
100
}
101

102
/* This function will check whether the given brick_path
103
 * is a thinly provisioned LV or not.
104
 *
105
 * @param brick_path    Brick Path
106
 *
107
 * @return              _gf_true if LV is thin else _gf_false
108
 */
109
gf_boolean_t
110
glusterd_lvm_probe(char *brick_path)
111
{
112
    int ret = -1;
113
    char msg[1024] = "";
114
    char pool_name[PATH_MAX] = "";
115
    char *ptr = NULL;
116
    char *device = NULL;
117
    xlator_t *this = NULL;
118
    runner_t runner = {
119
        0,
120
    };
121
    gf_boolean_t is_thin = _gf_false;
122

123
    this = THIS;
124

125
    GF_VALIDATE_OR_GOTO("glusterd", this, out);
126
    GF_VALIDATE_OR_GOTO(this->name, brick_path, out);
127

128
    device = glusterd_get_brick_mount_device(brick_path);
129
    if (!device) {
130
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_GET_INFO_FAIL,
131
               "getting device name for "
132
               "the brick %s failed",
133
               brick_path);
134
        goto out;
135
    }
136

137
    if (!glusterd_is_cmd_available("/sbin/lvs")) {
138
        gf_msg(this->name, GF_LOG_DEBUG, 0, GD_MSG_COMMAND_NOT_FOUND,
139
               "LVM commands not found");
140
        ret = -1;
141
        goto out;
142
    }
143

144
    snprintf(msg, sizeof(msg), "Get thin pool name for device %s", device);
145

146
    runinit(&runner);
147

148
    runner_add_args(&runner, "/sbin/lvs", "--noheadings", "-o", "pool_lv",
149
                    device, NULL);
150
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
151
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
152

153
    ret = runner_start(&runner);
154
    if (ret == -1) {
155
        gf_msg(this->name, GF_LOG_DEBUG, errno, GD_MSG_TPOOL_GET_FAIL,
156
               "Failed to get thin pool "
157
               "name for device %s",
158
               device);
159
        runner_end(&runner);
160
        goto out;
161
    }
162

163
    ptr = fgets(pool_name, sizeof(pool_name),
164
                runner_chio(&runner, STDOUT_FILENO));
165
    if (!ptr || !strlen(pool_name)) {
166
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_TPOOL_GET_FAIL,
167
               "Failed to get pool name "
168
               "for device %s",
169
               device);
170
        runner_end(&runner);
171
        ret = -1;
172
        goto out;
173
    }
174

175
    runner_end(&runner);
176

177
    /* Trim all the whitespaces. */
178
    ptr = gf_trim(pool_name);
179

180
    /* If the LV has thin pool associated with this
181
     * then it is a thinly provisioned LV else it is
182
     * regular LV */
183
    if (0 != ptr[0]) {
184
        is_thin = _gf_true;
185
    }
186

187
out:
188
    if (device) {
189
        GF_FREE(device);
190
    }
191

192
    return is_thin;
193
}
194

195
/* This function is called to get the device path of the snap lvm. Usually
196
   if /dev/mapper/<group-name>-<lvm-name> is the device for the lvm,
197
   then the snap device will be /dev/<group-name>/<snapname>.
198
   This function takes care of building the path for the snap device.
199
*/
200

201
char *
202
glusterd_lvm_snapshot_device(char *brick_path, char *snapname)
203
{
204
    char snap[PATH_MAX] = "";
205
    char msg[1024] = "";
206
    char volgroup[PATH_MAX] = "";
207
    char *device = NULL;
208
    char *snap_device = NULL;
209
    xlator_t *this = NULL;
210
    runner_t runner = {
211
        0,
212
    };
213
    char *ptr = NULL;
214
    int ret = -1;
215

216
    this = THIS;
217
    GF_ASSERT(this);
218
    if (!brick_path) {
219
        gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
220
               "brick path is NULL");
221
        goto out;
222
    }
223
    if (!snapname) {
224
        gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
225
               "snapname is NULL");
226
        goto out;
227
    }
228

229
    device = glusterd_get_brick_mount_device(brick_path);
230
    if (!device) {
231
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_GET_INFO_FAIL,
232
               "getting device name for "
233
               "the brick %s failed",
234
               brick_path);
235
        goto out;
236
    }
237

238
    runinit(&runner);
239
    runner_add_args(&runner, "/sbin/lvs", "--noheadings", "-o", "vg_name",
240
                    device, NULL);
241
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
242
    snprintf(msg, sizeof(msg), "Get volume group for device %s", device);
243
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
244
    ret = runner_start(&runner);
245
    if (ret == -1) {
246
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_VG_GET_FAIL,
247
               "Failed to get volume group "
248
               "for device %s",
249
               device);
250
        runner_end(&runner);
251
        goto out;
252
    }
253
    ptr = fgets(volgroup, sizeof(volgroup),
254
                runner_chio(&runner, STDOUT_FILENO));
255
    if (!ptr || !strlen(volgroup)) {
256
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_VG_GET_FAIL,
257
               "Failed to get volume group "
258
               "for snap %s",
259
               snapname);
260
        runner_end(&runner);
261
        ret = -1;
262
        goto out;
263
    }
264
    runner_end(&runner);
265

266
    snprintf(snap, sizeof(snap), "/dev/%s/%s", gf_trim(volgroup), snapname);
267
    snap_device = gf_strdup(snap);
268
    if (!snap_device) {
269
        gf_msg(this->name, GF_LOG_WARNING, ENOMEM, GD_MSG_NO_MEMORY,
270
               "Cannot copy the snapshot device name for snapname: %s",
271
               snapname);
272
    }
273

274
out:
275
    if (device) {
276
        GF_FREE(device);
277
    }
278
    return snap_device;
279
}
280

281
/* This function actually calls the command (or the API) for taking the
282
   snapshot of the backend brick filesystem. If this is successful,
283
   then call the glusterd_snap_create function to create the snap object
284
   for glusterd
285
*/
286
int32_t
287
glusterd_lvm_snapshot_create_clone(glusterd_brickinfo_t *snap_brickinfo,
288
                                   int clone, char *snapname,
289
                                   char *snap_volume_id, char *clonename,
290
                                   char *clone_volume_id, int32_t brick_num)
291
{
292
    char msg[4096] = "";
293
    char buf[PATH_MAX] = "";
294
    char *ptr = NULL;
295
    char *origin_device = NULL;
296
    char brick_snapname[NAME_MAX] = "";
297
    char *snap_device = NULL;
298
    int ret = -1;
299
    gf_boolean_t match = _gf_false;
300
    runner_t runner = {
301
        0,
302
    };
303
    xlator_t *this = THIS;
304

305
    GF_ASSERT(snap_brickinfo);
306

307
    if (!clone) {
308
        origin_device = glusterd_get_brick_mount_device(
309
            snap_brickinfo->origin_path);
310
        if (!origin_device) {
311
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_GET_INFO_FAIL,
312
                   "getting device name for "
313
                   "the brick %s failed",
314
                   snap_brickinfo->origin_path);
315
            goto out;
316
        }
317
    } else {
318
        ret = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
319
                       snap_volume_id, brick_num);
320
        if (ret < 0) {
321
            goto out;
322
        }
323

324
        /* If the Snapshot created before origin_path is introduced */
325
        if (strlen(snap_brickinfo->device_path) > 0) {
326
            ret = glusterd_origin_device(snap_brickinfo->device_path,
327
                                         &origin_device);
328
            if (ret) {
329
                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_GET_INFO_FAIL,
330
                       "getting origin_device for "
331
                       "the snap %s(Brick: %s) failed",
332
                       snapname, snap_brickinfo->path);
333
                goto out;
334
            }
335
        } else
336
            origin_device = glusterd_lvm_snapshot_device(
337
                snap_brickinfo->origin_path, brick_snapname);
338

339
        if (!origin_device) {
340
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICK_GET_INFO_FAIL,
341
                   "getting device name for "
342
                   "the snap %s(Brick: %s) failed",
343
                   snapname, snap_brickinfo->path);
344
            goto out;
345
        }
346
    }
347

348
    /* Figuring out if setactivationskip flag is supported or not */
349
    runinit(&runner);
350
    snprintf(msg, sizeof(msg), "running lvcreate help");
351
    runner_add_args(&runner, LVM_CREATE, "--help", NULL);
352
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
353
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
354
    ret = runner_start(&runner);
355
    if (ret) {
356
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_LVCREATE_FAIL,
357
               "Failed to run lvcreate help");
358
        runner_end(&runner);
359
        goto out;
360
    }
361

362
    /* Looking for setactivationskip in lvcreate --help */
363
    do {
364
        ptr = fgets(buf, sizeof(buf), runner_chio(&runner, STDOUT_FILENO));
365
        if (ptr) {
366
            if (strstr(buf, "setactivationskip")) {
367
                match = _gf_true;
368
                break;
369
            }
370
        }
371
    } while (ptr != NULL);
372
    runner_end(&runner);
373

374
    if (clone)
375
        ret = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
376
                       clone_volume_id, brick_num);
377
    else
378
        ret = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
379
                       snap_volume_id, brick_num);
380

381
    if (ret < 0) {
382
        goto out;
383
    }
384

385
    if (strlen(snap_brickinfo->device_path) > 0)
386
        snap_device = gf_strdup(snap_brickinfo->device_path);
387
    else
388
        snap_device = glusterd_lvm_snapshot_device(snap_brickinfo->origin_path,
389
                                                   brick_snapname);
390

391
    if (!snap_device) {
392
        gf_msg(this->name, GF_LOG_ERROR, ENXIO,
393
               GD_MSG_SNAP_DEVICE_NAME_GET_FAIL,
394
               "failed to get device name for the snapshot "
395
               "%s (Brick: %s)",
396
               brick_snapname, snap_brickinfo->path);
397
        ret = -1;
398
        goto out;
399
    }
400

401
    /* Taking the actual snapshot */
402
    runinit(&runner);
403
    snprintf(msg, sizeof(msg), "taking snapshot of the brick %s",
404
             snap_brickinfo->origin_path);
405
    if (match == _gf_true)
406
        runner_add_args(&runner, LVM_CREATE, "-s", origin_device,
407
                        "--setactivationskip", "n", "--name", snap_device,
408
                        NULL);
409
    else
410
        runner_add_args(&runner, LVM_CREATE, "-s", origin_device, "--name",
411
                        snap_device, NULL);
412
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
413
    ret = runner_run(&runner);
414
    if (ret) {
415
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_CREATION_FAIL,
416
               "taking snapshot of the "
417
               "brick (%s) of device %s failed",
418
               snap_brickinfo->origin_path, origin_device);
419
    }
420

421
    /* After the snapshot both the origin brick (LVM brick) and
422
     * the snapshot brick will have the same file-system label. This
423
     * will cause lot of problems at mount time. Therefore we must
424
     * generate a new label for the snapshot brick
425
     */
426
    ret = glusterd_update_fs_label(snap_brickinfo->path, snap_brickinfo->fstype,
427
                                   snap_device);
428
    if (ret) {
429
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_FS_LABEL_UPDATE_FAIL,
430
               "Failed to update "
431
               "file-system label for %s brick",
432
               snap_brickinfo->path);
433
        /* Failing to update label should not cause snapshot failure.
434
         * Currently label is updated only for XFS and ext2/ext3/ext4
435
         * file-system.
436
         */
437
    }
438

439
out:
440
    if (origin_device)
441
        GF_FREE(origin_device);
442

443
    if (snap_device)
444
        GF_FREE(snap_device);
445

446
    return ret;
447
}
448

449
int32_t
450
glusterd_lvm_snapshot_create(glusterd_brickinfo_t *snap_brickinfo,
451
                             char *snapname, char *snap_volume_id,
452
                             int32_t brick_num)
453
{
454
    return glusterd_lvm_snapshot_create_clone(
455
        snap_brickinfo, 0, snapname, snap_volume_id, NULL, NULL, brick_num);
456
}
457

458
int32_t
459
glusterd_lvm_snapshot_clone(glusterd_brickinfo_t *snap_brickinfo,
460
                            char *snapname, char *snap_volume_id,
461
                            char *clonename, char *clone_volume_id,
462
                            int32_t brick_num)
463
{
464
    return glusterd_lvm_snapshot_create_clone(snap_brickinfo, 1, snapname,
465
                                              snap_volume_id, clonename,
466
                                              clone_volume_id, brick_num);
467
}
468

469
static int
470
glusterd_lvm_brick_details(dict_t *rsp_dict,
471
                           glusterd_brickinfo_t *snap_brickinfo, char *snapname,
472
                           char *snap_volume_id, int32_t brick_num,
473
                           char *key_prefix)
474
{
475
    int ret = -1;
476
    char *device = NULL;
477
    glusterd_conf_t *priv = NULL;
478
    runner_t runner = {
479
        0,
480
    };
481
    xlator_t *this = THIS;
482
    char msg[PATH_MAX] = "";
483
    char buf[PATH_MAX] = "";
484
    char *ptr = NULL;
485
    char *token = NULL;
486
    char key[160] = ""; /* key_prefix is 128 bytes at most */
487
    char *value = NULL;
488
    char *snap_device = NULL;
489
    char brick_snapname[NAME_MAX] = "";
490

491
    GF_ASSERT(rsp_dict);
492
    GF_ASSERT(snap_brickinfo);
493
    GF_ASSERT(key_prefix);
494
    priv = this->private;
495
    GF_ASSERT(priv);
496

497
    ret = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
498
                   snap_volume_id, brick_num);
499
    if (ret < 0) {
500
        goto out;
501
    }
502

503
    if (strlen(snap_brickinfo->device_path) > 0)
504
        snap_device = gf_strdup(snap_brickinfo->device_path);
505
    else
506
        snap_device = glusterd_lvm_snapshot_device(snap_brickinfo->origin_path,
507
                                                   brick_snapname);
508

509
    if (!snap_device) {
510
        gf_msg(this->name, GF_LOG_ERROR, ENXIO,
511
               GD_MSG_SNAP_DEVICE_NAME_GET_FAIL,
512
               "failed to get device name for the snapshot "
513
               "%s (Brick: %s)",
514
               brick_snapname, snap_brickinfo->path);
515
        ret = -1;
516
        goto out;
517
    }
518

519
    runinit(&runner);
520
    snprintf(msg, sizeof(msg),
521
             "running lvs command, "
522
             "for getting snap status");
523

524
    /* Using lvs command fetch the Volume Group name,
525
     * Percentage of data filled and Logical Volume size
526
     *
527
     * "-o" argument is used to get the desired information,
528
     * example : "lvs /dev/VolGroup/thin_vol -o vgname,lv_size",
529
     * will get us Volume Group name and Logical Volume size.
530
     *
531
     * Here separator used is ":",
532
     * for the above given command with separator ":",
533
     * The output will be "vgname:lvsize"
534
     */
535
    runner_add_args(&runner, LVS, snap_device, "--noheading", "-o",
536
                    "vg_name,data_percent,lv_size", "--separator", ":", NULL);
537
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
538
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
539
    ret = runner_start(&runner);
540
    if (ret) {
541
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_LVS_FAIL,
542
               "Could not perform lvs action");
543
        goto end;
544
    }
545
    do {
546
        ptr = fgets(buf, sizeof(buf), runner_chio(&runner, STDOUT_FILENO));
547

548
        if (ptr == NULL)
549
            break;
550
        token = strtok(buf, ":");
551

552
        while (token && token[0] == ' ')
553
            token++;
554
        if (!token) {
555
            ret = -1;
556
            gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
557
                   "Invalid vg entry");
558
            goto end;
559
        }
560
        value = gf_strdup(token);
561
        if (!value) {
562
            ret = -1;
563
            goto end;
564
        }
565
        ret = snprintf(key, sizeof(key), "%s.vgname", key_prefix);
566
        if (ret < 0) {
567
            goto end;
568
        }
569

570
        ret = dict_set_dynstr(rsp_dict, key, value);
571
        if (ret) {
572
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
573
                   "Could not save vgname ");
574
            goto end;
575
        }
576

577
        token = strtok(NULL, ":");
578
        if (token != NULL) {
579
            value = gf_strdup(token);
580
            if (!value) {
581
                ret = -1;
582
                goto end;
583
            }
584
            ret = snprintf(key, sizeof(key), "%s.data", key_prefix);
585
            if (ret < 0) {
586
                goto end;
587
            }
588

589
            ret = dict_set_dynstr(rsp_dict, key, value);
590
            if (ret) {
591
                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
592
                       "Could not save data percent ");
593
                goto end;
594
            }
595
        }
596
        token = strtok(NULL, ":");
597
        if (token != NULL) {
598
            value = gf_strdup(token);
599
            if (!value) {
600
                ret = -1;
601
                goto end;
602
            }
603
            ret = snprintf(key, sizeof(key), "%s.lvsize", key_prefix);
604
            if (ret < 0) {
605
                goto end;
606
            }
607

608
            ret = dict_set_dynstr(rsp_dict, key, value);
609
            if (ret) {
610
                gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
611
                       "Could not save meta data percent ");
612
                goto end;
613
            }
614
        }
615

616
    } while (ptr != NULL);
617

618
    ret = 0;
619

620
end:
621
    runner_end(&runner);
622

623
out:
624
    if (ret && value) {
625
        GF_FREE(value);
626
    }
627

628
    if (device)
629
        GF_FREE(device);
630

631
    if (snap_device)
632
        GF_FREE(snap_device);
633

634
    return ret;
635
}
636

637
int
638
glusterd_lvm_snapshot_remove(glusterd_brickinfo_t *snap_brickinfo,
639
                             char *snapname, char *snap_volume_id,
640
                             int32_t brick_num)
641
{
642
    int ret = -1;
643
    xlator_t *this = THIS;
644
    glusterd_conf_t *priv = NULL;
645
    runner_t runner = {
646
        0,
647
    };
648
    char msg[1024] = "";
649
    char *snap_device = NULL;
650
    int32_t len = 0;
651
    char brick_snapname[NAME_MAX] = "";
652
    struct stat stbuf = {
653
        0,
654
    };
655

656
    priv = this->private;
657
    GF_ASSERT(priv);
658

659
    GF_ASSERT(snap_brickinfo);
660

661
    len = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
662
                   snap_volume_id, brick_num);
663
    if ((len < 0) || (len >= sizeof(brick_snapname))) {
664
        goto out;
665
    }
666

667
    if (strlen(snap_brickinfo->device_path) > 0)
668
        snap_device = gf_strdup(snap_brickinfo->device_path);
669
    else
670
        snap_device = glusterd_lvm_snapshot_device(snap_brickinfo->origin_path,
671
                                                   brick_snapname);
672

673
    if (!snap_device) {
674
        gf_msg(this->name, GF_LOG_ERROR, ENXIO,
675
               GD_MSG_SNAP_DEVICE_NAME_GET_FAIL,
676
               "failed to get device name for the snapshot "
677
               "%s (Brick: %s)",
678
               snapname, snap_brickinfo->path);
679
        ret = -1;
680
        goto out;
681
    }
682

683
    /* Verify if the device path exists or not */
684
    ret = sys_stat(snap_device, &stbuf);
685
    if (ret) {
686
        gf_msg_debug(this->name, 0,
687
                     "Device (%s) for brick (%s:%s) not present. "
688
                     "Removing the brick path",
689
                     snap_device, snap_brickinfo->hostname,
690
                     snap_brickinfo->path);
691
        /* Making ret = 0 as absence of device path should *
692
         * not fail the remove operation */
693
        ret = 0;
694
        goto out;
695
    }
696

697
    runinit(&runner);
698
    len = snprintf(msg, sizeof(msg),
699
                   "remove snapshot of the brick %s, "
700
                   "snap name: %s (device: %s)",
701
                   snap_brickinfo->path, brick_snapname, snap_device);
702
    if (len < 0) {
703
        strcpy(msg, "<error>");
704
    }
705
    runner_add_args(&runner, LVM_REMOVE, "-f", snap_device, NULL);
706
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
707

708
    ret = runner_run(&runner);
709
    if (ret) {
710
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_REMOVE_FAIL,
711
               "removing snapshot of the "
712
               "brick (%s) of snapshot %s (device: %s) failed",
713
               snap_brickinfo->path, brick_snapname, snap_device);
714
        goto out;
715
    }
716

717
out:
718
    if (snap_device)
719
        GF_FREE(snap_device);
720

721
    return ret;
722
}
723

724
int32_t
725
glusterd_lvm_snapshot_activate(glusterd_brickinfo_t *snap_brickinfo,
726
                               char *snapname, char *snap_volume_id,
727
                               int32_t brick_num)
728
{
729
    char msg[4096] = "";
730
    char mnt_opts[1024] = "";
731
    char buff[PATH_MAX] = {0};
732
    int32_t ret = -1;
733
    runner_t runner = {
734
        0,
735
    };
736
    xlator_t *this = NULL;
737
    struct mntent *entry = NULL;
738
    struct mntent save_entry = {0};
739
    char *snap_device = NULL;
740
    char brick_snapname[NAME_MAX] = "";
741
    char *snap_brick_mount_path = NULL;
742
    int32_t len = 0;
743

744
    this = THIS;
745
    GF_ASSERT(this);
746
    GF_ASSERT(snap_brickinfo);
747

748
    /* Fetch the brick mount path from the brickinfo->path */
749
    ret = glusterd_find_brick_mount_path(snap_brickinfo->path,
750
                                         &snap_brick_mount_path);
751
    if (ret) {
752
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRK_MNTPATH_GET_FAIL,
753
               "Failed to find snap_brick_mount_path for %s",
754
               snap_brickinfo->path);
755
        goto out;
756
    }
757

758
    ret = mkdir_p(snap_brick_mount_path, 0755, _gf_true);
759
    if (ret) {
760
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_DIR_OP_FAILED,
761
               "creating the brick directory"
762
               " %s for the snapshot %s failed",
763
               snap_brick_mount_path, snapname);
764
        goto out;
765
    }
766

767
    /* Check to see if the brick is already mounted */
768
    entry = glusterd_get_mnt_entry_info(snap_brick_mount_path, buff,
769
                                        sizeof(buff), &save_entry);
770
    gf_log(this->name, GF_LOG_DEBUG,
771
           "Checking to see if %s "
772
           "is already mounted @ %s",
773
           snap_brickinfo->path, snap_brick_mount_path);
774
    if (entry) {
775
        gf_log(this->name, GF_LOG_INFO, "Snapshot already mounted at %s",
776
               snap_brick_mount_path);
777
        ret = 0;
778
        goto out;
779
    }
780

781
    len = snprintf(brick_snapname, sizeof(brick_snapname), "%s_%d",
782
                   snap_volume_id, brick_num);
783
    if ((len < 0) || (len >= sizeof(brick_snapname))) {
784
        goto out;
785
    }
786

787
    if (strlen(snap_brickinfo->device_path) > 0)
788
        snap_device = gf_strdup(snap_brickinfo->device_path);
789
    else
790
        snap_device = glusterd_lvm_snapshot_device(snap_brickinfo->origin_path,
791
                                                   brick_snapname);
792

793
    if (!snap_device) {
794
        gf_msg(this->name, GF_LOG_ERROR, ENXIO,
795
               GD_MSG_SNAP_DEVICE_NAME_GET_FAIL,
796
               "failed to get device name for the snapshot "
797
               "%s (Brick: %s)",
798
               snapname, snap_brickinfo->path);
799
        ret = -1;
800
        goto out;
801
    }
802

803
    runinit(&runner);
804
    snprintf(msg, sizeof(msg), "mount %s %s", snap_device,
805
             snap_brick_mount_path);
806

807
    strcpy(mnt_opts, snap_brickinfo->mnt_opts);
808

809
    /* XFS file-system does not allow to mount file-system with duplicate
810
     * UUID. File-system UUID of snapshot and its origin volume is same.
811
     * Therefore to mount such a snapshot in XFS we need to pass nouuid
812
     * option
813
     */
814
    if (!strcmp(snap_brickinfo->fstype, "xfs") &&
815
        !glusterd_mntopts_exists(mnt_opts, "nouuid")) {
816
        if (strlen(mnt_opts) > 0)
817
            strcat(mnt_opts, ",");
818
        strcat(mnt_opts, "nouuid");
819
    }
820

821
    if (strlen(mnt_opts) > 0) {
822
        runner_add_args(&runner, "mount", "-o", mnt_opts, snap_device,
823
                        snap_brick_mount_path, NULL);
824
    } else {
825
        runner_add_args(&runner, "mount", snap_device, snap_brick_mount_path,
826
                        NULL);
827
    }
828

829
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
830
    ret = runner_run(&runner);
831
    if (ret) {
832
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_MOUNT_FAIL,
833
               "mounting the snapshot "
834
               "logical device %s failed (error: %s)",
835
               snap_device, strerror(errno));
836
        goto out;
837
    } else
838
        gf_msg_debug(this->name, 0,
839
                     "mounting the snapshot "
840
                     "logical device %s successful",
841
                     snap_device);
842

843
out:
844
    if (snap_brick_mount_path)
845
        GF_FREE(snap_brick_mount_path);
846

847
    if (snap_device)
848
        GF_FREE(snap_device);
849

850
    gf_msg_trace(this->name, 0, "Returning with %d", ret);
851
    return ret;
852
}
853

854
int32_t
855
glusterd_lvm_snapshot_deactivate(glusterd_brickinfo_t *snap_brickinfo,
856
                                 char *snapname, char *snap_volume_id,
857
                                 int32_t brick_num)
858
{
859
    char msg[NAME_MAX] = "";
860
    int32_t ret = -1;
861
    runner_t runner = {
862
        0,
863
    };
864
    xlator_t *this = NULL;
865
    char *snap_brick_mount_path = NULL;
866

867
    this = THIS;
868
    GF_ASSERT(this);
869
    GF_ASSERT(snap_brickinfo);
870

871
    /* Fetch the brick mount path from the brickinfo->path */
872
    ret = glusterd_find_brick_mount_path(snap_brickinfo->path,
873
                                         &snap_brick_mount_path);
874
    if (ret) {
875
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRK_MNTPATH_GET_FAIL,
876
               "Failed to find snap_brick_mount_path for %s",
877
               snap_brickinfo->path);
878
        goto out;
879
    }
880

881
    if (!glusterd_is_path_mounted(snap_brick_mount_path)) {
882
        return 0;
883
    }
884

885
    /*umount2 system call doesn't cleanup mtab entry after un-mount.
886
      So use external umount command*/
887
    runinit(&runner);
888
    snprintf(msg, sizeof(msg), "umount path %s", snap_brick_mount_path);
889
    runner_add_args(&runner, _PATH_UMOUNT, "-f", snap_brick_mount_path, NULL);
890
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
891
    ret = runner_run(&runner);
892
    if (ret) {
893
        gf_msg(this->name, GF_LOG_ERROR, errno, GD_MSG_GLUSTERD_UMOUNT_FAIL,
894
               "umounting %s failed (%s)", snap_brick_mount_path,
895
               strerror(errno));
896
        goto out;
897
    }
898
out:
899
    if (snap_brick_mount_path)
900
        GF_FREE(snap_brick_mount_path);
901

902
    gf_msg_trace(this->name, 0, "Returning with %d", ret);
903
    return ret;
904
}
905

906
int32_t
907
glusterd_lvm_snapshot_restore(glusterd_brickinfo_t *snap_brickinfo,
908
                              char *snapname, char *snap_volume_id,
909
                              int32_t brick_num,
910
                              gf_boolean_t *retain_origin_path)
911
{
912
    int32_t ret = -1;
913
    xlator_t *this = NULL;
914

915
    this = THIS;
916
    GF_ASSERT(this);
917
    GF_ASSERT(snap_brickinfo);
918

919
    ret = glusterd_lvm_snapshot_activate(snap_brickinfo, snapname,
920
                                         snap_volume_id, brick_num);
921
    if (ret) {
922
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_MOUNT_FAIL,
923
               "Failed to mount snapshot to restore.");
924
        goto out;
925
    }
926

927
out:
928
    return ret;
929
}
930

931
int32_t
932
glusterd_lvm_snap_clone_brick_path(char *snap_mount_dir,
933
                                   char *origin_brick_path, int clone,
934
                                   char *snap_clone_name,
935
                                   char *snap_clone_volume_id,
936
                                   char *snap_brick_dir, int brick_num,
937
                                   glusterd_brickinfo_t *brickinfo, int restore)
938
{
939
    int32_t len = 0;
940
    int ret = 0;
941

942
    if (strcmp(snap_brick_dir, "/") == 0) {
943
        snap_brick_dir = "";
944
    }
945

946
    len = snprintf(brickinfo->path, sizeof(brickinfo->path), "%s/%s/brick%d%s",
947
                   snap_mount_dir, snap_clone_volume_id, brick_num + 1,
948
                   snap_brick_dir);
949

950
    if ((len < 0) || (len >= sizeof(brickinfo->path))) {
951
        brickinfo->path[0] = 0;
952
        ret = -1;
953
    }
954

955
    return ret;
956
}
957

958
struct glusterd_snap_ops lvm_snap_ops = {
959
    .name = "LVM",
960
    .probe = glusterd_lvm_probe,
961
    .details = glusterd_lvm_brick_details,
962
    .create = glusterd_lvm_snapshot_create,
963
    .clone = glusterd_lvm_snapshot_clone,
964
    .remove = glusterd_lvm_snapshot_remove,
965
    .activate = glusterd_lvm_snapshot_activate,
966
    .deactivate = glusterd_lvm_snapshot_deactivate,
967
    .restore = glusterd_lvm_snapshot_restore,
968
    .brick_path = glusterd_lvm_snap_clone_brick_path};
969

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.