[sheepdog] [PATCH 4/5] farm: add a lock for read/write

Liu Yuan namei.unix at gmail.com
Tue Jun 19 05:55:17 CEST 2012


From: Liu Yuan <tailai.ly at taobao.com>

We observed a race for this same object, which resule an EIO:

Jun 14 16:16:12 queue_request(387) 1
Jun 14 16:16:12 do_local_io(52) 1, ac1a3e00000000 , 1
Jun 14 16:16:12 listen_handler(805) accepted a new connection: 191
Jun 14 16:16:12 client_rx_handler(588) connection from: 10.232.134.8:42092
Jun 14 16:16:12 queue_request(387) 2
Jun 14 16:16:12 do_local_io(52) 2, ac1a3e00000000 , 1
Jun 14 16:16:12 do_io_request(111) failed: 2, ac1a3e00000000 , 1, 3
Jun 14 16:16:12 io_op_done(119) leaving sheepdog cluster

So let's be more denfensive now.

Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
---
 sheep/farm/farm.c |   29 ++++++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/sheep/farm/farm.c b/sheep/farm/farm.c
index 5351e59..bef821c 100644
--- a/sheep/farm/farm.c
+++ b/sheep/farm/farm.c
@@ -14,6 +14,7 @@
 #include <dirent.h>
 #include <pthread.h>
 #include <linux/limits.h>
+#include <sys/file.h>
 
 #include "farm.h"
 #include "sheep_priv.h"
@@ -125,13 +126,29 @@ static int farm_write(uint64_t oid, struct siocb *iocb, int create)
 	if (fd < 0)
 		return err_to_sderr(oid, errno);
 
+	if (flock(fd, LOCK_EX) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
 	if (create && !(iocb->flags & SD_FLAG_CMD_COW)) {
 		ret = prealloc(fd, is_vdi_obj(oid) ?
 			       SD_INODE_SIZE : SD_DATA_OBJ_SIZE);
-		if (ret != SD_RES_SUCCESS)
+		if (ret != SD_RES_SUCCESS) {
+			if (flock(fd, LOCK_UN) < 0) {
+				ret = SD_RES_EIO;
+				eprintf("%m\n");
+				goto out;
+			}
 			goto out;
+		}
 	}
 	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
+	if (flock(fd, LOCK_UN) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
 	if (size != iocb->length) {
 		eprintf("%m\n");
 		ret = SD_RES_EIO;
@@ -451,7 +468,17 @@ static int farm_read(uint64_t oid, struct siocb *iocb)
 	if (fd < 0)
 		return err_to_sderr(oid, errno);
 
+	if (flock(fd, LOCK_SH) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
 	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
+	if (flock(fd, LOCK_UN) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
 	if (size != iocb->length) {
 		ret = SD_RES_EIO;
 		goto out;
-- 
1.7.10.2




More information about the sheepdog mailing list