glusterfs

Форк
0
/
glusterd-zfs-snapshot.c 
519 строк · 14.7 Кб
1
/*
2
   Copyright (c) 2021 iXsystems, Inc <https://www.ixsystems.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
#if defined(GF_LINUX_HOST_OS)
24
#include <mntent.h>
25
#else
26
#include "mntent_compat.h"
27
#endif
28

29
#define ZFS_COMMAND "/sbin/zfs"
30

31
extern char snap_mount_dir[VALID_GLUSTERD_PATHMAX];
32

33
int32_t
34
glusterd_zfs_dataset(char *brick_path, char **pool_name)
35
{
36
    char msg[1024] = "";
37
    char dataset[PATH_MAX] = "";
38
    xlator_t *this = NULL;
39
    runner_t runner = {
40
        0,
41
    };
42
    char *ptr = NULL;
43
    int32_t ret = 0;
44

45
    this = THIS;
46
    GF_ASSERT(this);
47

48
    runinit(&runner);
49
    snprintf(msg, sizeof(msg),
50
             "running zfs command, "
51
             "for getting zfs pool name from brick path");
52
    runner_add_args(&runner, "zfs", "list", "-Ho", "name", brick_path, NULL);
53
    runner_redir(&runner, STDOUT_FILENO, RUN_PIPE);
54
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
55
    ret = runner_start(&runner);
56
    if (ret == -1) {
57
        gf_log(this->name, GF_LOG_ERROR,
58
               "Failed to get dataset name "
59
               "for the brick_path %s",
60
               brick_path);
61
        runner_end(&runner);
62
        goto out;
63
    }
64
    ptr = fgets(dataset, sizeof(dataset), runner_chio(&runner, STDOUT_FILENO));
65

66
    if (!ptr || !strlen(dataset)) {
67
        gf_log(this->name, GF_LOG_ERROR,
68
               "Failed to get datset name "
69
               "for the brick_path %s",
70
               brick_path);
71
        runner_end(&runner);
72
        ret = -1;
73
        goto out;
74
    }
75
    runner_end(&runner);
76

77
    *pool_name = strtok(dataset, "\n");
78

79
out:
80
    return ret;
81
}
82

83
gf_boolean_t
84
glusterd_zfs_probe(char *brick_path)
85
{
86
    int ret = -1;
87
    xlator_t *this = NULL;
88
    gf_boolean_t is_zfs = _gf_false;
89
    char *mnt_pt = NULL;
90
    char buff[PATH_MAX] = "";
91
    struct mntent *entry = NULL;
92
    struct mntent save_entry = {
93
        0,
94
    };
95

96
    this = THIS;
97

98
    GF_VALIDATE_OR_GOTO("glusterd", this, out);
99
    GF_VALIDATE_OR_GOTO(this->name, brick_path, out);
100

101
    if (!glusterd_is_cmd_available(ZFS_COMMAND)) {
102
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_COMMAND_NOT_FOUND,
103
               "ZFS commands not found");
104
        ret = -1;
105
        goto out;
106
    }
107

108
    ret = glusterd_get_brick_root(brick_path, &mnt_pt);
109
    if (ret) {
110
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_BRICKPATH_ROOT_GET_FAIL,
111
               "getting the root "
112
               "of the brick (%s) failed ",
113
               brick_path);
114
        goto out;
115
    }
116

117
    entry = glusterd_get_mnt_entry_info(mnt_pt, buff, sizeof(buff),
118
                                        &save_entry);
119
    if (!entry) {
120
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MNTENTRY_GET_FAIL,
121
               "getting the mount entry for "
122
               "the brick (%s) failed",
123
               brick_path);
124
        goto out;
125
    }
126

127
    if (0 == strncmp("zfs", entry->mnt_type, 5)) {
128
        is_zfs = _gf_true;
129
    }
130

131
out:
132
    if (mnt_pt)
133
        GF_FREE(mnt_pt);
134

135
    return is_zfs;
136
}
137

138
int32_t
139
glusterd_zfs_snapshot_create_or_clone(glusterd_brickinfo_t *snap_brickinfo,
140
                                      int clone, char *snapname,
141
                                      char *snap_volume_id, char *clonename,
142
                                      char *clone_volume_id, int32_t brick_num)
143
{
144
    char msg[4096] = "";
145
    int ret = -1;
146
    runner_t runner = {
147
        0,
148
    };
149
    xlator_t *this = THIS;
150
    char snap_device[NAME_MAX] = "";
151
    char clone_device[NAME_MAX] = "";
152
    char *dataset = NULL;
153
    int32_t len = 0;
154

155
    GF_ASSERT(snap_brickinfo);
156

157
    ret = glusterd_zfs_dataset(snap_brickinfo->origin_path, &dataset);
158
    if (ret)
159
        goto out;
160

161
    len = snprintf(snap_device, sizeof(snap_device), "%s@%s_%d", dataset,
162
                   snap_volume_id, brick_num);
163
    if ((len < 0) || (len >= sizeof(snap_device))) {
164
        goto out;
165
    }
166

167
    /* Taking the actual snapshot */
