Module Name:    src
Committed By:   pooka
Date:           Fri Dec 11 21:20:52 UTC 2009

Modified Files:
        src/lib/libukfs: Makefile ukfs.c

Log Message:
Use range locking (fnctl(F_SETLK)) instead of file locking (flock()).
This allows to mount multiple (non-overlapping) partitions from the
same disk image.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/lib/libukfs/Makefile
cvs rdiff -u -r1.44 -r1.45 src/lib/libukfs/ukfs.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libukfs/Makefile
diff -u src/lib/libukfs/Makefile:1.3 src/lib/libukfs/Makefile:1.4
--- src/lib/libukfs/Makefile:1.3	Wed Oct  7 20:51:00 2009
+++ src/lib/libukfs/Makefile	Fri Dec 11 21:20:52 2009
@@ -1,9 +1,9 @@
-#	$NetBSD: Makefile,v 1.3 2009/10/07 20:51:00 pooka Exp $
+#	$NetBSD: Makefile,v 1.4 2009/12/11 21:20:52 pooka Exp $
 #
 
 LIB=		ukfs
-LIBDPLIBS+=	rump	${.CURDIR}/../librump		\
-		rumpvfs	${.CURDIR}/../librumpvfs
+#LIBDPLIBS+=	rump	${.CURDIR}/../librump		\
+#		rumpvfs	${.CURDIR}/../librumpvfs
 CPPFLAGS+=	-I${.CURDIR}
 
 INCS=		ukfs.h
@@ -11,5 +11,6 @@
 
 SRCS=		ukfs.c ukfs_disklabel.c
 MAN=		ukfs.3
+DBG=		-g
 
 .include <bsd.lib.mk>

Index: src/lib/libukfs/ukfs.c
diff -u src/lib/libukfs/ukfs.c:1.44 src/lib/libukfs/ukfs.c:1.45
--- src/lib/libukfs/ukfs.c:1.44	Fri Dec 11 16:47:33 2009
+++ src/lib/libukfs/ukfs.c	Fri Dec 11 21:20:52 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ukfs.c,v 1.44 2009/12/11 16:47:33 pooka Exp $	*/
+/*	$NetBSD: ukfs.c,v 1.45 2009/12/11 21:20:52 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
@@ -79,6 +79,7 @@
 	int ukfs_devfd;
 	char *ukfs_devpath;
 	char *ukfs_mountpath;
+	struct ukfs_part *ukfs_part;
 };
 
 static int builddirs(const char *, mode_t,
@@ -180,6 +181,8 @@
 struct ukfs_part *ukfs_part_none = &ukfs__part_none;
 struct ukfs_part *ukfs_part_na = &ukfs__part_na;
 
+#define PART2LOCKSIZE(len) ((len) == RUMP_ETFS_SIZE_ENDOFF ? 0 : (len))
+
 int
 _ukfs_init(int version)
 {
@@ -387,6 +390,20 @@
 	return rv;
 }
 
+static void
+unlockdev(int fd, struct ukfs_part *part)
+{
+	struct flock flarg;
+
+	memset(&flarg, 0, sizeof(flarg));
+	flarg.l_type = F_UNLCK;
+	flarg.l_whence = SEEK_SET;
+	flarg.l_start = part->part_devoff;
+	flarg.l_len = PART2LOCKSIZE(part->part_devsize);
+	if (fcntl(fd, F_SETLK, &flarg) == -1)
+		warn("ukfs: cannot unlock device file");
+}
+
 /*
  * Open the disk file and flock it.  Also, if we are operation on
  * an embedded partition, find the partition offset and size from
@@ -395,12 +412,12 @@
  * We hard-fail only in two cases:
  *  1) we failed to get the partition info out (don't know what offset
  *     to mount from)
- *  2) we failed to flock the source device (i.e. flock() fails,
+ *  2) we failed to flock the source device (i.e. fcntl() fails,
  *     not e.g. open() before it)
  *
  * Otherwise we let the code proceed to mount and let the file system
  * throw the proper error.  The only questionable bit is that if we
- * soft-fail before flock() and mount does succeed...
+ * soft-fail before flock and mount does succeed...
  *
  * Returns: -1 error (errno reports error code)
  *           0 success
@@ -435,10 +452,25 @@
 	 * We also need to close the device for fairly obvious reasons.
 	 */
 	if (!S_ISBLK(sb.st_mode)) {
-		if (flock(devfd, LOCK_NB | (rdonly ? LOCK_SH:LOCK_EX)) == -1) {
-			warnx("ukfs_mount: cannot get %s lock on "
-			    "device", rdonly ? "shared" : "exclusive");
-			rv = errno;
+		struct flock flarg;
+
+		memset(&flarg, 0, sizeof(flarg));
+		flarg.l_type = rdonly ? F_RDLCK : F_WRLCK;
+		flarg.l_whence = SEEK_SET;
+		flarg.l_start = part->part_devoff;
+		flarg.l_len = PART2LOCKSIZE(part->part_devsize);
+		if (fcntl(devfd, F_SETLK, &flarg) == -1) {
+			pid_t holder;
+			int sverrno;
+
+			sverrno = errno;
+			if (fcntl(devfd, F_GETLK, &flarg) != 1)
+				holder = flarg.l_pid;
+			else
+				holder = -1;
+			warnx("ukfs_mount: cannot lock device.  held by pid %d",
+			    holder);
+			rv = sverrno;
 			goto out;
 		}
 	} else {
@@ -518,10 +550,10 @@
 	fs->ukfs_cdir = ukfs_getrvp(fs);
 	pthread_spin_init(&fs->ukfs_spin, PTHREAD_PROCESS_SHARED);
 	fs->ukfs_devfd = devfd;
+	fs->ukfs_part = part;
 	assert(rv == 0);
 
  out:
-	ukfs_part_release(part);
 	if (rv) {
 		if (fs) {
 			if (fs->ukfs_rvp)
@@ -534,9 +566,10 @@
 		if (regged)
 			rump_pub_etfs_remove(devpath);
 		if (devfd != -1) {
-			flock(devfd, LOCK_UN);
+			unlockdev(fs->ukfs_devfd, fs->ukfs_part);
 			close(devfd);
 		}
+		ukfs_part_release(part);
 		errno = rv;
 	}
 
@@ -588,6 +621,7 @@
 		rump_pub_lwp_release(rump_pub_lwp_curlwp());
 	}
 
+	ukfs_part_release(fs->ukfs_part);
 	if (fs->ukfs_devpath) {
 		rump_pub_etfs_remove(fs->ukfs_devpath);
 		free(fs->ukfs_devpath);
@@ -596,7 +630,7 @@
 
 	pthread_spin_destroy(&fs->ukfs_spin);
 	if (fs->ukfs_devfd != -1) {
-		flock(fs->ukfs_devfd, LOCK_UN);
+		unlockdev(fs->ukfs_devfd, fs->ukfs_part);
 		close(fs->ukfs_devfd);
 	}
 	free(fs);

Reply via email to