Module Name:    src
Committed By:   pooka
Date:           Sun Dec 13 20:52:36 UTC 2009

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

Log Message:
Refcount ukfs_part.  Otherwise it's not possible to call ukfs_mount()
several times with only one ukfs_part_probe().


To generate a diff of this commit:
cvs rdiff -u -r1.46 -r1.47 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/ukfs.c
diff -u src/lib/libukfs/ukfs.c:1.46 src/lib/libukfs/ukfs.c:1.47
--- src/lib/libukfs/ukfs.c:1.46	Sat Dec 12 00:46:04 2009
+++ src/lib/libukfs/ukfs.c	Sun Dec 13 20:52:36 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ukfs.c,v 1.46 2009/12/12 00:46:04 pooka Exp $	*/
+/*	$NetBSD: ukfs.c,v 1.47 2009/12/13 20:52:36 pooka Exp $	*/
 
 /*
  * Copyright (c) 2007, 2008, 2009  Antti Kantee.  All Rights Reserved.
@@ -164,6 +164,9 @@
 }
 
 struct ukfs_part {
+	pthread_spinlock_t part_lck;
+	int part_refcount;
+
 	int part_type;
 	char part_labelchar;
 	off_t part_devoff;
@@ -231,7 +234,14 @@
 		errno = ENOMEM;
 		return -1;
 	}
+	if (pthread_spin_init(&part->part_lck, PTHREAD_PROCESS_PRIVATE) == -1) {
+		error = errno;
+		free(part);
+		errno = error;
+		return -1;
+	}
 	part->part_type = UKFS_PART_NONE;
+	part->part_refcount = 1;
 
 	/*
 	 * Check for magic in pathname:
@@ -338,7 +348,7 @@
 		part->part_devsize = val;
 		part->part_type = UKFS_PART_OFFSET;
 	} else {
-		free(part);
+		ukfs_part_release(part);
 		part = ukfs_part_none;
 	}
 
@@ -395,6 +405,9 @@
 {
 	struct flock flarg;
 
+	if (part == ukfs_part_na)
+		return;
+
 	memset(&flarg, 0, sizeof(flarg));
 	flarg.l_type = F_UNLCK;
 	flarg.l_whence = SEEK_SET;
@@ -497,6 +510,9 @@
 	int mounted = 0;
 	int regged = 0;
 
+	pthread_spin_lock(&part->part_lck);
+	part->part_refcount++;
+	pthread_spin_unlock(&part->part_lck);
 	if (part != ukfs_part_na) {
 		if ((rv = process_diskdevice(devpath, part,
 		    mntflags & MNT_RDONLY, &devfd)) != 0)
@@ -621,7 +637,6 @@
 		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);
@@ -633,6 +648,7 @@
 		unlockdev(fs->ukfs_devfd, fs->ukfs_part);
 		close(fs->ukfs_devfd);
 	}
+	ukfs_part_release(fs->ukfs_part);
 	free(fs);
 
 	return 0;
@@ -641,9 +657,17 @@
 void
 ukfs_part_release(struct ukfs_part *part)
 {
+	int release;
 
-	if (part != ukfs_part_none && part != ukfs_part_na)
-		free(part);
+	if (part != ukfs_part_none && part != ukfs_part_na) {
+		pthread_spin_lock(&part->part_lck);
+		release = --part->part_refcount == 0;
+		pthread_spin_unlock(&part->part_lck);
+		if (release) {
+			pthread_spin_destroy(&part->part_lck);
+			free(part);
+		}
+	}
 }
 
 #define STDCALL(ukfs, thecall)						\

Reply via email to