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);