10
#include "glusterd-op-sm.h"
11
#include "glusterd-store.h"
12
#include "glusterd-utils.h"
13
#include "glusterd-volgen.h"
14
#include "glusterd-locks.h"
15
#include "glusterd-errno.h"
16
#include <glusterfs/run.h>
17
#include <glusterfs/syscall.h>
18
#include "glusterd-messages.h"
22
#define GF_MAX_LOCKING_ENTITIES 3
27
glusterd_valid_entities valid_types[] = {
30
{"global", _gf_false},
36
glusterd_mgmt_v3_is_type_valid(char *type)
42
for (i = 0; valid_types[i].type; i++) {
43
if (!strcmp(type, valid_types[i].type)) {
54
glusterd_mgmt_v3_lock_init(void)
57
glusterd_conf_t *priv = NULL;
62
priv->mgmt_v3_lock = dict_new();
63
if (!priv->mgmt_v3_lock)
74
glusterd_mgmt_v3_lock_fini(void)
76
glusterd_conf_t *priv = NULL;
81
if (priv->mgmt_v3_lock)
82
dict_unref(priv->mgmt_v3_lock);
88
glusterd_mgmt_v3_lock_timer_init(void)
91
xlator_t *this = THIS;
92
glusterd_conf_t *priv = NULL;
95
GF_VALIDATE_OR_GOTO(this->name, priv, out);
97
priv->mgmt_v3_lock_timer = dict_new();
98
if (!priv->mgmt_v3_lock_timer)
109
glusterd_mgmt_v3_lock_timer_fini(void)
111
xlator_t *this = THIS;
112
glusterd_conf_t *priv = NULL;
114
priv = this->private;
115
GF_VALIDATE_OR_GOTO(this->name, priv, out);
117
if (priv->mgmt_v3_lock_timer)
118
dict_unref(priv->mgmt_v3_lock_timer);
124
glusterd_get_mgmt_v3_lock_owner(char *key, uuid_t *uuid)
127
glusterd_mgmt_v3_lock_obj *lock_obj = NULL;
128
glusterd_conf_t *priv = NULL;
129
xlator_t *this = THIS;
131
priv = this->private;
135
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
136
"key or uuid is null.");
141
ret = dict_get_bin(priv->mgmt_v3_lock, key, (void **)&lock_obj);
143
gf_uuid_copy(*uuid, lock_obj->lock_owner);
147
gf_msg_trace(this->name, 0, "Returning %d", ret);
154
glusterd_release_multiple_locks_per_entity(dict_t *dict, uuid_t uuid,
155
int32_t locked_count, char *type)
157
char name_buf[PATH_MAX] = "";
162
xlator_t *this = THIS;
167
if (locked_count == 0) {
168
gf_msg_debug(this->name, 0, "No %s locked as part of this transaction",
174
for (i = 0; i < locked_count; i++) {
175
ret = snprintf(name_buf, sizeof(name_buf), "%sname%d", type, i + 1);
179
ret = dict_get_strn(dict, name_buf, ret, &name);
181
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
182
"Unable to get %s locked_count = %d", name_buf,
188
ret = glusterd_mgmt_v3_unlock(name, uuid, type);
190
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL,
191
"Failed to release lock for %s.", name);
197
gf_msg_trace(this->name, 0, "Returning %d", op_ret);
206
glusterd_acquire_multiple_locks_per_entity(dict_t *dict, uuid_t uuid,
207
uint32_t *op_errno, int32_t count,
210
char name_buf[PATH_MAX] = "";
214
int32_t locked_count = 0;
215
xlator_t *this = THIS;
221
for (i = 0; i < count; i++) {
222
ret = snprintf(name_buf, sizeof(name_buf), "%sname%d", type, i + 1);
226
ret = dict_get_strn(dict, name_buf, ret, &name);
228
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
229
"Unable to get %s count = %d", name_buf, count);
233
ret = glusterd_mgmt_v3_lock(name, uuid, op_errno, type);
235
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL,
236
"Failed to acquire lock for %s %s "
237
"on behalf of %s. Reversing "
239
type, name, uuid_utoa(uuid));
245
if (count == locked_count) {
252
ret = glusterd_release_multiple_locks_per_entity(dict, uuid, locked_count,
255
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL,
256
"Failed to release multiple %s locks", type);
260
gf_msg_trace(this->name, 0, "Returning %d", ret);
269
glusterd_mgmt_v3_unlock_entity(dict_t *dict, uuid_t uuid, char *type,
270
gf_boolean_t default_value)
272
char name_buf[PATH_MAX] = "";
276
gf_boolean_t hold_locks = _gf_false;
277
xlator_t *this = THIS;
282
snprintf(name_buf, sizeof(name_buf), "hold_%s_locks", type);
283
hold_locks = dict_get_str_boolean(dict, name_buf, default_value);
285
if (hold_locks == _gf_false) {
293
ret = snprintf(name_buf, sizeof(name_buf), "%scount", type);
294
ret = dict_get_int32n(dict, name_buf, ret, &count);
298
ret = snprintf(name_buf, sizeof(name_buf), "%sname", type);
299
ret = dict_get_strn(dict, name_buf, ret, &name);
301
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
302
"Unable to fetch %sname", type);
306
ret = glusterd_mgmt_v3_unlock(name, uuid, type);
308
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL,
309
"Failed to release lock for %s %s "
311
type, name, uuid_utoa(uuid));
316
ret = glusterd_release_multiple_locks_per_entity(dict, uuid, count,
319
gf_msg(this->name, GF_LOG_ERROR, 0,
320
GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL,
321
"Failed to release all %s locks", type);
328
gf_msg_trace(this->name, 0, "Returning %d", ret);
337
glusterd_mgmt_v3_lock_entity(dict_t *dict, uuid_t uuid, uint32_t *op_errno,
338
char *type, gf_boolean_t default_value)
340
char name_buf[PATH_MAX] = "";
344
gf_boolean_t hold_locks = _gf_false;
345
xlator_t *this = THIS;
350
snprintf(name_buf, sizeof(name_buf), "hold_%s_locks", type);
351
hold_locks = dict_get_str_boolean(dict, name_buf, default_value);
353
if (hold_locks == _gf_false) {
360
ret = snprintf(name_buf, sizeof(name_buf), "%scount", type);
361
ret = dict_get_int32n(dict, name_buf, ret, &count);
365
ret = snprintf(name_buf, sizeof(name_buf), "%sname", type);
366
ret = dict_get_strn(dict, name_buf, ret, &name);
368
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
369
"Unable to fetch %sname", type);
373
ret = glusterd_mgmt_v3_lock(name, uuid, op_errno, type);
375
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL,
376
"Failed to acquire lock for %s %s "
378
type, name, uuid_utoa(uuid));
383
ret = glusterd_acquire_multiple_locks_per_entity(dict, uuid, op_errno,
386
gf_msg(this->name, GF_LOG_ERROR, 0,
387
GD_MSG_MULTIPLE_LOCK_ACQUIRE_FAIL,
388
"Failed to acquire all %s locks", type);
395
gf_msg_trace(this->name, 0, "Returning %d", ret);
402
glusterd_multiple_mgmt_v3_unlock(dict_t *dict, uuid_t uuid)
407
xlator_t *this = THIS;
410
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_EMPTY, "dict is null.");
415
for (i = 0; valid_types[i].type; i++) {
416
ret = glusterd_mgmt_v3_unlock_entity(dict, uuid, valid_types[i].type,
417
valid_types[i].default_value);
419
gf_msg(this->name, GF_LOG_ERROR, 0,
420
GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL, "Unable to unlock all %s",
421
valid_types[i].type);
428
gf_msg_debug(this->name, 0, "Returning %d", ret);
435
glusterd_multiple_mgmt_v3_lock(dict_t *dict, uuid_t uuid, uint32_t *op_errno)
439
int32_t locked_count = 0;
440
xlator_t *this = THIS;
443
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_EMPTY, "dict is null.");
449
for (i = 0; valid_types[i].type; i++) {
450
ret = glusterd_mgmt_v3_lock_entity(dict, uuid, op_errno,
452
valid_types[i].default_value);
454
gf_msg(this->name, GF_LOG_ERROR, 0,
455
GD_MSG_MULTIPLE_LOCK_ACQUIRE_FAIL, "Unable to lock all %s",
456
valid_types[i].type);
462
if (locked_count == GF_MAX_LOCKING_ENTITIES) {
469
for (i = 0; i < locked_count; i++) {
470
ret = glusterd_mgmt_v3_unlock_entity(dict, uuid, valid_types[i].type,
471
valid_types[i].default_value);
473
gf_msg(this->name, GF_LOG_ERROR, 0,
474
GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL, "Unable to unlock all %s",
475
valid_types[i].type);
480
gf_msg_debug(this->name, 0, "Returning %d", ret);
485
glusterd_mgmt_v3_lock(const char *name, uuid_t uuid, uint32_t *op_errno,
488
char key[PATH_MAX] = "";
490
glusterd_mgmt_v3_lock_obj *lock_obj = NULL;
491
gf_timer_t *mgmt_lock_timer = NULL;
492
glusterd_conf_t *priv = NULL;
493
gf_boolean_t is_valid = _gf_true;
495
xlator_t *this = THIS;
496
struct timespec delay = {0};
497
char *key_dup = NULL;
499
priv = this->private;
502
if (!name || !type) {
503
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
504
"name or type is null.");
509
is_valid = glusterd_mgmt_v3_is_type_valid(type);
510
if (is_valid != _gf_true) {
511
gf_msg_callingfn(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
512
"Invalid entity. Cannot perform locking "
513
"operation on %s types",
519
ret = snprintf(key, sizeof(key), "%s_%s", name, type);
520
if (ret != strlen(name) + 1 + strlen(type)) {
522
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
523
"Unable to create key");
527
gf_msg_debug(this->name, 0, "Trying to acquire lock of %s for %s", key,
530
ret = glusterd_get_mgmt_v3_lock_owner(key, &owner);
532
gf_msg_debug(this->name, 0, "Unable to get mgmt_v3 lock owner");
538
if (!gf_uuid_is_null(owner)) {
539
gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
540
GD_MSG_LOCK_ALREADY_HELD, "Lock for %s held by %s",
541
name, uuid_utoa(owner));
543
*op_errno = EG_ANOTRANS;
547
lock_obj = GF_MALLOC(sizeof(glusterd_mgmt_v3_lock_obj),
548
gf_common_mt_mgmt_v3_lock_obj_t);
554
gf_uuid_copy(lock_obj->lock_owner, uuid);
556
ret = dict_set_bin(priv->mgmt_v3_lock, key, lock_obj,
557
sizeof(glusterd_mgmt_v3_lock_obj));
559
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
560
"Unable to set lock owner in mgmt_v3 lock");
565
key_dup = gf_strdup(key);
566
delay.tv_sec = priv->mgmt_v3_lock_timeout;
570
priv->mgmt_v3_lock_timeout = GF_LOCK_TIMER;
572
mgmt_lock_timer = gf_timer_call_after(this->ctx, delay,
573
gd_mgmt_v3_unlock_timer_cbk, key_dup);
582
ret = dict_set_static_bin(priv->mgmt_v3_lock_timer, key, mgmt_lock_timer,
583
sizeof(mgmt_lock_timer));
585
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
586
"Unable to set timer in mgmt_v3 lock");
588
GF_FREE(mgmt_lock_timer);
596
if ((bt = gf_backtrace_save(NULL))) {
597
snprintf(key, sizeof(key), "debug.last-success-bt-%s", key_dup);
598
ret = dict_set_dynstr_with_alloc(priv->mgmt_v3_lock, key, bt);
600
gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_SET_FAILED,
602
"the back trace for lock %s granted to %s",
603
key_dup, uuid_utoa(uuid));
609
gf_msg_debug(this->name, 0, "Lock for %s successfully held by %s", key_dup,
614
gf_msg_trace(this->name, 0, "Returning %d", ret);
622
gd_mgmt_v3_unlock_timer_cbk(void *data)
624
xlator_t *this = THIS;
625
glusterd_conf_t *conf = NULL;
626
gf_timer_t *mgmt_lock_timer = NULL;
631
conf = this->private;
632
GF_VALIDATE_OR_GOTO(this->name, conf, out);
634
GF_ASSERT(NULL != data);
637
keylen = strlen(key);
638
dict_deln(conf->mgmt_v3_lock, key, keylen);
641
char bt_key[PATH_MAX] = "";
644
bt_key_len = snprintf(bt_key, PATH_MAX, "debug.last-success-bt-%s", key);
645
if (bt_key_len != SLEN("debug.last-success-bt-") + keylen) {
646
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
647
"Unable to create backtrace "
652
dict_deln(conf->mgmt_v3_lock, bt_key, bt_key_len);
655
ret = dict_get_bin(conf->mgmt_v3_lock_timer, key,
656
(void **)&mgmt_lock_timer);
658
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
659
"Unable to get lock owner in mgmt_v3 lock");
663
if (mgmt_lock_timer) {
664
GF_ASSERT(mgmt_lock_timer->xl && mgmt_lock_timer->xl->ctx);
665
GF_FREE(mgmt_lock_timer->data);
666
gf_timer_call_cancel(mgmt_lock_timer->xl->ctx, mgmt_lock_timer);
668
dict_deln(conf->mgmt_v3_lock_timer, bt_key, bt_key_len);
670
gf_log(this->name, GF_LOG_INFO,
671
"unlock timer is cancelled for volume_type"
678
glusterd_mgmt_v3_unlock(const char *name, uuid_t uuid, char *type)
680
char key[PATH_MAX] = "";
681
char key_dup[PATH_MAX] = "";
684
gf_boolean_t is_valid = _gf_true;
685
glusterd_conf_t *priv = NULL;
686
glusterd_volinfo_t *volinfo = NULL;
687
gf_timer_t *mgmt_lock_timer = NULL;
689
xlator_t *this = THIS;
691
priv = this->private;
694
if (!name || !type) {
695
gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
701
is_valid = glusterd_mgmt_v3_is_type_valid(type);
702
if (is_valid != _gf_true) {
703
gf_msg_callingfn(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
704
"Invalid entity. Cannot perform unlocking "
705
"operation on %s types",
711
keylen = snprintf(key, sizeof(key), "%s_%s", name, type);
712
if (keylen != strlen(name) + 1 + strlen(type)) {
713
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
714
"Unable to create key");
719
gf_msg_debug(this->name, 0, "Trying to release lock of %s %s for %s as %s",
720
type, name, uuid_utoa(uuid), key);
722
ret = glusterd_get_mgmt_v3_lock_owner(key, &owner);
724
gf_msg_debug(this->name, 0, "Unable to get mgmt_v3 lock owner");
728
if (gf_uuid_is_null(owner)) {
729
gf_msg_callingfn(this->name, GF_LOG_WARNING, 0, GD_MSG_LOCK_NOT_HELD,
730
"Lock for %s %s not held", type, name);
735
ret = gf_uuid_compare(uuid, owner);
737
gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
738
GD_MSG_LOCK_OWNER_MISMATCH,
739
"Lock owner mismatch. "
740
"Lock for %s %s held by %s",
741
type, name, uuid_utoa(owner));
746
dict_deln(priv->mgmt_v3_lock, key, keylen);
748
ret = dict_get_bin(priv->mgmt_v3_lock_timer, key,
749
(void **)&mgmt_lock_timer);
751
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
752
"Unable to get mgmt lock key in mgmt_v3 lock");
756
(void)snprintf(key_dup, sizeof(key_dup), "%s", key);
760
ret = snprintf(key, sizeof(key), "debug.last-success-bt-%s", key_dup);
761
if (ret != SLEN("debug.last-success-bt-") + keylen) {
762
gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
763
"Unable to create backtrace "
768
dict_deln(priv->mgmt_v3_lock, key, ret);
771
gf_msg_debug(this->name, 0, "Lock for %s %s successfully released", type,
775
if (mgmt_lock_timer) {
776
GF_ASSERT(mgmt_lock_timer->xl && mgmt_lock_timer->xl->ctx);
777
GF_FREE(mgmt_lock_timer->data);
778
gf_timer_call_cancel(mgmt_lock_timer->xl->ctx, mgmt_lock_timer);
779
dict_deln(priv->mgmt_v3_lock_timer, key_dup, keylen);
781
ret = glusterd_volinfo_find(name, &volinfo);
782
if (volinfo && volinfo->stage_deleted) {
787
volinfo->stage_deleted = _gf_false;
788
gf_log(this->name, GF_LOG_INFO,
789
"Volume %s still exist, setting "
790
"stage deleted flag to false for the volume",
796
gf_msg_trace(this->name, 0, "Returning %d", ret);