Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 14 Jun 2000 22:29:32 +0200
From:      Poul-Henning Kamp <phk@freebsd.org>
To:        current@freebsd.org
Subject:   HEADSUP: bioops patch.
Message-ID:  <18317.961014572@critter.freebsd.dk>

next in thread | raw e-mail | index | archive | help

This patch virtualizes & untangles the bioops operations vector.

Background:

The bioops operation vector is a list of OO-like operations which can
be performed on struct buf.  They are used by the softupdates code
to handle dependencies.

Ideally struct buf should have had a real OO like operations vector
like vnodes have it, and struct bioops is the first step towards that.

One of the reasons we should have OO-like struct buf, is that as
long as bwrite(bp) "knows" that the buffer is backed by a disk
device, we cannot use the UFS layer on top of a storage manager
which isn't based on disk-devices:  When UFS modifies a directory
inode, it will call bwrite(bp) on the buffer with the data.  This
would not work if the backing were based on malloc(9) or anonymous
swap-backed VM objects for instance.

In other words: this is the main reason why we don't have a decent
tmpfs in FreeBSD.

Instead of just assuming that it works on a disk, bwrite(bp) should
do a "bp->b_ops->bwrite(bp)" so that each buffer could have its own
private idea of how to write itself, depending on what backing it has.

So in order to move bioops closer to become a bp->b_ops, this patch
takes two entries out of bioops:  the "sync" and the "fsync" items
and virtualizes the rest of the elements a bit.

The "sync" item is called only from the syncer, and is a call to the
softupdates code to do what it needs to do for periodic syncing.

The real way of doing that would be to have an event-handler for this
since other code could need to be part of the sync trafic, raid5
private parity caches could be one example.  I have not done this
yet, since currently softupdates is the only client.

The fsync item really doesn't belong in the fsync system call, it
belongs in ffs_fsync, and has been moved there.

To give the right behaviour when SOFTUPDATES is not compiled in,
stubs for both of these functions have been added to ffs_softdep_stub.c

Finally all the checks to see if the bioops vector is populated
has been centralized in in-line functions in <sys/buf.h> thereby
paving the road for the global bioops to become bp->b_ops.

Comments, reviews, tests please

Poul-Henning

Index: contrib/softupdates/ffs_softdep.c
===================================================================
RCS file: /home/ncvs/src/sys/contrib/softupdates/ffs_softdep.c,v
retrieving revision 1.64
diff -u -r1.64 ffs_softdep.c
--- contrib/softupdates/ffs_softdep.c	2000/05/26 02:01:59	1.64
+++ contrib/softupdates/ffs_softdep.c	2000/06/14 19:26:46
@@ -222,8 +222,6 @@
 	softdep_disk_io_initiation,		/* io_start */
 	softdep_disk_write_complete,		/* io_complete */
 	softdep_deallocate_dependencies,	/* io_deallocate */
-	softdep_fsync,				/* io_fsync */
-	softdep_process_worklist,		/* io_sync */
 	softdep_move_dependencies,		/* io_movedeps */
 	softdep_count_dependencies,		/* io_countdeps */
 };
Index: kern/vfs_bio.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_bio.c,v
retrieving revision 1.258
diff -u -r1.258 vfs_bio.c
--- kern/vfs_bio.c	2000/05/26 02:04:39	1.258
+++ kern/vfs_bio.c	2000/06/14 19:00:56
@@ -616,8 +616,8 @@
 		newbp->b_flags &= ~B_INVAL;
 
 		/* move over the dependencies */
-		if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_movedeps)
-			(*bioops.io_movedeps)(bp, newbp);
+		if (LIST_FIRST(&bp->b_dep) != NULL)
+			buf_movedeps(bp, newbp);
 
 		/*
 		 * Initiate write on the copy, release the original to
@@ -673,10 +673,10 @@
 	/*
 	 * Process dependencies then return any unfinished ones.
 	 */
-	if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_complete)
-		(*bioops.io_complete)(bp);
-	if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_movedeps)
-		(*bioops.io_movedeps)(bp, origbp);
+	if (LIST_FIRST(&bp->b_dep) != NULL)
+		buf_complete(bp);
+	if (LIST_FIRST(&bp->b_dep) != NULL)
+		buf_movedeps(bp, origbp);
 	/*
 	 * Clear the BX_BKGRDINPROG flag in the original buffer
 	 * and awaken it if it is waiting for the write to complete.
@@ -939,8 +939,8 @@
 		 * cache the buffer.
 		 */
 		bp->b_flags |= B_INVAL;
-		if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
-			(*bioops.io_deallocate)(bp);
+		if (LIST_FIRST(&bp->b_dep) != NULL)
+			buf_deallocate(bp);
 		if (bp->b_flags & B_DELWRI) {
 			--numdirtybuffers;
 			numdirtywakeup();
@@ -1570,8 +1570,8 @@
 			crfree(bp->b_wcred);
 			bp->b_wcred = NOCRED;
 		}
