Kernel support for HAMMER:
authorMatthew Dillon <dillon@dragonflybsd.org>
Mon, 14 Jul 2008 03:09:00 +0000 (03:09 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Mon, 14 Jul 2008 03:09:00 +0000 (03:09 +0000)
* Add another type to the bio->bio_caller_info1 union

* Add two new flags to getblk(), used by the cluster code.

  GETBLK_SZMATCH - Tell getblk() to fail and return NULL if a
  pre-existing buffer's size does not match
  the requested size (this prevents getblk()
  from doing a potentially undesired bwrite()
  sequence).

  GETBLK_NOWAIT - Tell getblk() to use a non-blocking lock.

* pop_bio() now returns the previous BIO (or NULL if there is no previous
  BIO).  This allows HAMMER to chain bio_done()'s

* Fix a bug in cluster_read().  The cluster code's read-ahead at the
  end could go past the caller-specified limit and force a block to
  the wrong block size.

sys/kern/vfs_bio.c
sys/kern/vfs_cluster.c
sys/sys/bio.h
sys/sys/buf.h

index 5435a9c..b418db4 100644 (file)
@@ -12,7 +12,7 @@
  *             John S. Dyson.
  *
  * $FreeBSD: src/sys/kern/vfs_bio.c,v 1.242.2.20 2003/05/28 18:38:10 alc Exp $
- * $DragonFly: src/sys/kern/vfs_bio.c,v 1.111 2008/07/08 03:34:27 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_bio.c,v 1.112 2008/07/14 03:09:00 dillon Exp $
  */
 
 /*
@@ -587,10 +587,14 @@ push_bio(struct bio *bio)
        return(nbio);
 }
 
-void
+/*
+ * Pop a BIO translation layer, returning the previous layer.  The
+ * must have been previously pushed.
+ */
+struct bio *
 pop_bio(struct bio *bio)
 {
-       /* NOP */
+       return(bio->bio_prev);
 }
 
 void
@@ -2465,6 +2469,10 @@ loop:
                 * once the lock has been obtained.
                 */
                if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) {
+                       if (blkflags & GETBLK_NOWAIT) {
+                               crit_exit();
+                               return(NULL);
+                       }
                        int lkflags = LK_EXCLUSIVE | LK_SLEEPFAIL;
                        if (blkflags & GETBLK_PCATCH)
                                lkflags |= LK_PCATCH;
@@ -2489,6 +2497,17 @@ loop:
                        goto loop;
                }
 
+               /*
+                * If SZMATCH any pre-existing buffer must be of the requested
+                * size or NULL is returned.  The caller absolutely does not
+                * want getblk() to bwrite() the buffer on a size mismatch.
+                */
+               if ((blkflags & GETBLK_SZMATCH) && size != bp->b_bcount) {
+                       BUF_UNLOCK(bp);
+                       crit_exit();
+                       return(NULL);
+               }
+
                /*
                 * All vnode-based buffers must be backed by a VM object.
                 */
