[sheepdog] [PATCH v3 2/7] sheep: revive lock operation
Hitoshi Mitake
mitake.hitoshi at lab.ntt.co.jp
Thu Jul 31 04:51:23 CEST 2014
Current sheepdog doesn't support vdi locking. This patch and
succeeding ones revive the feature. With this feature, more than two
clients (including QEMU and tgt) are not allowed to open same VDI at
the same time.
Cc: Fabian Zimmermann <dev.faz at gmail.com>
Cc: Valerio Pachera <sirio81 at gmail.com>
Signed-off-by: Hitoshi Mitake <mitake.hitoshi at lab.ntt.co.jp>
---
sheep/ops.c | 41 ++++++++++++++++++++++----
sheep/sheep_priv.h | 3 ++
sheep/vdi.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 125 insertions(+), 5 deletions(-)
diff --git a/sheep/ops.c b/sheep/ops.c
index 58ff397..dce0edc 100644
--- a/sheep/ops.c
+++ b/sheep/ops.c
@@ -1306,6 +1306,34 @@ static int local_repair_replica(struct request *req)
return ret;
}
+static int cluster_lock_vdi(const struct sd_req *req, struct sd_rsp *rsp,
+ void *data, const struct sd_node *sender)
+{
+ uint32_t vid = rsp->vdi.vdi_id;
+
+ sd_info("node: %s is locking VDI: %"PRIx32, node_to_str(sender), vid);
+
+ if (!vdi_lock(vid, &sender->nid)) {
+ sd_err("locking %"PRIx32 "failed", vid);
+ return SD_RES_VDI_NOT_LOCKED;
+ }
+
+ return SD_RES_SUCCESS;
+}
+
+static int cluster_release_vdi_main(const struct sd_req *req,
+ struct sd_rsp *rsp, void *data,
+ const struct sd_node *sender)
+{
+ uint32_t vid = req->vdi.base_vdi_id;
+
+ sd_info("node: %s is unlocking VDI: %"PRIx32, node_to_str(sender), vid);
+
+ vdi_unlock(vid, &sender->nid);
+
+ return SD_RES_SUCCESS;
+}
+
static struct sd_op_template sd_ops[] = {
/* cluster operations */
@@ -1400,6 +1428,14 @@ static struct sd_op_template sd_ops[] = {
.name = "LOCK_VDI",
.type = SD_OP_TYPE_CLUSTER,
.process_work = cluster_get_vdi_info,
+ .process_main = cluster_lock_vdi,
+ },
+
+ [SD_OP_RELEASE_VDI] = {
+ .name = "RELEASE_VDI",
+ .type = SD_OP_TYPE_CLUSTER,
+ .process_work = local_release_vdi,
+ .process_main = cluster_release_vdi_main,
},
[SD_OP_REWEIGHT] = {
@@ -1438,11 +1474,6 @@ static struct sd_op_template sd_ops[] = {
},
/* local operations */
- [SD_OP_RELEASE_VDI] = {
- .name = "RELEASE_VDI",
- .type = SD_OP_TYPE_LOCAL,
- .process_work = local_release_vdi,
- },
[SD_OP_GET_STORE_LIST] = {
.name = "GET_STORE_LIST",
diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
index b0156ee..edca05a 100644
--- a/sheep/sheep_priv.h
+++ b/sheep/sheep_priv.h
@@ -345,6 +345,9 @@ int sd_delete_vdi(const char *name);
int sd_lookup_vdi(const char *name, uint32_t *vid);
int sd_create_hyper_volume(const char *name, uint32_t *vdi_id);
+bool vdi_lock(uint32_t vid, const struct node_id *owner);
+bool vdi_unlock(uint32_t vid, const struct node_id *owner);
+
extern int ec_max_data_strip;
int read_vdis(char *data, int len, unsigned int *rsp_len);
diff --git a/sheep/vdi.c b/sheep/vdi.c
index 747c810..b2a9e03 100644
--- a/sheep/vdi.c
+++ b/sheep/vdi.c
@@ -11,11 +11,23 @@
#include "sheep_priv.h"
+enum lock_state {
+ LOCK_STATE_INIT,
+ LOCK_STATE_LOCKED,
+ LOCK_STATE_UNLOCKED,
+};
+
+struct vdi_lock_state {
+ enum lock_state state;
+ struct node_id owner;
+};
+
struct vdi_state_entry {
uint32_t vid;
unsigned int nr_copies;
bool snapshot;
uint8_t copy_policy;
+ struct vdi_lock_state lock_state;
struct rb_node node;
};
@@ -148,6 +160,9 @@ int add_vdi_state(uint32_t vid, int nr_copies, bool snapshot, uint8_t cp)
entry->snapshot = snapshot;
entry->copy_policy = cp;
+ entry->lock_state.state = LOCK_STATE_INIT;
+ memset(&entry->lock_state.owner, 0, sizeof(struct node_id));
+
if (cp) {
int d;
@@ -235,6 +250,77 @@ out:
return ret;
}
+bool vdi_lock(uint32_t vid, const struct node_id *owner)
+{
+ struct vdi_state_entry *entry;
+ bool ret = false;
+
+ sd_write_lock(&vdi_state_lock);
+
+ entry = vdi_state_search(&vdi_state_root, vid);
+ if (!entry) {
+ sd_err("no vdi state entry of %"PRIx32" found", vid);
+ goto out;
+ }
+
+ switch (entry->lock_state.state) {
+ case LOCK_STATE_INIT:
+ case LOCK_STATE_UNLOCKED:
+ entry->lock_state.state = LOCK_STATE_LOCKED;
+ memcpy(&entry->lock_state.owner, owner, sizeof(*owner));
+ sd_info("VDI %"PRIx32" is locked", vid);
+ ret = true;
+ goto out;
+ case LOCK_STATE_LOCKED:
+ sd_info("VDI %"PRIx32" is already locked", vid);
+ break;
+ default:
+ sd_alert("lock state of VDI (%"PRIx32") is unknown: %d",
+ vid, entry->lock_state.state);
+ break;
+ }
+
+out:
+ sd_rw_unlock(&vdi_state_lock);
+ return ret;
+}
+
+bool vdi_unlock(uint32_t vid, const struct node_id *owner)
+{
+ struct vdi_state_entry *entry;
+ bool ret = false;
+
+ sd_write_lock(&vdi_state_lock);
+
+ entry = vdi_state_search(&vdi_state_root, vid);
+ if (!entry) {
+ sd_err("no vdi state entry of %"PRIx32" found", vid);
+ ret = false;
+ goto out;
+ }
+
+ switch (entry->lock_state.state) {
+ case LOCK_STATE_INIT:
+ case LOCK_STATE_UNLOCKED:
+ sd_err("unlocking unlocked VDI: %"PRIx32, vid);
+ break;
+ case LOCK_STATE_LOCKED:
+ entry->lock_state.state = LOCK_STATE_UNLOCKED;
+ memset(&entry->lock_state.owner, 0,
+ sizeof(entry->lock_state.owner));
+ ret = true;
+ break;
+ default:
+ sd_alert("lock state of VDI (%"PRIx32") is unknown: %d",
+ vid, entry->lock_state.state);
+ break;
+ }
+
+out:
+ sd_rw_unlock(&vdi_state_lock);
+ return ret;
+}
+
static struct sd_inode *alloc_inode(const struct vdi_iocb *iocb,
uint32_t new_snapid, uint32_t new_vid,
uint32_t *data_vdi_id,
--
1.8.3.2
More information about the sheepdog
mailing list