"Fossies" - the Fresh Open Source Software Archive

Member "glusterfs-8.6/xlators/mgmt/glusterd/src/glusterd-locks.c" (20 Aug 2021, 26254 Bytes) of package /linux/misc/glusterfs-8.6.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glusterd-locks.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 8.5_vs_8.6.

    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 #include <glusterfs/common-utils.h>
   11 #include "cli1-xdr.h"
   12 #include "xdr-generic.h"
   13 #include "glusterd.h"
   14 #include "glusterd-op-sm.h"
   15 #include "glusterd-store.h"
   16 #include "glusterd-utils.h"
   17 #include "glusterd-volgen.h"
   18 #include "glusterd-locks.h"
   19 #include "glusterd-errno.h"
   20 #include <glusterfs/run.h>
   21 #include <glusterfs/syscall.h>
   22 #include "glusterd-messages.h"
   23 
   24 #include <signal.h>
   25 
   26 #define GF_MAX_LOCKING_ENTITIES 3
   27 
   28 /* Valid entities that the mgmt_v3 lock can hold locks upon    *
   29  * To add newer entities to be locked, we can just add more    *
   30  * entries to this table along with the type and default value */
   31 glusterd_valid_entities valid_types[] = {
   32     {"vol", _gf_true},
   33     {"snap", _gf_false},
   34     {"global", _gf_false},
   35     {NULL},
   36 };
   37 
   38 /* Checks if the lock request is for a valid entity */
   39 static gf_boolean_t
   40 glusterd_mgmt_v3_is_type_valid(char *type)
   41 {
   42     int i = 0;
   43 
   44     GF_ASSERT(type);
   45 
   46     for (i = 0; valid_types[i].type; i++) {
   47         if (!strcmp(type, valid_types[i].type)) {
   48             return _gf_true;
   49         }
   50     }
   51 
   52     return _gf_false;
   53 }
   54 
   55 /* Initialize the global mgmt_v3 lock list(dict) when
   56  * glusterd is spawned */
   57 int32_t
   58 glusterd_mgmt_v3_lock_init()
   59 {
   60     int32_t ret = -1;
   61     xlator_t *this = NULL;
   62     glusterd_conf_t *priv = NULL;
   63 
   64     this = THIS;
   65     GF_ASSERT(this);
   66     priv = this->private;
   67     GF_ASSERT(priv);
   68 
   69     priv->mgmt_v3_lock = dict_new();
   70     if (!priv->mgmt_v3_lock)
   71         goto out;
   72 
   73     ret = 0;
   74 out:
   75     return ret;
   76 }
   77 
   78 /* Destroy the global mgmt_v3 lock list(dict) when
   79  * glusterd cleanup is performed */
   80 void
   81 glusterd_mgmt_v3_lock_fini()
   82 {
   83     xlator_t *this = NULL;
   84     glusterd_conf_t *priv = NULL;
   85 
   86     this = THIS;
   87     GF_ASSERT(this);
   88     priv = this->private;
   89     GF_ASSERT(priv);
   90 
   91     if (priv->mgmt_v3_lock)
   92         dict_unref(priv->mgmt_v3_lock);
   93 }
   94 
   95 /* Initialize the global mgmt_v3_timer lock list(dict) when
   96  * glusterd is spawned */
   97 int32_t
   98 glusterd_mgmt_v3_lock_timer_init()
   99 {
  100     int32_t ret = -1;
  101     xlator_t *this = NULL;
  102     glusterd_conf_t *priv = NULL;
  103 
  104     this = THIS;
  105     GF_VALIDATE_OR_GOTO("glusterd", this, out);
  106 
  107     priv = this->private;
  108     GF_VALIDATE_OR_GOTO(this->name, priv, out);
  109 
  110     priv->mgmt_v3_lock_timer = dict_new();
  111     if (!priv->mgmt_v3_lock_timer)
  112         goto out;
  113 
  114     ret = 0;
  115 out:
  116     return ret;
  117 }
  118 
  119 /* Destroy the global mgmt_v3_timer lock list(dict) when
  120  * glusterd cleanup is performed */
  121 void
  122 glusterd_mgmt_v3_lock_timer_fini()
  123 {
  124     xlator_t *this = NULL;
  125     glusterd_conf_t *priv = NULL;
  126 
  127     this = THIS;
  128     GF_VALIDATE_OR_GOTO("glusterd", this, out);
  129 
  130     priv = this->private;
  131     GF_VALIDATE_OR_GOTO(this->name, priv, out);
  132 
  133     if (priv->mgmt_v3_lock_timer)
  134         dict_unref(priv->mgmt_v3_lock_timer);
  135 out:
  136     return;
  137 }
  138 
  139 static int32_t
  140 glusterd_get_mgmt_v3_lock_owner(char *key, uuid_t *uuid)
  141 {
  142     int32_t ret = -1;
  143     glusterd_mgmt_v3_lock_obj *lock_obj = NULL;
  144     glusterd_conf_t *priv = NULL;
  145     xlator_t *this = NULL;
  146 
  147     this = THIS;
  148     GF_ASSERT(this);
  149     priv = this->private;
  150     GF_ASSERT(priv);
  151 
  152     if (!key || !uuid) {
  153         gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
  154                "key or uuid is null.");
  155         ret = -1;
  156         goto out;
  157     }
  158 
  159     ret = dict_get_bin(priv->mgmt_v3_lock, key, (void **)&lock_obj);
  160     if (!ret)
  161         gf_uuid_copy(*uuid, lock_obj->lock_owner);
  162 
  163     ret = 0;
  164 out:
  165     gf_msg_trace(this->name, 0, "Returning %d", ret);
  166     return ret;
  167 }
  168 
  169 /* This function is called with the locked_count and type, to   *
  170  * release all the acquired locks. */
  171 static int32_t
  172 glusterd_release_multiple_locks_per_entity(dict_t *dict, uuid_t uuid,
  173                                            int32_t locked_count, char *type)
  174 {
  175     char name_buf[PATH_MAX] = "";
  176     char *name = NULL;
  177     int32_t i = -1;
  178     int32_t op_ret = 0;
  179     int32_t ret = -1;
  180     xlator_t *this = NULL;
  181 
  182     this = THIS;
  183     GF_ASSERT(this);
  184     GF_ASSERT(dict);
  185     GF_ASSERT(type);
  186 
  187     if (locked_count == 0) {
  188         gf_msg_debug(this->name, 0, "No %s locked as part of this transaction",
  189                      type);
  190         goto out;
  191     }
  192 
  193     /* Release all the locks held */
  194     for (i = 0; i < locked_count; i++) {
  195         ret = snprintf(name_buf, sizeof(name_buf), "%sname%d", type, i + 1);
  196 
  197         /* Looking for volname1, volname2 or snapname1, *
  198          * as key in the dict snapname2 */
  199         ret = dict_get_strn(dict, name_buf, ret, &name);
  200         if (ret) {
  201             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
  202                    "Unable to get %s locked_count = %d", name_buf,
  203                    locked_count);
  204             op_ret = ret;
  205             continue;
  206         }
  207 
  208         ret = glusterd_mgmt_v3_unlock(name, uuid, type);
  209         if (ret) {
  210             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL,
  211                    "Failed to release lock for %s.", name);
  212             op_ret = ret;
  213         }
  214     }
  215 
  216 out:
  217     gf_msg_trace(this->name, 0, "Returning %d", op_ret);
  218     return op_ret;
  219 }
  220 
  221 /* Given the count and type of the entity this function acquires     *
  222  * locks on multiple elements of the same entity. For example:       *
  223  * If type is "vol" this function tries to acquire locks on multiple *
  224  * volumes */
  225 static int32_t
  226 glusterd_acquire_multiple_locks_per_entity(dict_t *dict, uuid_t uuid,
  227                                            uint32_t *op_errno, int32_t count,
  228                                            char *type)
  229 {
  230     char name_buf[PATH_MAX] = "";
  231     char *name = NULL;
  232     int32_t i = -1;
  233     int32_t ret = -1;
  234     int32_t locked_count = 0;
  235     xlator_t *this = NULL;
  236 
  237     this = THIS;
  238     GF_ASSERT(this);
  239     GF_ASSERT(dict);
  240     GF_ASSERT(type);
  241 
  242     /* Locking one element after other */
  243     for (i = 0; i < count; i++) {
  244         ret = snprintf(name_buf, sizeof(name_buf), "%sname%d", type, i + 1);
  245 
  246         /* Looking for volname1, volname2 or snapname1, *
  247          * as key in the dict snapname2 */
  248         ret = dict_get_strn(dict, name_buf, ret, &name);
  249         if (ret) {
  250             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
  251                    "Unable to get %s count = %d", name_buf, count);
  252             break;
  253         }
  254 
  255         ret = glusterd_mgmt_v3_lock(name, uuid, op_errno, type);
  256         if (ret) {
  257             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL,
  258                    "Failed to acquire lock for %s %s "
  259                    "on behalf of %s. Reversing "
  260                    "this transaction",
  261                    type, name, uuid_utoa(uuid));
  262             break;
  263         }
  264         locked_count++;
  265     }
  266 
  267     if (count == locked_count) {
  268         /* If all locking ops went successfully, return as success */
  269         ret = 0;
  270         goto out;
  271     }
  272 
  273     /* If we failed to lock one element, unlock others and return failure */
  274     ret = glusterd_release_multiple_locks_per_entity(dict, uuid, locked_count,
  275                                                      type);
  276     if (ret) {
  277         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL,
  278                "Failed to release multiple %s locks", type);
  279     }
  280     ret = -1;
  281 out:
  282     gf_msg_trace(this->name, 0, "Returning %d", ret);
  283     return ret;
  284 }
  285 
  286 /* Given the type of entity, this function figures out if it should unlock a   *
  287  * single element of multiple elements of the said entity. For example:        *
  288  * if the type is "vol", this function will accordingly unlock a single volume *
  289  * or multiple volumes */
  290 static int32_t
  291 glusterd_mgmt_v3_unlock_entity(dict_t *dict, uuid_t uuid, char *type,
  292                                gf_boolean_t default_value)
  293 {
  294     char name_buf[PATH_MAX] = "";
  295     char *name = NULL;
  296     int32_t count = -1;
  297     int32_t ret = -1;
  298     gf_boolean_t hold_locks = _gf_false;
  299     xlator_t *this = NULL;
  300 
  301     this = THIS;
  302     GF_ASSERT(this);
  303     GF_ASSERT(dict);
  304     GF_ASSERT(type);
  305 
  306     snprintf(name_buf, sizeof(name_buf), "hold_%s_locks", type);
  307     hold_locks = dict_get_str_boolean(dict, name_buf, default_value);
  308 
  309     if (hold_locks == _gf_false) {
  310         /* Locks were not held for this particular entity *
  311          * Hence nothing to release */
  312         ret = 0;
  313         goto out;
  314     }
  315 
  316     /* Looking for volcount or snapcount in the dict */
  317     ret = snprintf(name_buf, sizeof(name_buf), "%scount", type);
  318     ret = dict_get_int32n(dict, name_buf, ret, &count);
  319     if (ret) {
  320         /* count is not present. Only one *
  321          * element name needs to be unlocked */
  322         ret = snprintf(name_buf, sizeof(name_buf), "%sname", type);
  323         ret = dict_get_strn(dict, name_buf, ret, &name);
  324         if (ret) {
  325             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
  326                    "Unable to fetch %sname", type);
  327             goto out;
  328         }
  329 
  330         ret = glusterd_mgmt_v3_unlock(name, uuid, type);
  331         if (ret) {
  332             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_UNLOCK_FAIL,
  333                    "Failed to release lock for %s %s "
  334                    "on behalf of %s.",
  335                    type, name, uuid_utoa(uuid));
  336             goto out;
  337         }
  338     } else {
  339         /* Unlocking one element name after another */
  340         ret = glusterd_release_multiple_locks_per_entity(dict, uuid, count,
  341                                                          type);
  342         if (ret) {
  343             gf_msg(this->name, GF_LOG_ERROR, 0,
  344                    GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL,
  345                    "Failed to release all %s locks", type);
  346             goto out;
  347         }
  348     }
  349 
  350     ret = 0;
  351 out:
  352     gf_msg_trace(this->name, 0, "Returning %d", ret);
  353     return ret;
  354 }
  355 
  356 /* Given the type of entity, this function figures out if it should lock a   *
  357  * single element or multiple elements of the said entity. For example:      *
  358  * if the type is "vol", this function will accordingly lock a single volume *
  359  * or multiple volumes */
  360 static int32_t
  361 glusterd_mgmt_v3_lock_entity(dict_t *dict, uuid_t uuid, uint32_t *op_errno,
  362                              char *type, gf_boolean_t default_value)
  363 {
  364     char name_buf[PATH_MAX] = "";
  365     char *name = NULL;
  366     int32_t count = -1;
  367     int32_t ret = -1;
  368     gf_boolean_t hold_locks = _gf_false;
  369     xlator_t *this = NULL;
  370 
  371     this = THIS;
  372     GF_ASSERT(this);
  373     GF_ASSERT(dict);
  374     GF_ASSERT(type);
  375 
  376     snprintf(name_buf, sizeof(name_buf), "hold_%s_locks", type);
  377     hold_locks = dict_get_str_boolean(dict, name_buf, default_value);
  378 
  379     if (hold_locks == _gf_false) {
  380         /* Not holding locks for this particular entity */
  381         ret = 0;
  382         goto out;
  383     }
  384 
  385     /* Looking for volcount or snapcount in the dict */
  386     ret = snprintf(name_buf, sizeof(name_buf), "%scount", type);
  387     ret = dict_get_int32n(dict, name_buf, ret, &count);
  388     if (ret) {
  389         /* count is not present. Only one *
  390          * element name needs to be locked */
  391         ret = snprintf(name_buf, sizeof(name_buf), "%sname", type);
  392         ret = dict_get_strn(dict, name_buf, ret, &name);
  393         if (ret) {
  394             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_GET_FAILED,
  395                    "Unable to fetch %sname", type);
  396             goto out;
  397         }
  398 
  399         ret = glusterd_mgmt_v3_lock(name, uuid, op_errno, type);
  400         if (ret) {
  401             gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_MGMTV3_LOCK_GET_FAIL,
  402                    "Failed to acquire lock for %s %s "
  403                    "on behalf of %s.",
  404                    type, name, uuid_utoa(uuid));
  405             goto out;
  406         }
  407     } else {
  408         /* Locking one element name after another */
  409         ret = glusterd_acquire_multiple_locks_per_entity(dict, uuid, op_errno,
  410                                                          count, type);
  411         if (ret) {
  412             gf_msg(this->name, GF_LOG_ERROR, 0,
  413                    GD_MSG_MULTIPLE_LOCK_ACQUIRE_FAIL,
  414                    "Failed to acquire all %s locks", type);
  415             goto out;
  416         }
  417     }
  418 
  419     ret = 0;
  420 out:
  421     gf_msg_trace(this->name, 0, "Returning %d", ret);
  422     return ret;
  423 }
  424 
  425 /* Try to release locks of multiple entities like *
  426  * volume, snaps etc. */
  427 int32_t
  428 glusterd_multiple_mgmt_v3_unlock(dict_t *dict, uuid_t uuid)
  429 {
  430     int32_t i = -1;
  431     int32_t ret = -1;
  432     int32_t op_ret = 0;
  433     xlator_t *this = NULL;
  434 
  435     this = THIS;
  436     GF_ASSERT(this);
  437 
  438     if (!dict) {
  439         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_EMPTY, "dict is null.");
  440         ret = -1;
  441         goto out;
  442     }
  443 
  444     for (i = 0; valid_types[i].type; i++) {
  445         ret = glusterd_mgmt_v3_unlock_entity(dict, uuid, valid_types[i].type,
  446                                              valid_types[i].default_value);
  447         if (ret) {
  448             gf_msg(this->name, GF_LOG_ERROR, 0,
  449                    GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL, "Unable to unlock all %s",
  450                    valid_types[i].type);
  451             op_ret = ret;
  452         }
  453     }
  454 
  455     ret = op_ret;
  456 out:
  457     gf_msg_debug(this->name, 0, "Returning %d", ret);
  458     return ret;
  459 }
  460 
  461 /* Try to acquire locks on multiple entities like *
  462  * volume, snaps etc. */
  463 int32_t
  464 glusterd_multiple_mgmt_v3_lock(dict_t *dict, uuid_t uuid, uint32_t *op_errno)
  465 {
  466     int32_t i = -1;
  467     int32_t ret = -1;
  468     int32_t locked_count = 0;
  469     xlator_t *this = NULL;
  470 
  471     this = THIS;
  472     GF_ASSERT(this);
  473 
  474     if (!dict) {
  475         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_EMPTY, "dict is null.");
  476         ret = -1;
  477         goto out;
  478     }
  479 
  480     /* Locking one entity after other */
  481     for (i = 0; valid_types[i].type; i++) {
  482         ret = glusterd_mgmt_v3_lock_entity(dict, uuid, op_errno,
  483                                            valid_types[i].type,
  484                                            valid_types[i].default_value);
  485         if (ret) {
  486             gf_msg(this->name, GF_LOG_ERROR, 0,
  487                    GD_MSG_MULTIPLE_LOCK_ACQUIRE_FAIL, "Unable to lock all %s",
  488                    valid_types[i].type);
  489             break;
  490         }
  491         locked_count++;
  492     }
  493 
  494     if (locked_count == GF_MAX_LOCKING_ENTITIES) {
  495         /* If all locking ops went successfully, return as success */
  496         ret = 0;
  497         goto out;
  498     }
  499 
  500     /* If we failed to lock one entity, unlock others and return failure */
  501     for (i = 0; i < locked_count; i++) {
  502         ret = glusterd_mgmt_v3_unlock_entity(dict, uuid, valid_types[i].type,
  503                                              valid_types[i].default_value);
  504         if (ret) {
  505             gf_msg(this->name, GF_LOG_ERROR, 0,
  506                    GD_MSG_MULTIPLE_LOCK_RELEASE_FAIL, "Unable to unlock all %s",
  507                    valid_types[i].type);
  508         }
  509     }
  510     ret = -1;
  511 out:
  512     gf_msg_debug(this->name, 0, "Returning %d", ret);
  513     return ret;
  514 }
  515 
  516 int32_t
  517 glusterd_mgmt_v3_lock(const char *name, uuid_t uuid, uint32_t *op_errno,
  518                       char *type)
  519 {
  520     char key[PATH_MAX] = "";
  521     int32_t ret = -1;
  522     glusterd_mgmt_v3_lock_obj *lock_obj = NULL;
  523     glusterd_mgmt_v3_lock_timer *mgmt_lock_timer = NULL;
  524     glusterd_conf_t *priv = NULL;
  525     gf_boolean_t is_valid = _gf_true;
  526     uuid_t owner = {0};
  527     xlator_t *this = NULL;
  528     char *bt = NULL;
  529     struct timespec delay = {0};
  530     char *key_dup = NULL;
  531     glusterfs_ctx_t *mgmt_lock_timer_ctx = NULL;
  532     xlator_t *mgmt_lock_timer_xl = NULL;
  533 
  534     this = THIS;
  535     GF_ASSERT(this);
  536 
  537     priv = this->private;
  538     GF_ASSERT(priv);
  539 
  540     if (!name || !type) {
  541         gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
  542                "name or type is null.");
  543         ret = -1;
  544         goto out;
  545     }
  546 
  547     is_valid = glusterd_mgmt_v3_is_type_valid(type);
  548     if (is_valid != _gf_true) {
  549         gf_msg_callingfn(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
  550                          "Invalid entity. Cannot perform locking "
  551                          "operation on %s types",
  552                          type);
  553         ret = -1;
  554         goto out;
  555     }
  556 
  557     ret = snprintf(key, sizeof(key), "%s_%s", name, type);
  558     if (ret != strlen(name) + 1 + strlen(type)) {
  559         ret = -1;
  560         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
  561                "Unable to create key");
  562         goto out;
  563     }
  564 
  565     gf_msg_debug(this->name, 0, "Trying to acquire lock of %s for %s", key,
  566                  uuid_utoa(uuid));
  567 
  568     ret = glusterd_get_mgmt_v3_lock_owner(key, &owner);
  569     if (ret) {
  570         gf_msg_debug(this->name, 0, "Unable to get mgmt_v3 lock owner");
  571         goto out;
  572     }
  573 
  574     /* If the lock has already been held for the given volume
  575      * we fail */
  576     if (!gf_uuid_is_null(owner)) {
  577         gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
  578                          GD_MSG_LOCK_ALREADY_HELD, "Lock for %s held by %s",
  579                          name, uuid_utoa(owner));
  580         ret = -1;
  581         *op_errno = EG_ANOTRANS;
  582         goto out;
  583     }
  584 
  585     lock_obj = GF_MALLOC(sizeof(glusterd_mgmt_v3_lock_obj),
  586                          gf_common_mt_mgmt_v3_lock_obj_t);
  587     if (!lock_obj) {
  588         ret = -1;
  589         goto out;
  590     }
  591 
  592     gf_uuid_copy(lock_obj->lock_owner, uuid);
  593 
  594     ret = dict_set_bin(priv->mgmt_v3_lock, key, lock_obj,
  595                        sizeof(glusterd_mgmt_v3_lock_obj));
  596     if (ret) {
  597         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
  598                "Unable to set lock owner in mgmt_v3 lock");
  599         GF_FREE(lock_obj);
  600         goto out;
  601     }
  602 
  603     mgmt_lock_timer = GF_CALLOC(1, sizeof(glusterd_mgmt_v3_lock_timer),
  604                                 gf_common_mt_mgmt_v3_lock_timer_t);
  605 
  606     if (!mgmt_lock_timer) {
  607         ret = -1;
  608         goto out;
  609     }
  610 
  611     mgmt_lock_timer->xl = THIS;
  612 
  613     ret = -1;
  614     mgmt_lock_timer_xl = mgmt_lock_timer->xl;
  615     if (!mgmt_lock_timer_xl) {
  616         GF_FREE(mgmt_lock_timer);
  617         goto out;
  618     }
  619 
  620     mgmt_lock_timer_ctx = mgmt_lock_timer_xl->ctx;
  621     if (!mgmt_lock_timer_ctx) {
  622         GF_FREE(mgmt_lock_timer);
  623         goto out;
  624     }
  625 
  626     key_dup = gf_strdup(key);
  627     delay.tv_sec = priv->mgmt_v3_lock_timeout;
  628     delay.tv_nsec = 0;
  629 
  630     /*changing to default timeout value*/
  631     priv->mgmt_v3_lock_timeout = GF_LOCK_TIMER;
  632 
  633     mgmt_lock_timer->timer = gf_timer_call_after(
  634         mgmt_lock_timer_ctx, delay, gd_mgmt_v3_unlock_timer_cbk, key_dup);
  635 
  636     ret = dict_set_bin(priv->mgmt_v3_lock_timer, key, mgmt_lock_timer,
  637                        sizeof(glusterd_mgmt_v3_lock_timer));
  638     if (ret) {
  639         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
  640                "Unable to set timer in mgmt_v3 lock");
  641         GF_FREE(key_dup);
  642         GF_FREE(mgmt_lock_timer);
  643         goto out;
  644     }
  645 
  646     /* Saving the backtrace into the pre-allocated buffer, ctx->btbuf*/
  647     if ((bt = gf_backtrace_save(NULL))) {
  648         snprintf(key, sizeof(key), "debug.last-success-bt-%s", key_dup);
  649         ret = dict_set_dynstr_with_alloc(priv->mgmt_v3_lock, key, bt);
  650         if (ret)
  651             gf_msg(this->name, GF_LOG_WARNING, 0, GD_MSG_DICT_SET_FAILED,
  652                    "Failed to save "
  653                    "the back trace for lock %s granted to %s",
  654                    key_dup, uuid_utoa(uuid));
  655         ret = 0;
  656     }
  657 
  658     gf_msg_debug(this->name, 0, "Lock for %s successfully held by %s", key_dup,
  659                  uuid_utoa(uuid));
  660 
  661     ret = 0;
  662 out:
  663     gf_msg_trace(this->name, 0, "Returning %d", ret);
  664     return ret;
  665 }
  666 
  667 /*
  668  * This call back will ensure to unlock the lock_obj, in case we hit a situation
  669  * where unlocking failed and stale lock exist*/
  670 void
  671 gd_mgmt_v3_unlock_timer_cbk(void *data)
  672 {
  673     xlator_t *this = NULL;
  674     glusterd_conf_t *conf = NULL;
  675     glusterd_mgmt_v3_lock_timer *mgmt_lock_timer = NULL;
  676     char *key = NULL;
  677     int keylen;
  678     char bt_key[PATH_MAX] = "";
  679     int bt_key_len = 0;
  680     int32_t ret = -1;
  681     glusterfs_ctx_t *mgmt_lock_timer_ctx = NULL;
  682     xlator_t *mgmt_lock_timer_xl = NULL;
  683     gf_timer_t *timer = NULL;
  684 
  685     this = THIS;
  686     GF_VALIDATE_OR_GOTO("glusterd", this, out);
  687 
  688     conf = this->private;
  689     GF_VALIDATE_OR_GOTO(this->name, conf, out);
  690 
  691     GF_ASSERT(NULL != data);
  692     key = (char *)data;
  693 
  694     keylen = strlen(key);
  695     dict_deln(conf->mgmt_v3_lock, key, keylen);
  696 
  697     bt_key_len = snprintf(bt_key, PATH_MAX, "debug.last-success-bt-%s", key);
  698     if (bt_key_len != SLEN("debug.last-success-bt-") + keylen) {
  699         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
  700                "Unable to create backtrace "
  701                "key");
  702         goto out;
  703     }
  704 
  705     dict_deln(conf->mgmt_v3_lock, bt_key, bt_key_len);
  706 
  707     ret = dict_get_bin(conf->mgmt_v3_lock_timer, key,
  708                        (void **)&mgmt_lock_timer);
  709     if (ret) {
  710         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
  711                "Unable to get lock owner in mgmt_v3 lock");
  712     }
  713 
  714 out:
  715     if (mgmt_lock_timer && mgmt_lock_timer->timer) {
  716         mgmt_lock_timer_xl = mgmt_lock_timer->xl;
  717         GF_VALIDATE_OR_GOTO(this->name, mgmt_lock_timer_xl, ret_function);
  718 
  719         mgmt_lock_timer_ctx = mgmt_lock_timer_xl->ctx;
  720         GF_VALIDATE_OR_GOTO(this->name, mgmt_lock_timer_ctx, ret_function);
  721 
  722         timer = mgmt_lock_timer->timer;
  723         GF_FREE(timer->data);
  724         gf_timer_call_cancel(mgmt_lock_timer_ctx, mgmt_lock_timer->timer);
  725         dict_deln(conf->mgmt_v3_lock_timer, bt_key, bt_key_len);
  726         mgmt_lock_timer->timer = NULL;
  727         gf_log(this->name, GF_LOG_INFO,
  728                "unlock timer is cancelled for volume_type"
  729                " %s",
  730                key);
  731     }
  732 
  733 ret_function:
  734 
  735     return;
  736 }
  737 
  738 int32_t
  739 glusterd_mgmt_v3_unlock(const char *name, uuid_t uuid, char *type)
  740 {
  741     char key[PATH_MAX] = "";
  742     char key_dup[PATH_MAX] = "";
  743     int keylen;
  744     int32_t ret = -1;
  745     gf_boolean_t is_valid = _gf_true;
  746     glusterd_conf_t *priv = NULL;
  747     glusterd_volinfo_t *volinfo = NULL;
  748     glusterd_mgmt_v3_lock_timer *mgmt_lock_timer = NULL;
  749     uuid_t owner = {0};
  750     xlator_t *this = NULL;
  751     glusterfs_ctx_t *mgmt_lock_timer_ctx = NULL;
  752     xlator_t *mgmt_lock_timer_xl = NULL;
  753     gf_timer_t *timer = NULL;
  754 
  755     this = THIS;
  756     GF_ASSERT(this);
  757 
  758     priv = this->private;
  759     GF_ASSERT(priv);
  760 
  761     if (!name || !type) {
  762         gf_msg(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
  763                "name is null.");
  764         ret = -1;
  765         goto out;
  766     }
  767 
  768     is_valid = glusterd_mgmt_v3_is_type_valid(type);
  769     if (is_valid != _gf_true) {
  770         gf_msg_callingfn(this->name, GF_LOG_ERROR, EINVAL, GD_MSG_INVALID_ENTRY,
  771                          "Invalid entity. Cannot perform unlocking "
  772                          "operation on %s types",
  773                          type);
  774         ret = -1;
  775         goto out;
  776     }
  777 
  778     keylen = snprintf(key, sizeof(key), "%s_%s", name, type);
  779     if (keylen != strlen(name) + 1 + strlen(type)) {
  780         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
  781                "Unable to create key");
  782         ret = -1;
  783         goto out;
  784     }
  785 
  786     gf_msg_debug(this->name, 0, "Trying to release lock of %s %s for %s as %s",
  787                  type, name, uuid_utoa(uuid), key);
  788 
  789     ret = glusterd_get_mgmt_v3_lock_owner(key, &owner);
  790     if (ret) {
  791         gf_msg_debug(this->name, 0, "Unable to get mgmt_v3 lock owner");
  792         goto out;
  793     }
  794 
  795     if (gf_uuid_is_null(owner)) {
  796         gf_msg_callingfn(this->name, GF_LOG_WARNING, 0, GD_MSG_LOCK_NOT_HELD,
  797                          "Lock for %s %s not held", type, name);
  798         ret = -1;
  799         goto out;
  800     }
  801 
  802     ret = gf_uuid_compare(uuid, owner);
  803     if (ret) {
  804         gf_msg_callingfn(this->name, GF_LOG_WARNING, 0,
  805                          GD_MSG_LOCK_OWNER_MISMATCH,
  806                          "Lock owner mismatch. "
  807                          "Lock for %s %s held by %s",
  808                          type, name, uuid_utoa(owner));
  809         goto out;
  810     }
  811 
  812     /* Removing the mgmt_v3 lock from the global list */
  813     dict_deln(priv->mgmt_v3_lock, key, keylen);
  814 
  815     ret = dict_get_bin(priv->mgmt_v3_lock_timer, key,
  816                        (void **)&mgmt_lock_timer);
  817     if (ret) {
  818         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_DICT_SET_FAILED,
  819                "Unable to get mgmt lock key in mgmt_v3 lock");
  820         goto out;
  821     }
  822 
  823     (void)snprintf(key_dup, sizeof(key_dup), "%s", key);
  824 
  825     /* Remove the backtrace key as well */
  826     ret = snprintf(key, sizeof(key), "debug.last-success-bt-%s", key_dup);
  827     if (ret != SLEN("debug.last-success-bt-") + keylen) {
  828         gf_msg(this->name, GF_LOG_ERROR, 0, GD_MSG_CREATE_KEY_FAIL,
  829                "Unable to create backtrace "
  830                "key");
  831         ret = -1;
  832         goto out;
  833     }
  834     dict_deln(priv->mgmt_v3_lock, key, ret);
  835 
  836     gf_msg_debug(this->name, 0, "Lock for %s %s successfully released", type,
  837                  name);
  838 
  839     /* Release owner reference which was held during lock */
  840     if (mgmt_lock_timer && mgmt_lock_timer->timer) {
  841         ret = -1;
  842         mgmt_lock_timer_xl = mgmt_lock_timer->xl;
  843         GF_VALIDATE_OR_GOTO(this->name, mgmt_lock_timer_xl, out);
  844 
  845         mgmt_lock_timer_ctx = mgmt_lock_timer_xl->ctx;
  846         GF_VALIDATE_OR_GOTO(this->name, mgmt_lock_timer_ctx, out);
  847         ret = 0;
  848 
  849         timer = mgmt_lock_timer->timer;
  850         GF_FREE(timer->data);
  851         gf_timer_call_cancel(mgmt_lock_timer_ctx, mgmt_lock_timer->timer);
  852         dict_deln(priv->mgmt_v3_lock_timer, key_dup, keylen);
  853     }
  854     ret = glusterd_volinfo_find(name, &volinfo);
  855     if (volinfo && volinfo->stage_deleted) {
  856         /* this indicates a volume still exists and the volume delete
  857          * operation has failed in some of the phases, need to ensure
  858          * stage_deleted flag is set back to false
  859          */
  860         volinfo->stage_deleted = _gf_false;
  861         gf_log(this->name, GF_LOG_INFO,
  862                "Volume %s still exist, setting "
  863                "stage deleted flag to false for the volume",
  864                volinfo->volname);
  865     }
  866     ret = 0;
  867 out:
  868 
  869     gf_msg_trace(this->name, 0, "Returning %d", ret);
  870     return ret;
  871 }