mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
Keep client locks (VG locks usually) in their own hash table so
we can actually have more then one of them per client.
This commit is contained in:
parent
167babfedb
commit
8ef0b7b9ef
@ -337,7 +337,7 @@ static void get_members()
|
|||||||
}
|
}
|
||||||
nodelist.max_members = count_nodes;
|
nodelist.max_members = count_nodes;
|
||||||
nodelist.nodes = nodes;
|
nodelist.nodes = nodes;
|
||||||
|
|
||||||
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
num_nodes = ioctl(cluster_sock, SIOCCLUSTER_GETMEMBERS, &nodelist);
|
||||||
if (num_nodes <= 0) {
|
if (num_nodes <= 0) {
|
||||||
perror("get node details");
|
perror("get node details");
|
||||||
@ -441,6 +441,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUGLOG("sync_lock: '%s' mode:%d flags=%d\n", resource,mode,flags);
|
||||||
/* Conversions need the lockid in the LKSB */
|
/* Conversions need the lockid in the LKSB */
|
||||||
if (flags & LKF_CONVERT)
|
if (flags & LKF_CONVERT)
|
||||||
lwait.lksb.sb_lkid = *lockid;
|
lwait.lksb.sb_lkid = *lockid;
|
||||||
@ -466,6 +467,7 @@ int sync_lock(const char *resource, int mode, int flags, int *lockid)
|
|||||||
*lockid = lwait.lksb.sb_lkid;
|
*lockid = lwait.lksb.sb_lkid;
|
||||||
|
|
||||||
errno = lwait.lksb.sb_status;
|
errno = lwait.lksb.sb_status;
|
||||||
|
DEBUGLOG("sync_lock: returning lkid %x\n", *lockid);
|
||||||
if (lwait.lksb.sb_status)
|
if (lwait.lksb.sb_status)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
@ -477,6 +479,8 @@ int sync_unlock(const char *resource /* UNUSED */, int lockid)
|
|||||||
int status;
|
int status;
|
||||||
struct lock_wait lwait;
|
struct lock_wait lwait;
|
||||||
|
|
||||||
|
DEBUGLOG("sync_unlock: '%s' lkid:%x\n", resource, lockid);
|
||||||
|
|
||||||
pthread_cond_init(&lwait.cond, NULL);
|
pthread_cond_init(&lwait.cond, NULL);
|
||||||
pthread_mutex_init(&lwait.mutex, NULL);
|
pthread_mutex_init(&lwait.mutex, NULL);
|
||||||
pthread_mutex_lock(&lwait.mutex);
|
pthread_mutex_lock(&lwait.mutex);
|
||||||
|
@ -66,6 +66,7 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "hash.h"
|
||||||
#include "locking.h"
|
#include "locking.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "lvm-functions.h"
|
#include "lvm-functions.h"
|
||||||
@ -135,6 +136,61 @@ int do_command(struct local_client *client, struct clvm_header *msg, int msglen,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lock_vg(struct local_client *client)
|
||||||
|
{
|
||||||
|
struct hash_table *lock_hash;
|
||||||
|
struct clvm_header *header =
|
||||||
|
(struct clvm_header *) client->bits.localsock.cmd;
|
||||||
|
unsigned char lock_cmd;
|
||||||
|
unsigned char lock_flags;
|
||||||
|
char *args = header->node + strlen(header->node) + 1;
|
||||||
|
int lkid;
|
||||||
|
int status = 0;
|
||||||
|
char *lockname;
|
||||||
|
|
||||||
|
/* Keep a track of VG locks in our own hash table. In current
|
||||||
|
practice there should only ever be more than two VGs locked
|
||||||
|
if a user tries to merge lots of them at once */
|
||||||
|
if (client->bits.localsock.private) {
|
||||||
|
lock_hash = (struct hash_table *)client->bits.localsock.private;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lock_hash = hash_create(3);
|
||||||
|
if (!lock_hash)
|
||||||
|
return ENOMEM;
|
||||||
|
client->bits.localsock.private = (void *)lock_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_cmd = args[0];
|
||||||
|
lock_flags = args[1];
|
||||||
|
lockname = &args[2];
|
||||||
|
DEBUGLOG("doing PRE command LOCK_VG '%s' at %x (client=%p)\n", lockname, lock_cmd, client);
|
||||||
|
|
||||||
|
if (lock_cmd == LCK_UNLOCK) {
|
||||||
|
|
||||||
|
lkid = (int)(long)hash_lookup(lock_hash, lockname);
|
||||||
|
if (lkid == 0)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
status = sync_unlock(lockname, lkid);
|
||||||
|
if (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
hash_remove(lock_hash, lockname);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
status = sync_lock(lockname, (int)lock_cmd, (int)lock_flags, &lkid);
|
||||||
|
if (status)
|
||||||
|
status = errno;
|
||||||
|
else
|
||||||
|
hash_insert(lock_hash, lockname, (void *)lkid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Pre-command is a good place to get locks that are needed only for the duration
|
/* Pre-command is a good place to get locks that are needed only for the duration
|
||||||
of the commands around the cluster (don't forget to free them in post-command),
|
of the commands around the cluster (don't forget to free them in post-command),
|
||||||
and to sanity check the command arguments */
|
and to sanity check the command arguments */
|
||||||
@ -156,22 +212,7 @@ int do_pre_command(struct local_client *client)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_VG:
|
case CLVMD_CMD_LOCK_VG:
|
||||||
lock_cmd = args[0];
|
status = lock_vg(client);
|
||||||
lock_flags = args[1];
|
|
||||||
lockname = &args[2];
|
|
||||||
DEBUGLOG("doing PRE command LOCK_VG %s at %x\n", lockname,
|
|
||||||
lock_cmd);
|
|
||||||
if (lock_cmd == LCK_UNLOCK) {
|
|
||||||
status = sync_unlock(lockname, (int) (long) client->bits.localsock.private);
|
|
||||||
if (status)
|
|
||||||
status = errno;
|
|
||||||
} else {
|
|
||||||
status = sync_lock(lockname, (int) lock_cmd, (int) lock_flags, &lockid);
|
|
||||||
if (status)
|
|
||||||
status = errno;
|
|
||||||
else
|
|
||||||
client->bits.localsock.private = (void *) lockid;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_LV:
|
case CLVMD_CMD_LOCK_LV:
|
||||||
@ -204,6 +245,7 @@ int do_post_command(struct local_client *client)
|
|||||||
case CLVMD_CMD_TEST:
|
case CLVMD_CMD_TEST:
|
||||||
status =
|
status =
|
||||||
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
sync_unlock("CLVMD_TEST", (int) (long) client->bits.localsock.private);
|
||||||
|
client->bits.localsock.private = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CLVMD_CMD_LOCK_VG:
|
case CLVMD_CMD_LOCK_VG:
|
||||||
@ -219,3 +261,25 @@ int do_post_command(struct local_client *client)
|
|||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Called when the client is about to be deleted */
|
||||||
|
void cmd_client_cleanup(struct local_client *client)
|
||||||
|
{
|
||||||
|
if (client->bits.localsock.private) {
|
||||||
|
|
||||||
|
struct hash_node *v;
|
||||||
|
struct hash_table *lock_hash =
|
||||||
|
(struct hash_table *)client->bits.localsock.private;
|
||||||
|
|
||||||
|
hash_iterate(v, lock_hash) {
|
||||||
|
int lkid = (int)(long)hash_get_data(lock_hash, v);
|
||||||
|
|
||||||
|
DEBUGLOG("cleanup: Unlocking lkid %x\n", lkid);
|
||||||
|
sync_unlock("DUMMY", lkid);
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_destroy(lock_hash);
|
||||||
|
client->bits.localsock.private = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -303,6 +303,7 @@ static int local_rendezvous_callback(struct local_client *thisfd, char *buf,
|
|||||||
newfd->bits.localsock.threadid = 0;
|
newfd->bits.localsock.threadid = 0;
|
||||||
newfd->bits.localsock.finished = 0;
|
newfd->bits.localsock.finished = 0;
|
||||||
newfd->bits.localsock.pipe_client = NULL;
|
newfd->bits.localsock.pipe_client = NULL;
|
||||||
|
newfd->bits.localsock.private = NULL;
|
||||||
newfd->bits.localsock.all_success = 1;
|
newfd->bits.localsock.all_success = 1;
|
||||||
DEBUGLOG("Got new connection on fd %d\n", newfd->fd);
|
DEBUGLOG("Got new connection on fd %d\n", newfd->fd);
|
||||||
*new_client = newfd;
|
*new_client = newfd;
|
||||||
@ -496,6 +497,7 @@ static void main_loop(int local_sock, int cmd_timeout)
|
|||||||
lastfd->next = thisfd->next;
|
lastfd->next = thisfd->next;
|
||||||
free_fd = thisfd;
|
free_fd = thisfd;
|
||||||
thisfd = lastfd;
|
thisfd = lastfd;
|
||||||
|
cmd_client_cleanup(free_fd);
|
||||||
free(free_fd);
|
free(free_fd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -717,6 +719,7 @@ static int read_from_local_sock(struct local_client *thisfd)
|
|||||||
struct local_client *newfd;
|
struct local_client *newfd;
|
||||||
char csid[MAX_CSID_LEN];
|
char csid[MAX_CSID_LEN];
|
||||||
struct clvm_header *inheader;
|
struct clvm_header *inheader;
|
||||||
|
int status;
|
||||||
|
|
||||||
inheader = (struct clvm_header *) buffer;
|
inheader = (struct clvm_header *) buffer;
|
||||||
|
|
||||||
@ -863,8 +866,10 @@ static int read_from_local_sock(struct local_client *thisfd)
|
|||||||
/* Run the pre routine */
|
/* Run the pre routine */
|
||||||
thisfd->bits.localsock.in_progress = TRUE;
|
thisfd->bits.localsock.in_progress = TRUE;
|
||||||
thisfd->bits.localsock.state = PRE_COMMAND;
|
thisfd->bits.localsock.state = PRE_COMMAND;
|
||||||
pthread_create(&thisfd->bits.localsock.threadid, NULL,
|
DEBUGLOG("Creating pre&post thread\n");
|
||||||
|
status = pthread_create(&thisfd->bits.localsock.threadid, NULL,
|
||||||
pre_and_post_thread, thisfd);
|
pre_and_post_thread, thisfd);
|
||||||
|
DEBUGLOG("Created pre&post thread, state = %d\n", status);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
@ -111,7 +111,7 @@ extern int do_command(struct local_client *client, struct clvm_header *msg,
|
|||||||
/* Pre and post command routines are called only on the local node */
|
/* Pre and post command routines are called only on the local node */
|
||||||
extern int do_pre_command(struct local_client *client);
|
extern int do_pre_command(struct local_client *client);
|
||||||
extern int do_post_command(struct local_client *client);
|
extern int do_post_command(struct local_client *client);
|
||||||
|
extern void cmd_client_cleanup(struct local_client *client);
|
||||||
extern int add_client(struct local_client *new_client);
|
extern int add_client(struct local_client *new_client);
|
||||||
|
|
||||||
extern void clvmd_cluster_init_completed(void);
|
extern void clvmd_cluster_init_completed(void);
|
||||||
|
@ -105,6 +105,7 @@
|
|||||||
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
#define MSG_MULTICAST 0x080000 /* Message was sent to all nodes in the cluster
|
||||||
*/
|
*/
|
||||||
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
#define MSG_ALLINT 0x100000 /* Send out of all interfaces */
|
||||||
|
#define MSG_REPLYEXP 0x200000 /* Reply is expected */
|
||||||
|
|
||||||
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
typedef enum { NODESTATE_REMOTEMEMBER, NODESTATE_JOINING, NODESTATE_MEMBER,
|
||||||
NODESTATE_DEAD } nodestate_t;
|
NODESTATE_DEAD } nodestate_t;
|
||||||
|
Loading…
Reference in New Issue
Block a user