168
    runinit(&runner);
169
    snprintf(msg, sizeof(msg), "taking snapshot of the brick %s",
170
             snap_brickinfo->origin_path);
171

172
    if (clone) {
173
        len = snprintf(clone_device, sizeof(clone_device), "%s/%s_%d", dataset,
174
                       clone_volume_id, brick_num);
175
        if ((len < 0) || (len >= sizeof(clone_device))) {
176
            goto out;
177
        }
178

179
        runner_add_args(&runner, ZFS_COMMAND, "clone", snap_device,
180
                        clone_device, NULL);
181
    } else
182
        runner_add_args(&runner, ZFS_COMMAND, "snapshot", snap_device, NULL);
183

184
    runner_log(&runner, this->name, GF_LOG_DEBUG, msg);
185
    ret = runner_run(&runner);
186
    if (ret) {
187
        if (clone)
188
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_CLONE_FAILED,
189
                   "taking clone of the "
190
                   "brick (%s) failed",
191
                   snap_brickinfo->origin_path);
192
        else
193
            gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_CREATION_FAIL,
194
                   "taking snapshot of the "
195
                   "brick (%s) failed",
196
                   snap_brickinfo->origin_path);
197
    }
198

199
out:
200
    return ret;
201
}
202

203
/* This function actually calls the command for creating
204
   a snapshot of the backend brick filesystem.
205
*/
206
int32_t
207
glusterd_zfs_snapshot_create(glusterd_brickinfo_t *snap_brickinfo,
208
                             char *snapname, char *snap_volume_id,
209
                             int32_t brick_num)
210
{
211
    return glusterd_zfs_snapshot_create_or_clone(
212
        snap_brickinfo, 0, snapname, snap_volume_id, NULL, NULL, brick_num);
213
}
214

215
/* This function actually calls the command for cloning
216
   a snapshot of the backend brick filesystem.
217
*/
218
int32_t
219
glusterd_zfs_snapshot_clone(glusterd_brickinfo_t *snap_brickinfo,
220
                            char *snapname, char *snap_volume_id,
221
                            char *clonename, char *clone_volume_id,
222
                            int32_t brick_num)
223
{
224
    return glusterd_zfs_snapshot_create_or_clone(snap_brickinfo, 1, snapname,
225
                                                 snap_volume_id, clonename,
226
                                                 clone_volume_id, brick_num);
227
}
228

229
static int
230
glusterd_zfs_brick_details(dict_t *rsp_dict,
231
                           glusterd_brickinfo_t *snap_brickinfo, char *snapname,
232
                           char *snap_volume_id, int32_t brick_num,
233
                           char *key_prefix)
234
{
235
    int ret = -1;
236
    glusterd_conf_t *priv = NULL;
237
    xlator_t *this = THIS;
238
    char key[160] = ""; /* key_prefix is 128 bytes at most */
239
    char *dataset = NULL;
240

241
    GF_ASSERT(rsp_dict);
242
    GF_ASSERT(snap_brickinfo);
243
    GF_ASSERT(key_prefix);
244
    priv = this->private;
245
    GF_ASSERT(priv);
246

247
    ret = glusterd_zfs_dataset(snap_brickinfo->origin_path, &dataset);
248
    if (ret)
249
        goto out;
250

251
    ret = snprintf(key, sizeof(key), "%s.vgname", key_prefix);
252
    if (ret < 0) {
253
        goto out;
254
    }
255

256
    ret = dict_set_str(rsp_dict, key, dataset);
257
    if (ret) {
258
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
259
               "Could not save vgname ");
260
        goto out;
261
    }
262

263
    ret = snprintf(key, sizeof(key), "%s.data", key_prefix);
264
    if (ret < 0) {
265
        goto out;
266
    }
267

268
    ret = dict_set_str(rsp_dict, key, "-");
269
    if (ret) {
270
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
271
               "Could not save data percent ");
272
        goto out;
273
    }
274

