[sheepdog] [PATCH 1/5] farm: add concurrent access support to the same object

Liu Yuan namei.unix at gmail.com
Fri Jun 1 11:31:33 CEST 2012


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


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

diff --git a/sheep/farm/farm.c b/sheep/farm/farm.c
index cbfe99d..12a7d1a 100644
--- a/sheep/farm/farm.c
+++ b/sheep/farm/farm.c
@@ -109,6 +109,7 @@ static int farm_write(uint64_t oid, struct siocb *iocb, int create)
 	int flags = def_open_flags, fd, ret = SD_RES_SUCCESS;
 	char path[PATH_MAX];
 	ssize_t size;
+	struct flock fl;
 
 	if (iocb->epoch < sys_epoch()) {
 		dprintf("%"PRIu32" sys %"PRIu32"\n", iocb->epoch, sys_epoch());
@@ -125,6 +126,18 @@ static int farm_write(uint64_t oid, struct siocb *iocb, int create)
 	if (fd < 0)
 		return err_to_sderr(oid, errno);
 
+	fl.l_type = F_WRLCK;
+	fl.l_whence = SEEK_SET;
+	/* For create, we lock the whole object */
+	fl.l_start = create ? 0: iocb->offset;
+	fl.l_len = create ? (is_vdi_obj(oid) ? SD_INODE_SIZE : SD_DATA_OBJ_SIZE)
+		   : iocb->length;
+	fl.l_pid = getpid();
+	if (fcntl(fd, F_SETLKW, &fl) < 0) {
+		eprintf("%m\n");
+		ret = SD_RES_EIO;
+		goto out;
+	}
 	if (create && !(iocb->flags & SD_FLAG_CMD_COW)) {
 		ret = prealloc(fd, is_vdi_obj(oid) ?
 			       SD_INODE_SIZE : SD_DATA_OBJ_SIZE);
@@ -132,6 +145,12 @@ static int farm_write(uint64_t oid, struct siocb *iocb, int create)
 			goto out;
 	}
 	size = xpwrite(fd, iocb->buf, iocb->length, iocb->offset);
+	fl.l_type = F_UNLCK;
+	if (fcntl(fd, F_SETLK, &fl) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
 	if (size != iocb->length) {
 		eprintf("%m\n");
 		ret = SD_RES_EIO;
@@ -410,10 +429,13 @@ static int farm_read(uint64_t oid, struct siocb *iocb)
 {
 	int flags = def_open_flags, fd, ret = SD_RES_SUCCESS;
 	uint32_t epoch = sys_epoch();
+	char path[PATH_MAX];
+	ssize_t size;
+	int i;
+	void *buffer;
+	struct flock fl;
 
 	if (iocb->epoch < epoch) {
-		int i;
-		void *buffer;
 
 		buffer = read_working_object(oid, iocb->offset, iocb->length);
 		if (!buffer) {
@@ -424,7 +446,8 @@ static int farm_read(uint64_t oid, struct siocb *iocb)
 			 * in the next epoch we removed it from the local directory.
 			 * in this case, we should try to retrieve object upwards, since.
 			 * when the object is to be removed, it will get written to the
-			 * snapshot at later epoch. */
+			 * snapshot at later epoch.
+			 */
 			for (i = iocb->epoch; i < epoch; i++) {
 				buffer = retrieve_object_from_snap(oid, i);
 				if (buffer)
@@ -437,24 +460,37 @@ static int farm_read(uint64_t oid, struct siocb *iocb)
 		free(buffer);
 
 		return SD_RES_SUCCESS;
-	} else {
-		char path[PATH_MAX];
-		ssize_t size;
+	}
 
-		if (is_vdi_obj(oid))
-			flags &= ~O_DIRECT;
+	if (is_vdi_obj(oid))
+		flags &= ~O_DIRECT;
 
-		sprintf(path, "%s%016"PRIx64, obj_path, oid);
-		fd = open(path, flags);
+	sprintf(path, "%s%016"PRIx64, obj_path, oid);
+	fd = open(path, flags);
 
-		if (fd < 0)
-			return err_to_sderr(oid, errno);
+	if (fd < 0)
+		return err_to_sderr(oid, errno);
 
-		size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
-		if (size != iocb->length) {
-			ret = SD_RES_EIO;
-			goto out;
-		}
+	fl.l_type = F_RDLCK;
+	fl.l_whence = SEEK_SET;
+	fl.l_start = iocb->offset;
+	fl.l_len = iocb->length;
+	fl.l_pid = getpid();
+	if (fcntl(fd, F_SETLKW, &fl) < 0) {
+		eprintf("%m\n");
+		ret = SD_RES_EIO;
+		goto out;
+	}
+	size = xpread(fd, iocb->buf, iocb->length, iocb->offset);
+	fl.l_type = F_UNLCK;
+	if (fcntl(fd, F_SETLK, &fl) < 0) {
+		ret = SD_RES_EIO;
+		eprintf("%m\n");
+		goto out;
+	}
+	if (size != iocb->length) {
+		ret = SD_RES_EIO;
+		goto out;
 	}
 out:
 	close(fd);
-- 
1.7.10.2




More information about the sheepdog mailing list