index 2782801..b1f43c4 100644 (file)
@@ -34,7 +34,7 @@
  *
  *     @(#)vfs_cluster.c       8.7 (Berkeley) 2/13/94
  * $FreeBSD: src/sys/kern/vfs_cluster.c,v 1.92.2.9 2001/11/18 07:10:59 dillon Exp $
- * $DragonFly: src/sys/kern/vfs_cluster.c,v 1.39 2008/06/20 05:40:04 dillon Exp $
+ * $DragonFly: src/sys/kern/vfs_cluster.c,v 1.40 2008/07/14 03:09:00 dillon Exp $
  */
 
 #include "opt_debug_cluster.h"
@@ -244,13 +244,10 @@ single_block_read:
                int burstbytes;
                int tmp_error;
 
-               if ((rbp = findblk(vp, loffset)) != NULL) {
-                       if (BUF_LOCK(rbp, LK_EXCLUSIVE | LK_NOWAIT)) {
-                               goto no_read_ahead;
-                       }
-                       BUF_UNLOCK(rbp);
-               }
-               rbp = getblk(vp, loffset, blksize, 0, 0);
+               rbp = getblk(vp, loffset, blksize,
+                            GETBLK_SZMATCH|GETBLK_NOWAIT, 0);
+               if (rbp == NULL)
+                       goto no_read_ahead;
                if ((rbp->b_flags & B_CACHE)) {
                        bqrelse(rbp);
                        goto no_read_ahead;
@@ -380,24 +377,18 @@ cluster_rbuild(struct vnode *vp, off_t filesize, off_t loffset,
                         * would block in the lock.  The same checks have to
                         * be made again after we officially get the buffer.
                         */
-                       if ((tbp = findblk(vp, loffset + i * blksize)) != NULL) {
-                               if (BUF_LOCK(tbp, LK_EXCLUSIVE | LK_NOWAIT))
-                                       break;
-                               BUF_UNLOCK(tbp);
-
-                               for (j = 0; j < tbp->b_xio.xio_npages; j++) {
-                                       if (tbp->b_xio.xio_pages[j]->valid)
-                                               break;
-                               }
-                               
-                               if (j != tbp->b_xio.xio_npages)
-                                       break;
-       
-                               if (tbp->b_bcount != blksize)
+                       tbp = getblk(vp, loffset + i * blksize, blksize,
+                                    GETBLK_SZMATCH|GETBLK_NOWAIT, 0);
+                       if (tbp == NULL)
+                               break;
+                       for (j = 0; j < tbp->b_xio.xio_npages; j++) {
+                               if (tbp->b_xio.xio_pages[j]->valid)
                                        break;
                        }
-
-                       tbp = getblk(vp, loffset + i * blksize, blksize, 0, 0);
+                       if (j != tbp->b_xio.xio_npages) {
+                               bqrelse(tbp);
+                               break;
+                       }
 
                        /*
                         * Stop scanning if the buffer is fuly valid 
index 876fb81..41f23ab 100644 (file)
@@ -31,7 +31,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $DragonFly: src/sys/sys/bio.h,v 1.5 2006/05/20 02:42:13 dillon Exp $
+ * $DragonFly: src/sys/sys/bio.h,v 1.6 2008/07/14 03:08:58 dillon Exp $
  */
 
 #ifndef _SYS_BIO_H_
@@ -71,6 +71,7 @@ struct bio {
                void    *ptr;
                off_t   offset;
                int     index;
+               u_int32_t uvalue32;
                struct buf *cluster_head;
                struct bio *cluster_parent;
        } bio_caller_info1;
index 61c7cd3..a793514 100644 (file)
@@ -37,7 +37,7 @@
  *
  *     @(#)buf.h       8.9 (Berkeley) 3/30/95
  * $FreeBSD: src/sys/sys/buf.h,v 1.88.2.10 2003/01/25 19:02:23 dillon Exp $
- * $DragonFly: src/sys/sys/buf.h,v 1.50 2008/06/28 23:45:19 dillon Exp $
+ * $DragonFly: src/sys/sys/buf.h,v 1.51 2008/07/14 03:08:58 dillon Exp $
  */
 
 #ifndef _SYS_BUF_H_
@@ -195,9 +195,16 @@ struct buf {
  *
  * GETBLK_BHEAVY - This is a heavy weight buffer, meaning that resolving
  *                writes can require additional buffers.
+ *
+ * GETBLK_SZMATCH- blksize must match pre-existing b_bcount.  getblk() can
+ *                return NULL.
+ *
+ * GETBLK_NOWAIT - Do not use a blocking lock.  getblk() can return NULL.
  */
 #define GETBLK_PCATCH  0x0001  /* catch signals */
 #define GETBLK_BHEAVY  0x0002  /* heavy weight buffer */
+#define GETBLK_SZMATCH 0x0004  /* pre-existing buffer must match */
+#define GETBLK_NOWAIT  0x0008  /* non-blocking */
 
 /*
  * These flags are kept in b_flags.
@@ -396,7 +403,7 @@ struct buf *getblk (struct vnode *, off_t, int, int, int);
 struct buf *geteblk (int);
 void regetblk(struct buf *bp);
 struct bio *push_bio(struct bio *);
-void pop_bio(struct bio *);
+struct bio *pop_bio(struct bio *);
 int    biowait (struct buf *);
 void   biodone (struct bio *);