Module Name:    src
Committed By:   hannken
Date:           Thu Oct 15 10:05:48 UTC 2009

Modified Files:
        src/sys/ufs/ffs: ffs_snapshot.c

Log Message:
No longer abuse TAILQ internal data.


To generate a diff of this commit:
cvs rdiff -u -r1.96 -r1.97 src/sys/ufs/ffs/ffs_snapshot.c

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

Modified files:

Index: src/sys/ufs/ffs/ffs_snapshot.c
diff -u src/sys/ufs/ffs/ffs_snapshot.c:1.96 src/sys/ufs/ffs/ffs_snapshot.c:1.97
--- src/sys/ufs/ffs/ffs_snapshot.c:1.96	Tue Oct 13 12:38:14 2009
+++ src/sys/ufs/ffs/ffs_snapshot.c	Thu Oct 15 10:05:48 2009
@@ -1,4 +1,4 @@
-/*	$NetBSD: ffs_snapshot.c,v 1.96 2009/10/13 12:38:14 hannken Exp $	*/
+/*	$NetBSD: ffs_snapshot.c,v 1.97 2009/10/15 10:05:48 hannken Exp $	*/
 
 /*
  * Copyright 2000 Marshall Kirk McKusick. All Rights Reserved.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.96 2009/10/13 12:38:14 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ffs_snapshot.c,v 1.97 2009/10/15 10:05:48 hannken Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_ffs.h"
@@ -76,6 +76,14 @@
 
 #include <uvm/uvm.h>
 
+struct snap_info {
+	kmutex_t si_lock;			/* Lock this snapinfo */
+	kmutex_t si_snaplock;			/* Snapshot vnode common lock */
+	TAILQ_HEAD(inodelst, inode) si_snapshots; /* List of active snapshots */
+	daddr_t *si_snapblklist;		/* Snapshot block hints list */
+	uint32_t si_gen;			/* Incremented on change */
+};
+
 #if !defined(FFS_NO_SNAPSHOT)
 typedef int (*acctfunc_t)
     (struct vnode *, void *, int, int, struct fs *, daddr_t, int);
@@ -107,6 +115,7 @@
 static int syncsnap(struct vnode *);
 static int wrsnapblk(struct vnode *, void *, daddr_t);
 
+static inline bool is_active_snapshot(struct snap_info *, struct inode *);
 static inline daddr_t db_get(struct inode *, int);
 static inline void db_assign(struct inode *, int, daddr_t);
 static inline daddr_t ib_get(struct inode *, int);
@@ -114,14 +123,6 @@
 static inline daddr_t idb_get(struct inode *, void *, int);
 static inline void idb_assign(struct inode *, void *, int, daddr_t);
 
-struct snap_info {
-	kmutex_t si_lock;			/* Lock this snapinfo */
-	kmutex_t si_snaplock;			/* Snapshot vnode common lock */
-	TAILQ_HEAD(inodelst, inode) si_snapshots; /* List of active snapshots */
-	daddr_t *si_snapblklist;		/* Snapshot block hints list */
-	uint32_t si_gen;			/* Incremented on change */
-};
-
 #ifdef DEBUG
 static int snapdebug = 0;
 #endif
@@ -277,7 +278,7 @@
 	fs->fs_snapinum[snaploc] = ip->i_number;
 
 	mutex_enter(&si->si_lock);
-	if (ip->i_nextsnap.tqe_prev != 0)
+	if (is_active_snapshot(si, ip))
 		panic("ffs_snapshot: %"PRIu64" already on list", ip->i_number);
 	TAILQ_INSERT_TAIL(&si->si_snapshots, ip, i_nextsnap);
 	if (TAILQ_FIRST(&si->si_snapshots) == ip) {
@@ -1318,10 +1319,9 @@
 	 *
 	 * Clear copy-on-write flag if last snapshot.
 	 */
-	if (ip->i_nextsnap.tqe_prev != 0) {
-		mutex_enter(&si->si_lock);
+	mutex_enter(&si->si_lock);
+	if (is_active_snapshot(si, ip)) {
 		TAILQ_REMOVE(&si->si_snapshots, ip, i_nextsnap);
-		ip->i_nextsnap.tqe_prev = 0;
 		if (TAILQ_FIRST(&si->si_snapshots) != 0) {
 			/* Roll back the list of preallocated blocks. */
 			xp = TAILQ_LAST(&si->si_snapshots, inodelst);
@@ -1338,7 +1338,8 @@
 			free(ip->i_snapblklist, M_UFSMNT);
 			ip->i_snapblklist = NULL;
 		}
-	}
+	} else
+		mutex_exit(&si->si_lock);
 	/*
 	 * Clear all BLK_NOCOPY fields. Pass any block claims to other
 	 * snapshots that want them (see ffs_snapblkfree below).
@@ -1678,9 +1679,9 @@
 		/*
 		 * Link it onto the active snapshot list.
 		 */
-		if (ip->i_nextsnap.tqe_prev != 0)
-			panic("ffs_snapshot_mount: %llu already on list",
-			    (unsigned long long)ip->i_number);
+		if (is_active_snapshot(si, ip))
+			panic("ffs_snapshot_mount: %"PRIu64" already on list",
+			    ip->i_number);
 		else
 			TAILQ_INSERT_TAIL(&si->si_snapshots, ip, i_nextsnap);
 		vp->v_vflag |= VV_SYSTEM;
@@ -1720,7 +1721,6 @@
 	while ((xp = TAILQ_FIRST(&si->si_snapshots)) != 0) {
 		vp = ITOV(xp);
 		TAILQ_REMOVE(&si->si_snapshots, xp, i_nextsnap);
-		xp->i_nextsnap.tqe_prev = 0;
 		if (xp->i_snapblklist == si->si_snapblklist)
 			si->si_snapblklist = NULL;
 		free(xp->i_snapblklist, M_UFSMNT);
@@ -2121,6 +2121,23 @@
 }
 
 /*
+ * Check if this inode is present on the active snapshot list.
+ * Must be called with snapinfo locked.
+ */
+static inline bool
+is_active_snapshot(struct snap_info *si, struct inode *ip)
+{
+	struct inode *xp;
+
+	KASSERT(mutex_owned(&si->si_lock));
+
+	TAILQ_FOREACH(xp, &si->si_snapshots, i_nextsnap)
+		if (xp == ip)
+			return true;
+	return false;
+}
+
+/*
  * Get/Put direct block from inode or buffer containing disk addresses. Take
  * care for fs type (UFS1/UFS2) and byte swapping. These functions should go
  * into a global include.

Reply via email to