src/cmd.c | 56 +++++++++++++++++++++++++++++++++--
src/direct.c | 2 -
src/paxos_lease.c | 4 ++
src/paxos_lease.h | 1
src/resource.c | 24 ++++++++-------
src/resource.h | 3 +
src/sanlock_resource.h | 19 +++++++++++-
tests/sanlk_rename.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 170 insertions(+), 16 deletions(-)
New commits:
commit 3fd9e04789e220ef85bb9b852c8d2d957d55707a
Author: David Teigland <teigland(a)redhat.com>
Date: Wed Jul 10 16:32:47 2013 -0500
sanlock: add SANLK_REL_RENAME
Used to rename a resource when releasing the lease.
Signed-off-by: David Teigland <teigland(a)redhat.com>
diff --git a/src/cmd.c b/src/cmd.c
index 4ca87f2..da56d9d 100644
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -65,7 +65,7 @@ static void release_cl_tokens(struct task *task, struct client *cl)
token = cl->tokens[j];
if (!token)
continue;
- release_token(task, token);
+ release_token(task, token, NULL);
free(token);
}
}
@@ -76,7 +76,7 @@ static void release_new_tokens(struct task *task, struct token
*new_tokens[],
int i;
for (i = 0; i < acquire_count; i++)
- release_token(task, new_tokens[i]);
+ release_token(task, new_tokens[i], NULL);
for (i = 0; i < alloc_count; i++)
free(new_tokens[i]);
@@ -477,6 +477,8 @@ static void cmd_release(struct task *task, struct cmd_args *ca)
struct token *token;
struct token *rem_tokens[SANLK_MAX_RESOURCES];
struct sanlk_resource res;
+ struct sanlk_resource new;
+ struct sanlk_resource *resrename = NULL;
int fd, rv, i, j, found, pid_dead;
int rem_tokens_count = 0;
int result = 0;
@@ -506,6 +508,54 @@ static void cmd_release(struct task *task, struct cmd_args *ca)
goto do_remove;
}
+ if (ca->header.cmd_flags & SANLK_REL_RENAME) {
+ rv = recv(fd, &res, sizeof(struct sanlk_resource), MSG_WAITALL);
+ if (rv != sizeof(struct sanlk_resource)) {
+ log_error("cmd_release %d,%d,%d recv res %d %d",
+ cl_ci, cl_fd, cl_pid, rv, errno);
+ result = -ENOTCONN;
+ goto do_remove;
+ }
+
+ /* second res struct has new name for first res */
+ rv = recv(fd, &new, sizeof(struct sanlk_resource), MSG_WAITALL);
+ if (rv != sizeof(struct sanlk_resource)) {
+ log_error("cmd_release %d,%d,%d recv new %d %d",
+ cl_ci, cl_fd, cl_pid, rv, errno);
+ result = -ENOTCONN;
+ goto do_remove;
+ }
+
+ found = 0;
+
+ pthread_mutex_lock(&cl->mutex);
+ for (j = 0; j < SANLK_MAX_RESOURCES; j++) {
+ token = cl->tokens[j];
+ if (!token)
+ continue;
+
+ if (memcmp(token->r.lockspace_name, res.lockspace_name, NAME_ID_SIZE))
+ continue;
+ if (memcmp(token->r.name, res.name, NAME_ID_SIZE))
+ continue;
+
+ rem_tokens[rem_tokens_count++] = token;
+ cl->tokens[j] = NULL;
+ found = 1;
+ break;
+ }
+ pthread_mutex_unlock(&cl->mutex);
+
+ if (!found) {
+ log_error("cmd_release %d,%d,%d no resource %.48s",
+ cl_ci, cl_fd, cl_pid, res.name);
+ result = -1;
+ }
+
+ resrename = &new;
+ goto do_remove;
+ }
+
/* caller is specifying specific resources to release */
for (i = 0; i < ca->header.data; i++) {
@@ -548,7 +598,7 @@ static void cmd_release(struct task *task, struct cmd_args *ca)
for (i = 0; i < rem_tokens_count; i++) {
token = rem_tokens[i];
- rv = release_token(task, token);
+ rv = release_token(task, token, resrename);
if (rv < 0)
result = rv;
free(token);
diff --git a/src/direct.c b/src/direct.c
index 63684b8..ed6cca4 100644
--- a/src/direct.c
+++ b/src/direct.c
@@ -132,7 +132,7 @@ static int do_paxos_action(int action, struct task *task, int
io_timeout,
rv = paxos_lease_leader_read(task, token, &leader, "direct_release");
if (rv < 0)
break;
- rv = paxos_lease_release(task, token, &leader, leader_ret);
+ rv = paxos_lease_release(task, token, NULL, &leader, leader_ret);
break;
case ACT_READ_LEADER:
diff --git a/src/paxos_lease.c b/src/paxos_lease.c
index 69a4ed1..3b21017 100644
--- a/src/paxos_lease.c
+++ b/src/paxos_lease.c
@@ -1669,6 +1669,7 @@ int paxos_lease_renew(struct task *task,
int paxos_lease_release(struct task *task,
struct token *token,
+ struct sanlk_resource *resrename,
struct leader_record *leader_last,
struct leader_record *leader_ret)
{
@@ -1725,6 +1726,9 @@ int paxos_lease_release(struct task *task,
*/
}
+ if (resrename)
+ memcpy(leader.resource_name, resrename->name, NAME_ID_SIZE);
+
leader.timestamp = LEASE_FREE;
leader.write_id = token->host_id;
leader.write_generation = token->host_generation;
diff --git a/src/paxos_lease.h b/src/paxos_lease.h
index d924923..588cb39 100644
--- a/src/paxos_lease.h
+++ b/src/paxos_lease.h
@@ -29,6 +29,7 @@ int paxos_lease_acquire(struct task *task,
int paxos_lease_release(struct task *task,
struct token *token,
+ struct sanlk_resource *resrename,
struct leader_record *leader_last,
struct leader_record *leader_ret);
diff --git a/src/resource.c b/src/resource.c
index 2fa0752..b2a7ba1 100644
--- a/src/resource.c
+++ b/src/resource.c
@@ -556,12 +556,13 @@ static int acquire_disk(struct task *task, struct token *token,
/* return < 0 on error, 1 on success */
static int release_disk(struct task *task, struct token *token,
- struct leader_record *leader)
+ struct sanlk_resource *resrename,
+ struct leader_record *leader)
{
struct leader_record leader_tmp;
int rv;
- rv = paxos_lease_release(task, token, leader, &leader_tmp);
+ rv = paxos_lease_release(task, token, resrename, leader, &leader_tmp);
log_token(token, "release_disk rv %d", rv);
@@ -572,7 +573,9 @@ static int release_disk(struct task *task, struct token *token,
return rv; /* SANLK_OK */
}
-static int _release_token(struct task *task, struct token *token, int opened, int
nodisk)
+static int _release_token(struct task *task, struct token *token,
+ struct sanlk_resource *resrename,
+ int opened, int nodisk)
{
struct resource *r = token->resource;
uint64_t lver;
@@ -642,7 +645,7 @@ static int _release_token(struct task *task, struct token *token, int
opened, in
if (r->flags & R_LVB_WRITE_RELEASE)
write_lvb_block(task, r, token);
- rv = release_disk(task, token, &r->leader);
+ rv = release_disk(task, token, resrename, &r->leader);
}
close_disks(token->disks, token->r.num_disks);
@@ -664,17 +667,18 @@ static int _release_token(struct task *task, struct token *token,
int opened, in
static int release_token_nodisk(struct task *task, struct token *token)
{
- return _release_token(task, token, 0, 1);
+ return _release_token(task, token, NULL, 0, 1);
}
static int release_token_opened(struct task *task, struct token *token)
{
- return _release_token(task, token, 1, 0);
+ return _release_token(task, token, NULL, 1, 0);
}
-int release_token(struct task *task, struct token *token)
+int release_token(struct task *task, struct token *token,
+ struct sanlk_resource *resrename)
{
- return _release_token(task, token, 0, 0);
+ return _release_token(task, token, resrename, 0, 0);
}
/* We're releasing a token from the main thread, in which we don't want to
block,
@@ -931,7 +935,7 @@ int acquire_token(struct task *task, struct token *token, uint32_t
cmd_flags,
release_token_opened(task, token);
return rv;
} else {
- release_disk(task, token, &leader);
+ release_disk(task, token, NULL, &leader);
/* the token is kept, the paxos lease is released but with shared set */
goto out;
}
@@ -1195,7 +1199,7 @@ static void resource_thread_release(struct task *task, struct
resource *r, struc
if (r->flags & R_LVB_WRITE_RELEASE)
write_lvb_block(task, r, tt);
- release_disk(task, tt, &r->leader);
+ release_disk(task, tt, NULL, &r->leader);
}
close_disks(tt->disks, tt->r.num_disks);
diff --git a/src/resource.h b/src/resource.h
index 25e9c58..11ea4c0 100644
--- a/src/resource.h
+++ b/src/resource.h
@@ -17,7 +17,8 @@ void check_mode_block(struct token *token, int q, char *dblock);
int acquire_token(struct task *task, struct token *token, uint32_t cmd_flags,
char *killpath, char *killargs);
-int release_token(struct task *task, struct token *token);
+int release_token(struct task *task, struct token *token,
+ struct sanlk_resource *resrename);
void release_token_async(struct token *token);
int request_token(struct task *task, struct token *token, uint32_t force_mode,
diff --git a/src/sanlock_resource.h b/src/sanlock_resource.h
index 9c6112f..f691032 100644
--- a/src/sanlock_resource.h
+++ b/src/sanlock_resource.h
@@ -31,8 +31,25 @@
/* acquire flags */
#define SANLK_ACQUIRE_LVB 0x00000001
-/* release flags */
+/*
+ * release flags
+ *
+ * SANLK_REL_ALL
+ * Release all resources held by the client.
+ * The res args are ignored.
+ *
+ * SANLK_REL_RENAME
+ * Rename the resource lease on disk when it
+ * is released. The resource is freed and
+ * renamed in a single disk operation (write
+ * to the leader record.) The first res
+ * arg is the resource to release, and the
+ * second resource arg contains the new name
+ * for the first resource.
+ */
+
#define SANLK_REL_ALL 0x00000001
+#define SANLK_REL_RENAME 0x00000002
/*
* request flags
diff --git a/tests/sanlk_rename.c b/tests/sanlk_rename.c
new file mode 100644
index 0000000..4043c3e
--- /dev/null
+++ b/tests/sanlk_rename.c
@@ -0,0 +1,77 @@
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/un.h>
+#include <sys/mount.h>
+#include <sys/signalfd.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <signal.h>
+
+#include "sanlock.h"
+#include "sanlock_resource.h"
+
+/* gcc with -lsanlock */
+
+int main(int argc, char *argv[])
+{
+ char rd[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
+ char rd2[sizeof(struct sanlk_resource) + sizeof(struct sanlk_disk)];
+ struct sanlk_resource *res;
+ struct sanlk_resource *res2;
+ struct sanlk_resource **res_args;
+ int fd, rv;
+
+ if (argc < 6) {
+ printf("acquire with old name, release with new name\n");
+ printf("sanlk_rename <lockspace_name> <resource_name_old>
<resource_name_new> <path> <resource_offset>\n");
+ return -1;
+ }
+
+ res_args = malloc(2 * sizeof(struct sanlk_resource *));
+
+ memset(rd, 0, sizeof(rd));
+ memset(rd2, 0, sizeof(rd2));
+
+ res = (struct sanlk_resource *)&rd;
+ res2 = (struct sanlk_resource *)&rd2;
+
+ res_args[0] = res;
+ res_args[1] = res2;
+
+ strcpy(res->lockspace_name, argv[1]);
+ strcpy(res->name, argv[2]);
+ strcpy(res2->name, argv[3]);
+ res->num_disks = 1;
+ strcpy(res->disks[0].path, argv[4]);
+ res->disks[0].offset = atoi(argv[5]);
+
+ fd = sanlock_register();
+ if (fd < 0) {
+ fprintf(stderr, "register error %d\n", fd);
+ return -1;
+ }
+
+ rv = sanlock_acquire(fd, -1, 0, 1, &res, NULL);
+ if (rv < 0) {
+ fprintf(stderr, "acquire error %d\n", rv);
+ return -1;
+ }
+
+ rv = sanlock_release(fd, -1, SANLK_REL_RENAME, 2, res_args);
+ if (rv < 0) {
+ fprintf(stderr, "release error %d\n", rv);
+ return -1;
+ }
+
+ return 0;
+}
+