275
    ret = snprintf(key, sizeof(key), "%s.lvsize", key_prefix);
276
    if (ret < 0) {
277
        goto out;
278
    }
279

280
    ret = dict_set_str(rsp_dict, key, "-");
281
    if (ret) {
282
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
283
               "Could not save meta data percent ");
284
        goto out;
285
    }
286

287
    ret = 0;
288

289
out:
290
    return ret;
291
}
292

293
int
294
glusterd_zfs_snapshot_remove(glusterd_brickinfo_t *snap_brickinfo,
295
                             char *snapname, char *snap_volume_id,
296
                             int32_t brick_num)
297
{
298
    int ret = -1;
299
    xlator_t *this = THIS;
300
    glusterd_conf_t *priv = NULL;
301
    runner_t runner = {
302
        0,
303
    };
304
    char msg[1024] = "";
305
    int len;
306
    char snap_device[NAME_MAX] = "";
307
    char *dataset = NULL;
308

309
    priv = this->private;
310
    GF_ASSERT(priv);
311

312
    GF_ASSERT(snap_brickinfo);
313

314
    ret = glusterd_zfs_dataset(snap_brickinfo->origin_path, &dataset);
315
    if (ret)
316
        goto out;
317

318
    len = snprintf(snap_device, sizeof(snap_device), "%s@%s_%d", dataset,
319
                   snap_volume_id, brick_num);
320
    if ((len < 0) || (len >= sizeof(snap_device))) {
321
        goto out;
322
    }
323

324
    runinit(&runner);
325
    len = snprintf(msg, sizeof(msg),
326
                   "remove snapshot of the brick %s, "
327
                   "snap name: %s",
328
                   snap_brickinfo->origin_path, snapname);
329
    if (len < 0) {
330
        strcpy(msg, "<error>");
331
    }
332
    runner_add_args(&runner, ZFS_COMMAND, "destroy", snap_device, NULL);
333
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
334

335
    ret = runner_run(&runner);
336
    if (ret) {
337
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_REMOVE_FAIL,
338
               "removing snapshot of the "
339
               "brick (%s) of snapshot %s failed",
340
               snap_brickinfo->origin_path, snapname);
341
        goto out;
342
    }
343

344
out:
345
    return ret;
346
}
347

348
/* No op since .zfs directory is used */
349
int32_t
350
glusterd_zfs_snapshot_activate(glusterd_brickinfo_t *snap_brickinfo,
351
                               char *snapname, char *snap_volume_id,
352
                               int32_t brick_num)
353
{
354
    int32_t ret = 0;
355
    xlator_t *this = NULL;
356

357
    this = THIS;
358
    GF_ASSERT(this);
359
    GF_ASSERT(snap_brickinfo);
360

361
    gf_msg_trace(this->name, 0, "Returning with %d", ret);
362
    return ret;
363
}
364

365
/* No op since .zfs directory is used */
366
int32_t
367
glusterd_zfs_snapshot_deactivate(glusterd_brickinfo_t *snap_brickinfo,
368
                                 char *snapname, char *snap_volume_id,
369
                                 int32_t brick_num)
370
{
371
    int32_t ret = 0;
372
    xlator_t *this = NULL;
373

374
    this = THIS;
375
    GF_ASSERT(this);
376
    GF_ASSERT(snap_brickinfo);
377

378
    gf_msg_trace(this->name, 0, "Returning with %d", ret);
379
    return ret;
380
}
381

382
int32_t
383
glusterd_zfs_snapshot_restore(glusterd_brickinfo_t *snap_brickinfo,
384
                              char *snapname, char *snap_volume_id,
385
                              int32_t brick_num,
386
                              gf_boolean_t *retain_origin_path)