-		if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_deallocate)
-			(*bioops.io_deallocate)(bp);
+		if (LIST_FIRST(&bp->b_dep) != NULL)
+			buf_deallocate(bp);
 		if (bp->b_xflags & BX_BKGRDINPROG)
 			panic("losing buffer 3");
 		LIST_REMOVE(bp, b_hash);
@@ -1848,9 +1848,8 @@
 				break;
 			}
 			if (LIST_FIRST(&bp->b_dep) != NULL &&
-			    bioops.io_countdeps &&
 			    (bp->b_flags & B_DEFERRED) == 0 &&
-			    (*bioops.io_countdeps)(bp, 0)) {
+			    buf_countdeps(bp, 0)) {
 				TAILQ_REMOVE(&bufqueues[QUEUE_DIRTY],
 				    bp, b_freelist);
 				TAILQ_INSERT_TAIL(&bufqueues[QUEUE_DIRTY],
@@ -2664,8 +2663,8 @@
 		splx(s);
 		return;
 	}
-	if (LIST_FIRST(&bp->b_dep) != NULL && bioops.io_complete)
-		(*bioops.io_complete)(bp);
+	if (LIST_FIRST(&bp->b_dep) != NULL)
+		buf_complete(bp);
 
 	if (bp->b_flags & B_VMIO) {
 		int i, resid;
Index: kern/vfs_cluster.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_cluster.c,v
retrieving revision 1.98
diff -u -r1.98 vfs_cluster.c
--- kern/vfs_cluster.c	2000/05/05 09:58:25	1.98
+++ kern/vfs_cluster.c	2000/06/14 19:01:13
@@ -805,9 +805,8 @@
 				splx(s);
 			} /* end of code for non-first buffers only */
 			/* check for latent dependencies to be handled */
-			if ((LIST_FIRST(&tbp->b_dep)) != NULL &&
-			    bioops.io_start)
-				(*bioops.io_start)(tbp);
+			if ((LIST_FIRST(&tbp->b_dep)) != NULL)
+				buf_start(tbp);
 			/*
 			 * If the IO is via the VM then we do some
 			 * special VM hackery. (yuck)
Index: kern/vfs_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_subr.c,v
retrieving revision 1.257
diff -u -r1.257 vfs_subr.c
--- kern/vfs_subr.c	2000/05/26 02:04:39	1.257
+++ kern/vfs_subr.c	2000/06/14 19:56:33
@@ -1029,8 +1029,7 @@
 		/*
 		 * Do soft update processing.
 		 */
-		if (bioops.io_sync)
-			(*bioops.io_sync)(NULL);
+		softdep_process_worklist(NULL);
 
 		/*
 		 * The variable rushjob allows the kernel to speed up the
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.153
diff -u -r1.153 vfs_syscalls.c
--- kern/vfs_syscalls.c	2000/05/05 09:58:27	1.153
+++ kern/vfs_syscalls.c	2000/06/14 19:38:24
@@ -2545,10 +2545,7 @@
 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
 	if (vp->v_object)
 		vm_object_page_clean(vp->v_object, 0, 0, 0);
-	if ((error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p)) == 0 &&
-	    vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP) &&
-	    bioops.io_fsync)
-		error = (*bioops.io_fsync)(vp);
+	error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p);
 	VOP_UNLOCK(vp, 0, p);
 	return (error);
 }
Index: miscfs/devfs/devfs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/devfs/devfs_vnops.c,v
retrieving revision 1.96
diff -u -r1.96 devfs_vnops.c
--- miscfs/devfs/devfs_vnops.c	2000/05/05 09:58:29	1.96
+++ miscfs/devfs/devfs_vnops.c	2000/06/14 19:02:35
@@ -1570,9 +1570,8 @@
 		return error;
 
 
-	if ((bp->b_iocmd == BIO_WRITE) &&
-		(LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
-		(*bioops.io_start)(bp);
+	if ((bp->b_iocmd == BIO_WRITE) && (LIST_FIRST(&bp->b_dep)) != NULL)
+		buf_start(bp);
 	switch (vp->v_type) {
 	case VCHR:
 		(*vp->v_rdev->si_devsw->d_strategy)(&bp->b_io);
Index: miscfs/specfs/spec_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/specfs/spec_vnops.c,v
retrieving revision 1.138
diff -u -r1.138 spec_vnops.c
--- miscfs/specfs/spec_vnops.c	2000/06/12 10:20:18	1.138
+++ miscfs/specfs/spec_vnops.c	2000/06/14 19:02:49
@@ -417,9 +417,8 @@
 	struct mount *mp;
 
 	bp = ap->a_bp;
-	if ((bp->b_iocmd == BIO_WRITE) &&
-		(LIST_FIRST(&bp->b_dep)) != NULL && bioops.io_start)
-		(*bioops.io_start)(bp);
+	if ((bp->b_iocmd == BIO_WRITE) && (LIST_FIRST(&bp->b_dep)) != NULL)
+		buf_start(bp);
 
 	/*
 	 * Collect statistics on synchronous and asynchronous read
Index: sys/buf.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/buf.h,v
retrieving revision 1.103
diff -u -r1.103 buf.h
--- sys/buf.h	2000/05/26 02:06:53	1.103
+++ sys/buf.h	2000/06/14 19:26:59
@@ -64,8 +64,6 @@
 	void	(*io_start) __P((struct buf *));
 	void	(*io_complete) __P((struct buf *));
 	void	(*io_deallocate) __P((struct buf *));
-	int	(*io_fsync) __P((struct vnode *));
-	int	(*io_sync) __P((struct mount *));
 	void	(*io_movedeps) __P((struct buf *, struct buf *));
 	int	(*io_countdeps) __P((struct buf *, int));
 } bioops;
@@ -405,6 +403,43 @@
 
 #define BUF_WRITE(bp)		VOP_BWRITE((bp)->b_vp, (bp))
 #define BUF_STRATEGY(bp)	VOP_STRATEGY((bp)->b_vp, (bp))
+
+static __inline void
+buf_start(struct buf *bp)
+{
+	if (bioops.io_start)
+		(*bioops.io_start)(bp);
+}
+
+static __inline void
+buf_complete(struct buf *bp)
+{
+	if (bioops.io_complete)
+		(*bioops.io_complete)(bp);
+}
+
+static __inline void
+buf_deallocate(struct buf *bp)
+{
+	if (bioops.io_deallocate)
+		(*bioops.io_deallocate)(bp);
+}
+
+static __inline void
+buf_movedeps(struct buf *bp, struct buf *bp2)
+{
+	if (bioops.io_movedeps)
+		(*bioops.io_movedeps)(bp, bp2);
+}
+
+static __inline int
+buf_countdeps(struct buf *bp, int i)
+{
+	if (bioops.io_countdeps)
+		return ((*bioops.io_countdeps)(bp, i));
+	else
+		return (0);
+}
 
 #endif /* _KERNEL */
 
Index: sys/mount.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/mount.h,v
retrieving revision 1.91
diff -u -r1.91 mount.h
--- sys/mount.h	2000/05/26 02:06:55	1.91
+++ sys/mount.h	2000/06/14 19:58:22
@@ -447,6 +447,7 @@
 int	vfs_stdextattrctl __P((struct mount *mp, int cmd, const char *attrname,
 		caddr_t arg, struct proc *p));
 
+void	softdep_process_worklist __P((struct mount *));
 #else /* !_KERNEL */
 
 #include <sys/cdefs.h>
Index: ufs/ffs/ffs_softdep_stub.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_softdep_stub.c,v
retrieving revision 1.8
diff -u -r1.8 ffs_softdep_stub.c
--- ufs/ffs/ffs_softdep_stub.c	2000/04/19 14:58:25	1.8
+++ ufs/ffs/ffs_softdep_stub.c	2000/06/14 19:33:11
@@ -254,4 +254,20 @@
 
 	return (0);
 }
