[sheepdog] [PATCH 1/2] sbd: add support for read/write cloned vdi
Liu Yuan
namei.unix at gmail.com
Fri May 30 08:37:17 CEST 2014
From: Liu Yuan <tailai.ly at taobao.com>
Signed-off-by: Liu Yuan <namei.unix at gmail.com>
---
sbd/sbd.h | 1 +
sbd/sheep.c | 68 +++++++++++++++++++++++++++++++++++++------------------------
2 files changed, 42 insertions(+), 27 deletions(-)
diff --git a/sbd/sbd.h b/sbd/sbd.h
index 6762369..5fb0a92 100644
--- a/sbd/sbd.h
+++ b/sbd/sbd.h
@@ -90,6 +90,7 @@ struct sheep_request {
struct list_head list;
struct sheep_aiocb *aiocb;
u64 oid;
+ u64 cow_oid;
u32 seq_num;
int type;
int offset;
diff --git a/sbd/sheep.c b/sbd/sheep.c
index acd5b08..b1cbbfb 100644
--- a/sbd/sheep.c
+++ b/sbd/sheep.c
@@ -276,6 +276,7 @@ static int submit_sheep_request(struct sheep_request *req)
hdr.id = req->seq_num;
hdr.data_length = req->length;
hdr.obj.oid = req->oid;
+ hdr.obj.cow_oid = req->cow_oid;
hdr.obj.offset = req->offset;
write_lock(&dev->inflight_lock);
@@ -291,6 +292,8 @@ static int submit_sheep_request(struct sheep_request *req)
else
hdr.opcode = SD_OP_WRITE_OBJ;
hdr.flags = SD_FLAG_CMD_WRITE | SD_FLAG_CMD_DIRECT;
+ if (req->cow_oid)
+ hdr.flags |= SD_FLAG_CMD_COW;
ret = sheep_submit_sdreq(dev->sock, &hdr, req->buf,
req->length);
if (ret < 0)
@@ -400,8 +403,13 @@ struct sheep_aiocb *sheep_aiocb_setup(struct request *req)
return aiocb;
}
+static inline bool aiocb_is_write(struct sheep_aiocb *aiocb)
+{
+ return aiocb->aio_done_func == aio_write_done;
+}
+
static struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb,
- u64 oid, int len,
+ u64 oid, u64 cow_oid, int len,
int offset)
{
struct sheep_request *req = kmem_cache_alloc(sheep_request_pool,
@@ -414,24 +422,15 @@ static struct sheep_request *alloc_sheep_request(struct sheep_aiocb *aiocb,
req->offset = offset;
req->length = len;
req->oid = oid;
+ req->cow_oid = cow_oid;
req->aiocb = aiocb;
req->buf = aiocb->buf + aiocb->buf_iter;
req->seq_num = atomic_inc_return(&dev->seq_num);
INIT_LIST_HEAD(&req->list);
-
- switch (rq_data_dir(aiocb->request)) {
- case WRITE:
+ if (aiocb_is_write(aiocb))
req->type = SHEEP_WRITE;
- break;
- case READ:
+ else
req->type = SHEEP_READ;
- break;
- default:
- /* impossible case */
- WARN_ON(1);
- kmem_cache_free(sheep_request_pool, req);
- return ERR_PTR(-EINVAL);
- }
aiocb->buf_iter += len;
atomic_inc(&aiocb->nr_requests);
@@ -468,15 +467,15 @@ static struct sheep_request *find_inflight_request_oid(struct sbd_device *dev,
return NULL;
}
-static bool sheep_inode_has_idx(struct sbd_device *dev, u32 idx)
+static uint32_t sheep_inode_get_idx(struct sbd_device *dev, u32 idx)
{
+ uint32_t vid;
+
spin_lock(&dev->vdi_lock);
- if (dev->vdi.inode->data_vdi_id[idx]) {
- spin_unlock(&dev->vdi_lock);
- return true;
- }
+ vid = dev->vdi.inode->data_vdi_id[idx];
spin_unlock(&dev->vdi_lock);
- return false;
+
+ return vid;
}
int sheep_aiocb_submit(struct sheep_aiocb *aiocb)
@@ -485,8 +484,7 @@ int sheep_aiocb_submit(struct sheep_aiocb *aiocb)
u64 offset = aiocb->offset;
u64 total = aiocb->length;
u64 start = offset % SD_DATA_OBJ_SIZE;
- u32 vid = dev->vdi.vid;
- u64 oid = vid_to_data_oid(vid, offset / SD_DATA_OBJ_SIZE);
+ u32 idx = offset / SD_DATA_OBJ_SIZE;
int len = SD_DATA_OBJ_SIZE - start;
if (total < len)
@@ -502,16 +500,27 @@ int sheep_aiocb_submit(struct sheep_aiocb *aiocb)
do {
struct sheep_request *req;
- u32 idx = data_oid_to_idx(oid);
+ u64 oid = vid_to_data_oid(dev->vdi.vid, idx), cow_oid = 0;
+ uint32_t vid = sheep_inode_get_idx(dev, idx);
+
+ /*
+ * For read, either read cow object or end the request.
+ * For write, copy-on-write cow object
+ */
+ if (vid && vid != dev->vdi.vid) {
+ if (aiocb_is_write(aiocb))
+ cow_oid = vid_to_data_oid(vid, idx);
+ else
+ oid = vid_to_data_oid(vid, idx);
+ }
- req = alloc_sheep_request(aiocb, oid, len, start);
+ req = alloc_sheep_request(aiocb, oid, cow_oid, len, start);
if (IS_ERR(req))
return PTR_ERR(req);
- if (likely(sheep_inode_has_idx(dev, idx)))
+ if (likely(vid && !cow_oid))
goto submit;
- /* Object is not created yet... */
switch (req->type) {
case SHEEP_WRITE:
/*
@@ -520,12 +529,16 @@ int sheep_aiocb_submit(struct sheep_aiocb *aiocb)
* write reqs in next.
*/
if (find_inflight_request_oid(dev, oid)) {
+ uint32_t tmp_vid;
+
write_lock(&dev->blocking_lock);
/*
* There are slim chance object was created
* before we grab blocking_lock
*/
- if (unlikely(sheep_inode_has_idx(dev, idx))) {
+ tmp_vid = sheep_inode_get_idx(dev, idx);
+ if (unlikely(tmp_vid && tmp_vid ==
+ dev->vdi.vid)) {
write_unlock(&dev->blocking_lock);
goto submit;
}
@@ -545,7 +558,7 @@ int sheep_aiocb_submit(struct sheep_aiocb *aiocb)
submit:
submit_sheep_request(req);
done:
- oid++;
+ idx++;
total -= len;
start = (start + len) % SD_DATA_OBJ_SIZE;
len = total > SD_DATA_OBJ_SIZE ? SD_DATA_OBJ_SIZE : total;
@@ -634,6 +647,7 @@ int sheep_handle_reply(struct sbd_device *dev)
new->offset = SD_INODE_HEADER_SIZE + sizeof(vid) * idx;
new->length = sizeof(vid);
new->oid = oid;
+ new->cow_oid = 0;
new->aiocb = req->aiocb;
new->buf = (char *)&vid;
new->seq_num = atomic_inc_return(&dev->seq_num);
--
1.8.1.2
More information about the sheepdog
mailing list