LCOV - code coverage report
Current view: top level - misc/kabi/lvm2.git/lib/locking - cluster_locking.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 0 252 0.0 %
Date: 2010-04-13 Functions: 0 12 0.0 %
Branches: 0 140 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2002-2004 Sistina Software, Inc. All rights reserved.
       3                 :            :  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
       4                 :            :  *
       5                 :            :  * This file is part of LVM2.
       6                 :            :  *
       7                 :            :  * This copyrighted material is made available to anyone wishing to use,
       8                 :            :  * modify, copy, or redistribute it subject to the terms and conditions
       9                 :            :  * of the GNU Lesser General Public License v.2.1.
      10                 :            :  *
      11                 :            :  * You should have received a copy of the GNU Lesser General Public License
      12                 :            :  * along with this program; if not, write to the Free Software Foundation,
      13                 :            :  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      14                 :            :  */
      15                 :            : 
      16                 :            : /*
      17                 :            :  * Locking functions for LVM.
      18                 :            :  * The main purpose of this part of the library is to serialise LVM
      19                 :            :  * management operations across a cluster.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include "lib.h"
      23                 :            : #include "clvm.h"
      24                 :            : #include "lvm-string.h"
      25                 :            : #include "locking.h"
      26                 :            : #include "locking_types.h"
      27                 :            : #include "toolcontext.h"
      28                 :            : 
      29                 :            : #include <assert.h>
      30                 :            : #include <stddef.h>
      31                 :            : #include <sys/socket.h>
      32                 :            : #include <sys/un.h>
      33                 :            : #include <unistd.h>
      34                 :            : 
      35                 :            : #ifndef CLUSTER_LOCKING_INTERNAL
      36                 :            : int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags);
      37                 :            : int query_resource(const char *resource, int *mode);
      38                 :            : void locking_end(void);
      39                 :            : int locking_init(int type, struct config_tree *cf, uint32_t *flags);
      40                 :            : #endif
      41                 :            : 
      42                 :            : typedef struct lvm_response {
      43                 :            :         char node[255];
      44                 :            :         char *response;
      45                 :            :         int status;
      46                 :            :         int len;
      47                 :            : } lvm_response_t;
      48                 :            : 
      49                 :            : /*
      50                 :            :  * This gets stuck at the start of memory we allocate so we
      51                 :            :  * can sanity-check it at deallocation time
      52                 :            :  */
      53                 :            : #define LVM_SIGNATURE 0x434C564D
      54                 :            : 
      55                 :            : /*
      56                 :            :  * NOTE: the LVMD uses the socket FD as the client ID, this means
      57                 :            :  * that any client that calls fork() will inherit the context of
      58                 :            :  * it's parent.
      59                 :            :  */
      60                 :            : static int _clvmd_sock = -1;
      61                 :            : 
      62                 :            : /* FIXME Install SIGPIPE handler? */
      63                 :            : 
      64                 :            : /* Open connection to the Cluster Manager daemon */
      65                 :          0 : static int _open_local_sock(void)
      66                 :            : {
      67                 :            :         int local_socket;
      68                 :            :         struct sockaddr_un sockaddr;
      69                 :            : 
      70                 :            :         /* Open local socket */
      71         [ #  # ]:          0 :         if ((local_socket = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
      72                 :          0 :                 log_error("Local socket creation failed: %s", strerror(errno));
      73                 :          0 :                 return -1;
      74                 :            :         }
      75                 :            : 
      76                 :          0 :         memset(&sockaddr, 0, sizeof(sockaddr));
      77                 :          0 :         memcpy(sockaddr.sun_path, CLVMD_SOCKNAME, sizeof(CLVMD_SOCKNAME));
      78                 :            : 
      79                 :          0 :         sockaddr.sun_family = AF_UNIX;
      80                 :            : 
      81         [ #  # ]:          0 :         if (connect(local_socket,(struct sockaddr *) &sockaddr,
      82                 :            :                     sizeof(sockaddr))) {
      83                 :          0 :                 int saved_errno = errno;
      84                 :            : 
      85                 :          0 :                 log_error("connect() failed on local socket: %s",
      86                 :            :                           strerror(errno));
      87         [ #  # ]:          0 :                 if (close(local_socket))
      88                 :          0 :                         stack;
      89                 :            : 
      90                 :          0 :                 errno = saved_errno;
      91                 :          0 :                 return -1;
      92                 :            :         }
      93                 :            : 
      94                 :          0 :         return local_socket;
      95                 :            : }
      96                 :            : 
      97                 :            : /* Send a request and return the status */
      98                 :          0 : static int _send_request(char *inbuf, int inlen, char **retbuf)
      99                 :            : {
     100                 :            :         char outbuf[PIPE_BUF] __attribute((aligned(8)));
     101                 :          0 :         struct clvm_header *outheader = (struct clvm_header *) outbuf;
     102                 :            :         int len;
     103                 :            :         int off;
     104                 :            :         int buflen;
     105                 :            :         int err;
     106                 :            : 
     107                 :            :         /* Send it to CLVMD */
     108                 :            :  rewrite:
     109         [ #  # ]:          0 :         if ( (err = write(_clvmd_sock, inbuf, inlen)) != inlen) {
     110 [ #  # ][ #  # ]:          0 :                 if (err == -1 && errno == EINTR)
     111                 :          0 :                         goto rewrite;
     112                 :          0 :                 log_error("Error writing data to clvmd: %s", strerror(errno));
     113                 :          0 :                 return 0;
     114                 :            :         }
     115                 :            : 
     116                 :            :         /* Get the response */
     117                 :            :  reread:
     118         [ #  # ]:          0 :         if ((len = read(_clvmd_sock, outbuf, sizeof(struct clvm_header))) < 0) {
     119         [ #  # ]:          0 :                 if (errno == EINTR)
     120                 :          0 :                         goto reread;
     121                 :          0 :                 log_error("Error reading data from clvmd: %s", strerror(errno));
     122                 :          0 :                 return 0;
     123                 :            :         }
     124                 :            : 
     125         [ #  # ]:          0 :         if (len == 0) {
     126                 :          0 :                 log_error("EOF reading CLVMD");
     127                 :          0 :                 errno = ENOTCONN;
     128                 :          0 :                 return 0;
     129                 :            :         }
     130                 :            : 
     131                 :            :         /* Allocate buffer */
     132                 :          0 :         buflen = len + outheader->arglen;
     133                 :          0 :         *retbuf = dm_malloc(buflen);
     134         [ #  # ]:          0 :         if (!*retbuf) {
     135                 :          0 :                 errno = ENOMEM;
     136                 :          0 :                 return 0;
     137                 :            :         }
     138                 :            : 
     139                 :            :         /* Copy the header */
     140                 :          0 :         memcpy(*retbuf, outbuf, len);
     141                 :          0 :         outheader = (struct clvm_header *) *retbuf;
     142                 :            : 
     143                 :            :         /* Read the returned values */
     144                 :          0 :         off = 1;                /* we've already read the first byte */
     145 [ #  # ][ #  # ]:          0 :         while (off <= outheader->arglen && len > 0) {
     146                 :          0 :                 len = read(_clvmd_sock, outheader->args + off,
     147                 :          0 :                            buflen - off - offsetof(struct clvm_header, args));
     148         [ #  # ]:          0 :                 if (len > 0)
     149                 :          0 :                         off += len;
     150                 :            :         }
     151                 :            : 
     152                 :            :         /* Was it an error ? */
     153         [ #  # ]:          0 :         if (outheader->status != 0) {
     154                 :          0 :                 errno = outheader->status;
     155                 :            : 
     156                 :            :                 /* Only return an error here if there are no node-specific
     157                 :            :                    errors present in the message that might have more detail */
     158         [ #  # ]:          0 :                 if (!(outheader->flags & CLVMD_FLAG_NODEERRS)) {
     159                 :          0 :                         log_error("cluster request failed: %s", strerror(errno));
     160                 :          0 :                         return 0;
     161                 :            :                 }
     162                 :            : 
     163                 :            :         }
     164                 :            : 
     165                 :          0 :         return 1;
     166                 :            : }
     167                 :            : 
     168                 :            : /* Build the structure header and parse-out wildcard node names */
     169                 :            : /* FIXME: Cleanup implicit casts of clvmd_cmd (int, char, uint8_t, etc). */
     170                 :          0 : static void _build_header(struct clvm_header *head, int clvmd_cmd, const char *node,
     171                 :            :                           int len)
     172                 :            : {
     173                 :          0 :         head->cmd = clvmd_cmd;
     174                 :          0 :         head->status = 0;
     175                 :          0 :         head->flags = 0;
     176                 :          0 :         head->clientid = 0;
     177                 :          0 :         head->arglen = len;
     178                 :            : 
     179         [ #  # ]:          0 :         if (node) {
     180                 :            :                 /*
     181                 :            :                  * Allow a couple of special node names:
     182                 :            :                  * "*" for all nodes,
     183                 :            :                  * "." for the local node only
     184                 :            :                  */
     185         [ #  # ]:          0 :                 if (strcmp(node, "*") == 0) {
     186                 :          0 :                         head->node[0] = '\0';
     187         [ #  # ]:          0 :                 } else if (strcmp(node, ".") == 0) {
     188                 :          0 :                         head->node[0] = '\0';
     189                 :          0 :                         head->flags = CLVMD_FLAG_LOCAL;
     190                 :            :                 } else
     191                 :          0 :                         strcpy(head->node, node);
     192                 :            :         } else
     193                 :          0 :                 head->node[0] = '\0';
     194                 :          0 : }
     195                 :            : 
     196                 :            : /*
     197                 :            :  * Send a message to a(or all) node(s) in the cluster and wait for replies
     198                 :            :  */
     199                 :          0 : static int _cluster_request(char clvmd_cmd, const char *node, void *data, int len,
     200                 :            :                            lvm_response_t ** response, int *num)
     201                 :            : {
     202                 :          0 :         char outbuf[sizeof(struct clvm_header) + len + strlen(node) + 1] __attribute((aligned(8)));
     203                 :            :         char *inptr;
     204                 :          0 :         char *retbuf = NULL;
     205                 :            :         int status;
     206                 :            :         int i;
     207                 :          0 :         int num_responses = 0;
     208                 :          0 :         struct clvm_header *head = (struct clvm_header *) outbuf;
     209                 :            :         lvm_response_t *rarray;
     210                 :            : 
     211                 :          0 :         *num = 0;
     212                 :            : 
     213         [ #  # ]:          0 :         if (_clvmd_sock == -1)
     214                 :          0 :                 _clvmd_sock = _open_local_sock();
     215                 :            : 
     216         [ #  # ]:          0 :         if (_clvmd_sock == -1)
     217                 :          0 :                 return 0;
     218                 :            : 
     219                 :          0 :         _build_header(head, clvmd_cmd, node, len);
     220                 :          0 :         memcpy(head->node + strlen(head->node) + 1, data, len);
     221                 :            : 
     222                 :          0 :         status = _send_request(outbuf, sizeof(struct clvm_header) +
     223                 :            :                               strlen(head->node) + len, &retbuf);
     224         [ #  # ]:          0 :         if (!status)
     225                 :          0 :                 goto out;
     226                 :            : 
     227                 :            :         /* Count the number of responses we got */
     228                 :          0 :         head = (struct clvm_header *) retbuf;
     229                 :          0 :         inptr = head->args;
     230         [ #  # ]:          0 :         while (inptr[0]) {
     231                 :          0 :                 num_responses++;
     232                 :          0 :                 inptr += strlen(inptr) + 1;
     233                 :          0 :                 inptr += sizeof(int);
     234                 :          0 :                 inptr += strlen(inptr) + 1;
     235                 :            :         }
     236                 :            : 
     237                 :            :         /*
     238                 :            :          * Allocate response array.
     239                 :            :          * With an extra pair of INTs on the front to sanity
     240                 :            :          * check the pointer when we are given it back to free
     241                 :            :          */
     242                 :          0 :         *response = dm_malloc(sizeof(lvm_response_t) * num_responses);
     243         [ #  # ]:          0 :         if (!*response) {
     244                 :          0 :                 errno = ENOMEM;
     245                 :          0 :                 status = 0;
     246                 :          0 :                 goto out;
     247                 :            :         }
     248                 :            : 
     249                 :          0 :         rarray = *response;
     250                 :            : 
     251                 :            :         /* Unpack the response into an lvm_response_t array */
     252                 :          0 :         inptr = head->args;
     253                 :          0 :         i = 0;
     254         [ #  # ]:          0 :         while (inptr[0]) {
     255                 :          0 :                 strcpy(rarray[i].node, inptr);
     256                 :          0 :                 inptr += strlen(inptr) + 1;
     257                 :            : 
     258                 :          0 :                 memcpy(&rarray[i].status, inptr, sizeof(int));
     259                 :          0 :                 inptr += sizeof(int);
     260                 :            : 
     261                 :          0 :                 rarray[i].response = dm_malloc(strlen(inptr) + 1);
     262         [ #  # ]:          0 :                 if (rarray[i].response == NULL) {
     263                 :            :                         /* Free up everything else and return error */
     264                 :            :                         int j;
     265         [ #  # ]:          0 :                         for (j = 0; j < i; j++)
     266                 :          0 :                                 dm_free(rarray[i].response);
     267                 :          0 :                         free(*response);
     268                 :          0 :                         errno = ENOMEM;
     269                 :          0 :                         status = -1;
     270                 :          0 :                         goto out;
     271                 :            :                 }
     272                 :            : 
     273                 :          0 :                 strcpy(rarray[i].response, inptr);
     274                 :          0 :                 rarray[i].len = strlen(inptr);
     275                 :          0 :                 inptr += strlen(inptr) + 1;
     276                 :          0 :                 i++;
     277                 :            :         }
     278                 :          0 :         *num = num_responses;
     279                 :          0 :         *response = rarray;
     280                 :            : 
     281                 :            :       out:
     282         [ #  # ]:          0 :         if (retbuf)
     283                 :          0 :                 dm_free(retbuf);
     284                 :            : 
     285                 :          0 :         return status;
     286                 :            : }
     287                 :            : 
     288                 :            : /* Free reply array */
     289                 :          0 : static int _cluster_free_request(lvm_response_t * response, int num)
     290                 :            : {
     291                 :            :         int i;
     292                 :            : 
     293         [ #  # ]:          0 :         for (i = 0; i < num; i++) {
     294                 :          0 :                 dm_free(response[i].response);
     295                 :            :         }
     296                 :            : 
     297                 :          0 :         dm_free(response);
     298                 :            : 
     299                 :          0 :         return 1;
     300                 :            : }
     301                 :            : 
     302                 :          0 : static int _lock_for_cluster(struct cmd_context *cmd, unsigned char clvmd_cmd,
     303                 :            :                              uint32_t flags, const char *name)
     304                 :            : {
     305                 :            :         int status;
     306                 :            :         int i;
     307                 :            :         char *args;
     308                 :          0 :         const char *node = "";
     309                 :            :         int len;
     310                 :            :         int dmeventd_mode;
     311                 :          0 :         int saved_errno = errno;
     312                 :          0 :         lvm_response_t *response = NULL;
     313                 :            :         int num_responses;
     314                 :            : 
     315         [ #  # ]:          0 :         assert(name);
     316                 :            : 
     317                 :          0 :         len = strlen(name) + 3;
     318                 :          0 :         args = alloca(len);
     319                 :          0 :         strcpy(args + 2, name);
     320                 :            : 
     321                 :            :         /* Maskoff lock flags */
     322                 :          0 :         args[0] = flags & (LCK_SCOPE_MASK | LCK_TYPE_MASK | LCK_NONBLOCK | LCK_HOLD); 
     323                 :          0 :         args[1] = flags & (LCK_LOCAL | LCK_CLUSTER_VG);
     324                 :            : 
     325         [ #  # ]:          0 :         if (mirror_in_sync())
     326                 :          0 :                 args[1] |= LCK_MIRROR_NOSYNC_MODE;
     327                 :            : 
     328                 :            :         /*
     329                 :            :          * Must handle tri-state return from dmeventd_monitor_mode.
     330                 :            :          * But DMEVENTD_MONITOR_IGNORE is not propagated across the cluster.
     331                 :            :          */
     332                 :          0 :         dmeventd_mode = dmeventd_monitor_mode();
     333   [ #  #  #  # ]:          0 :         if (dmeventd_mode != DMEVENTD_MONITOR_IGNORE && dmeventd_mode)
     334                 :          0 :                 args[1] |= LCK_DMEVENTD_MONITOR_MODE;
     335                 :            : 
     336         [ #  # ]:          0 :         if (cmd->partial_activation)
     337                 :          0 :                 args[1] |= LCK_PARTIAL_MODE;
     338                 :            : 
     339                 :            :         /*
     340                 :            :          * VG locks are just that: locks, and have no side effects
     341                 :            :          * so we only need to do them on the local node because all
     342                 :            :          * locks are cluster-wide.
     343                 :            :          * Also, if the lock is exclusive it makes no sense to try to
     344                 :            :          * acquire it on all nodes, so just do that on the local node too.
     345                 :            :          * One exception, is that P_ locks /do/ get distributed across
     346                 :            :          * the cluster because they might have side-effects.
     347                 :            :          */
     348 [ #  # ][ #  # ]:          0 :         if (strncmp(name, "P_", 2) &&
         [ #  # ][ #  # ]
                 [ #  # ]
     349                 :            :             (clvmd_cmd == CLVMD_CMD_LOCK_VG ||
     350                 :          0 :              (flags & LCK_TYPE_MASK) == LCK_EXCL ||
     351                 :          0 :              (flags & LCK_LOCAL) ||
     352                 :          0 :              !(flags & LCK_CLUSTER_VG)))
     353                 :          0 :                 node = ".";
     354                 :            : 
     355                 :          0 :         status = _cluster_request(clvmd_cmd, node, args, len,
     356                 :            :                                   &response, &num_responses);
     357                 :            : 
     358                 :            :         /* If any nodes were down then display them and return an error */
     359         [ #  # ]:          0 :         for (i = 0; i < num_responses; i++) {
     360         [ #  # ]:          0 :                 if (response[i].status == EHOSTDOWN) {
     361                 :          0 :                         log_error("clvmd not running on node %s",
     362                 :            :                                   response[i].node);
     363                 :          0 :                         status = 0;
     364                 :          0 :                         errno = response[i].status;
     365         [ #  # ]:          0 :                 } else if (response[i].status) {
     366         [ #  # ]:          0 :                         log_error("Error locking on node %s: %s",
     367                 :            :                                   response[i].node,
     368                 :            :                                   response[i].response[0] ?
     369                 :            :                                         response[i].response :
     370                 :            :                                         strerror(response[i].status));
     371                 :          0 :                         status = 0;
     372                 :          0 :                         errno = response[i].status;
     373                 :            :                 }
     374                 :            :         }
     375                 :            : 
     376                 :          0 :         saved_errno = errno;
     377                 :          0 :         _cluster_free_request(response, num_responses);
     378                 :          0 :         errno = saved_errno;
     379                 :            : 
     380                 :          0 :         return status;
     381                 :            : }
     382                 :            : 
     383                 :            : /* API entry point for LVM */
     384                 :            : #ifdef CLUSTER_LOCKING_INTERNAL
     385                 :          0 : static int _lock_resource(struct cmd_context *cmd, const char *resource,
     386                 :            :                           uint32_t flags)
     387                 :            : #else
     388                 :            : int lock_resource(struct cmd_context *cmd, const char *resource, uint32_t flags)
     389                 :            : #endif
     390                 :            : {
     391                 :            :         char lockname[PATH_MAX];
     392                 :          0 :         int clvmd_cmd = 0;
     393                 :            :         const char *lock_scope;
     394                 :          0 :         const char *lock_type = "";
     395                 :            : 
     396         [ #  # ]:          0 :         assert(strlen(resource) < sizeof(lockname));
     397         [ #  # ]:          0 :         assert(resource);
     398                 :            : 
     399      [ #  #  # ]:          0 :         switch (flags & LCK_SCOPE_MASK) {
     400                 :            :         case LCK_VG:
     401         [ #  # ]:          0 :                 if (flags == LCK_VG_BACKUP) {
     402                 :          0 :                         log_very_verbose("Requesting backup of VG metadata for %s",
     403                 :            :                                          resource);
     404                 :          0 :                         return _lock_for_cluster(cmd, CLVMD_CMD_VG_BACKUP,
     405                 :            :                                                  LCK_CLUSTER_VG, resource);
     406                 :            :                 }
     407                 :            : 
     408                 :            :                 /* If the VG name is empty then lock the unused PVs */
     409 [ #  # ][ #  # ]:          0 :                 if (*resource == '#' || (flags & LCK_CACHE))
     410                 :          0 :                         dm_snprintf(lockname, sizeof(lockname), "P_%s",
     411                 :            :                                     resource);
     412                 :            :                 else
     413                 :          0 :                         dm_snprintf(lockname, sizeof(lockname), "V_%s",
     414                 :            :                                     resource);
     415                 :            : 
     416                 :          0 :                 lock_scope = "VG";
     417                 :          0 :                 clvmd_cmd = CLVMD_CMD_LOCK_VG;
     418                 :          0 :                 break;
     419                 :            : 
     420                 :            :         case LCK_LV:
     421                 :          0 :                 clvmd_cmd = CLVMD_CMD_LOCK_LV;
     422                 :          0 :                 strcpy(lockname, resource);
     423                 :          0 :                 lock_scope = "LV";
     424                 :          0 :                 flags &= ~LCK_HOLD; /* Mask off HOLD flag */
     425                 :          0 :                 break;
     426                 :            : 
     427                 :            :         default:
     428                 :          0 :                 log_error("Unrecognised lock scope: %d",
     429                 :            :                           flags & LCK_SCOPE_MASK);
     430                 :          0 :                 return 0;
     431                 :            :         }
     432                 :            : 
     433 [ #  #  #  #  # :          0 :         switch(flags & LCK_TYPE_MASK) {
                   #  # ]
     434                 :            :         case LCK_UNLOCK:
     435                 :          0 :                 lock_type = "UN";
     436                 :          0 :                 break;
     437                 :            :         case LCK_NULL:
     438                 :          0 :                 lock_type = "NL";
     439                 :          0 :                 break;
     440                 :            :         case LCK_READ:
     441                 :          0 :                 lock_type = "CR";
     442                 :          0 :                 break;
     443                 :            :         case LCK_PREAD:
     444                 :          0 :                 lock_type = "PR";
     445                 :          0 :                 break;
     446                 :            :         case LCK_WRITE:
     447                 :          0 :                 lock_type = "PW";
     448                 :          0 :                 break;
     449                 :            :         case LCK_EXCL:
     450                 :          0 :                 lock_type = "EX";
     451                 :          0 :                 break;
     452                 :            :         default:
     453                 :          0 :                 log_error("Unrecognised lock type: %u",
     454                 :            :                           flags & LCK_TYPE_MASK);
     455                 :          0 :                 return 0;
     456                 :            :         }
     457                 :            : 
     458 [ #  # ][ #  # ]:          0 :         log_very_verbose("Locking %s %s %s (%s%s%s%s%s%s) (0x%x)", lock_scope, lockname,
         [ #  # ][ #  # ]
                 [ #  # ]
     459                 :            :                          lock_type, lock_scope,
     460                 :            :                          flags & LCK_NONBLOCK ? "|NONBLOCK" : "",
     461                 :            :                          flags & LCK_HOLD ? "|HOLD" : "",
     462                 :            :                          flags & LCK_LOCAL ? "|LOCAL" : "",
     463                 :            :                          flags & LCK_CLUSTER_VG ? "|CLUSTER" : "",
     464                 :            :                          flags & LCK_CACHE ? "|CACHE" : "",
     465                 :            :                          flags);
     466                 :            : 
     467                 :            :         /* Send a message to the cluster manager */
     468                 :          0 :         return _lock_for_cluster(cmd, clvmd_cmd, flags, lockname);
     469                 :            : }
     470                 :            : 
     471                 :          0 : static int decode_lock_type(const char *response)
     472                 :            : {
     473         [ #  # ]:          0 :         if (!response)
     474                 :          0 :                 return LCK_NULL;
     475         [ #  # ]:          0 :         else if (strcmp(response, "EX"))
     476                 :          0 :                 return LCK_EXCL;
     477         [ #  # ]:          0 :         else if (strcmp(response, "CR"))
     478                 :          0 :                 return LCK_READ;
     479         [ #  # ]:          0 :         else if (strcmp(response, "PR"))
     480                 :          0 :                 return LCK_PREAD;
     481                 :            : 
     482                 :          0 :         stack;
     483                 :          0 :         return 0;
     484                 :            : }
     485                 :            : 
     486                 :            : #ifdef CLUSTER_LOCKING_INTERNAL
     487                 :          0 : static int _query_resource(const char *resource, int *mode)
     488                 :            : #else
     489                 :            : int query_resource(const char *resource, int *mode)
     490                 :            : #endif
     491                 :            : {
     492                 :            :         int i, status, len, num_responses, saved_errno;
     493                 :          0 :         const char *node = "";
     494                 :            :         char *args;
     495                 :          0 :         lvm_response_t *response = NULL;
     496                 :            : 
     497                 :          0 :         saved_errno = errno;
     498                 :          0 :         len = strlen(resource) + 3;
     499                 :          0 :         args = alloca(len);
     500                 :          0 :         strcpy(args + 2, resource);
     501                 :            : 
     502                 :          0 :         args[0] = 0;
     503                 :          0 :         args[1] = LCK_CLUSTER_VG;
     504                 :            : 
     505                 :          0 :         status = _cluster_request(CLVMD_CMD_LOCK_QUERY, node, args, len,
     506                 :            :                                   &response, &num_responses);
     507                 :          0 :         *mode = LCK_NULL;
     508         [ #  # ]:          0 :         for (i = 0; i < num_responses; i++) {
     509         [ #  # ]:          0 :                 if (response[i].status == EHOSTDOWN)
     510                 :          0 :                         continue;
     511                 :            : 
     512         [ #  # ]:          0 :                 if (!response[i].response[0])
     513                 :          0 :                         continue;
     514                 :            : 
     515                 :            :                 /*
     516                 :            :                  * All nodes should use CR, or exactly one node
     517                 :            :                  * should held EX. (PR is obsolete)
     518                 :            :                  * If two nodes node reports different locks,
     519                 :            :                  * something is broken - just return more important mode.
     520                 :            :                  */
     521         [ #  # ]:          0 :                 if (decode_lock_type(response[i].response) > *mode)
     522                 :          0 :                         *mode = decode_lock_type(response[i].response);
     523                 :            : 
     524                 :          0 :                 log_debug("Lock held for %s, node %s : %s", resource,
     525                 :            :                           response[i].node, response[i].response);
     526                 :            :         }
     527                 :            : 
     528                 :          0 :         _cluster_free_request(response, num_responses);
     529                 :          0 :         errno = saved_errno;
     530                 :            : 
     531                 :          0 :         return status;
     532                 :            : }
     533                 :            : 
     534                 :            : #ifdef CLUSTER_LOCKING_INTERNAL
     535                 :          0 : static void _locking_end(void)
     536                 :            : #else
     537                 :            : void locking_end(void)
     538                 :            : #endif
     539                 :            : {
     540 [ #  # ][ #  # ]:          0 :         if (_clvmd_sock != -1 && close(_clvmd_sock))
     541                 :          0 :                 stack;
     542                 :            : 
     543                 :          0 :         _clvmd_sock = -1;
     544                 :          0 : }
     545                 :            : 
     546                 :            : #ifdef CLUSTER_LOCKING_INTERNAL
     547                 :          0 : static void _reset_locking(void)
     548                 :            : #else
     549                 :            : void reset_locking(void)
     550                 :            : #endif
     551                 :            : {
     552         [ #  # ]:          0 :         if (close(_clvmd_sock))
     553                 :          0 :                 stack;
     554                 :            : 
     555                 :          0 :         _clvmd_sock = _open_local_sock();
     556         [ #  # ]:          0 :         if (_clvmd_sock == -1)
     557                 :          0 :                 stack;
     558                 :          0 : }
     559                 :            : 
     560                 :            : #ifdef CLUSTER_LOCKING_INTERNAL
     561                 :          0 : int init_cluster_locking(struct locking_type *locking, struct cmd_context *cmd)
     562                 :            : {
     563                 :          0 :         locking->lock_resource = _lock_resource;
     564                 :          0 :         locking->query_resource = _query_resource;
     565                 :          0 :         locking->fin_locking = _locking_end;
     566                 :          0 :         locking->reset_locking = _reset_locking;
     567                 :          0 :         locking->flags = LCK_PRE_MEMLOCK | LCK_CLUSTERED;
     568                 :            : 
     569                 :          0 :         _clvmd_sock = _open_local_sock();
     570         [ #  # ]:          0 :         if (_clvmd_sock == -1)
     571                 :          0 :                 return 0;
     572                 :            : 
     573                 :          0 :         return 1;
     574                 :            : }
     575                 :            : #else
     576                 :            : int locking_init(int type, struct config_tree *cf, uint32_t *flags)
     577                 :            : {
     578                 :            :         _clvmd_sock = _open_local_sock();
     579                 :            :         if (_clvmd_sock == -1)
     580                 :            :                 return 0;
     581                 :            : 
     582                 :            :         /* Ask LVM to lock memory before calling us */
     583                 :            :         *flags |= LCK_PRE_MEMLOCK;
     584                 :            :         *flags |= LCK_CLUSTERED;
     585                 :            : 
     586                 :            :         return 1;
     587                 :            : }
     588                 :            : #endif

Generated by: LCOV version 1.8