+
+int
+softdep_fsync(vp)
+	struct vnode *vp;	/* the "in_core" copy of the inode */
+{
+
+	return (0);
+}
+
+int
+softdep_process_worklist(matchmnt)
+	struct mount *matchmnt;
+{
+	return (0);
+}
+
 #endif	/* SOFTUPDATES not configured in */
Index: ufs/ffs/ffs_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/ufs/ffs/ffs_vnops.c,v
retrieving revision 1.66
diff -u -r1.66 ffs_vnops.c
--- ufs/ffs/ffs_vnops.c	2000/05/05 09:59:05	1.66
+++ ufs/ffs/ffs_vnops.c	2000/06/14 19:38:13
@@ -175,7 +175,7 @@
 			continue;
 		if (!wait && LIST_FIRST(&bp->b_dep) != NULL &&
 		    (bp->b_flags & B_DEFERRED) == 0 &&
-		    bioops.io_countdeps && (*bioops.io_countdeps)(bp, 0)) {
+		    buf_countdeps(bp, 0)) {
 			bp->b_flags |= B_DEFERRED;
 			continue;
 		}
@@ -278,5 +278,8 @@
 		}
 	}
 	splx(s);
-	return (UFS_UPDATE(vp, wait));
+	error = UFS_UPDATE(vp, wait);
+	if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
+		error = softdep_fsync(vp);
+	return (error);
 }

--
Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
phk@FreeBSD.ORG         | TCP/IP since RFC 956
FreeBSD coreteam member | BSD since 4.3-tahoe
Never attribute to malice what can adequately be explained by incompetence.


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?18317.961014572>