387
{
388
    int ret = -1;
389
    xlator_t *this = THIS;
390
    glusterd_conf_t *priv = NULL;
391
    runner_t runner = {
392
        0,
393
    };
394
    char msg[1024] = "";
395
    int len;
396
    char snap_device[NAME_MAX] = "";
397
    char clone_device[NAME_MAX] = "";
398
    char mnt_pt[PATH_MAX] = "";
399
    char *dataset = NULL;
400

401
    priv = this->private;
402
    GF_ASSERT(priv);
403

404
    GF_ASSERT(snap_brickinfo);
405

406
    ret = glusterd_zfs_dataset(snap_brickinfo->origin_path, &dataset);
407
    if (ret)
408
        goto out;
409

410
    len = snprintf(snap_device, sizeof(snap_device), "%s@%s_%d", dataset,
411
                   snap_volume_id, brick_num);
412
    if ((len < 0) || (len >= sizeof(snap_device))) {
413
        goto out;
414
    }
415

416
    len = snprintf(clone_device, sizeof(clone_device), "%s/%s_%d", dataset,
417
                   snap_volume_id, brick_num);
418
    if ((len < 0) || (len >= sizeof(clone_device))) {
419
        goto out;
420
    }
421

422
    runinit(&runner);
423
    len = snprintf(msg, sizeof(msg),
424
                   "restore snapshot of the brick %s, "
425
                   "snap name: %s",
426
                   snap_brickinfo->origin_path, snapname);
427
    if (len < 0) {
428
        strcpy(msg, "<error>");
429
    }
430
    runner_add_args(&runner, ZFS_COMMAND, "clone", snap_device, clone_device,
431
                    NULL);
432
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
433

434
    ret = runner_run(&runner);
435
    if (ret) {
436
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_RESTORE_FAIL,
437
               "restoring snapshot of the "
438
               "brick (%s) of snapshot %s failed",
439
               snap_brickinfo->origin_path, snapname);
440
        goto out;
441
    }
442

443
    runinit(&runner);
444
    len = snprintf(mnt_pt, sizeof(mnt_pt), "mountpoint=%s/%s/brick%d",
445
                   snap_mount_dir, snap_volume_id, brick_num);
446
    if ((len < 0) || (len >= sizeof(mnt_pt))) {
447
        goto out;
448
    }
449

450
    runner_add_args(&runner, ZFS_COMMAND, "set", mnt_pt, clone_device, NULL);
451
    runner_log(&runner, "", GF_LOG_DEBUG, msg);
452

453
    ret = runner_run(&runner);
454
    if (ret) {
455
        gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_SNAP_RESTORE_FAIL,
456
               "setting mountpoint of restore of the "
457
               "brick (%s) of snapshot %s failed",
458
               snap_brickinfo->origin_path, snapname);
459
        goto out;
460
    }
461

462
out:
463
    return ret;
464
}
465

466
int32_t
467
glusterd_zfs_snap_clone_brick_path(char *snap_mount_dir,
468
                                   char *origin_brick_path, int clone,
469
                                   char *snap_clone_name,
470
                                   char *snap_clone_volume_id,
471
                                   char *snap_brick_dir, int brick_num,
472
                                   glusterd_brickinfo_t *brickinfo, int restore)
473
{
474
    int32_t len = 0;
475
    int ret = 0;
476
    char brick_path[PATH_MAX] = "";
477
    char *origin_brick_mount = NULL;
478
    char *origin_brick = NULL;
479

480
    origin_brick = gf_strdup(origin_brick_path);
481
    origin_brick_mount = dirname(origin_brick);
482

483
    if (clone)
484
        len = snprintf(brickinfo->path, sizeof(brickinfo->path), "%s/%s_%d/%s",
485
                       origin_brick_mount, snap_clone_volume_id, brick_num,
486
                       snap_brick_dir);
487
    else {
488
        if (restore)
489
            len = snprintf(brickinfo->path, sizeof(brickinfo->path),
490
                           "%s/%s/brick%d%s", snap_mount_dir,
491
                           snap_clone_volume_id, brick_num, snap_brick_dir);
492
        else
493
            len = snprintf(brickinfo->path, sizeof(brickinfo->path),
494
                           "%s/.zfs/snapshot/%s_%d/%s", origin_brick_mount,
495
                           snap_clone_volume_id, brick_num, snap_brick_dir);
496
    }
497

498
    if ((len < 0) || (len >= sizeof(brick_path))) {
499
        brickinfo->path[0] = 0;
500
        ret = -1;
501
    }
502

503
    if (origin_brick)
504
        GF_FREE(origin_brick);
505

506
    return ret;
507
}
508

509
struct glusterd_snap_ops zfs_snap_ops = {
510
    .name = "ZFS",
511
    .probe = glusterd_zfs_probe,
512
    .details = glusterd_zfs_brick_details,
513
    .create = glusterd_zfs_snapshot_create,
514
    .clone = glusterd_zfs_snapshot_clone,
515
    .remove = glusterd_zfs_snapshot_remove,
516
    .activate = glusterd_zfs_snapshot_activate,
517
    .deactivate = glusterd_zfs_snapshot_deactivate,
518
    .restore = glusterd_zfs_snapshot_restore,
519
    .brick_path = glusterd_zfs_snap_clone_brick_path};
520

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

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

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

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