Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 29 Apr 2011 21:18:41 +0000 (UTC)
From:      Dag-Erling Smorgrav <des@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r221229 - head/sys/dev/md
Message-ID:  <201104292118.p3TLIf56016065@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: des
Date: Fri Apr 29 21:18:41 2011
New Revision: 221229
URL: http://svn.freebsd.org/changeset/base/221229

Log:
  Implement BIO_DELETE for vnode devices by simply overwriting the deleted
  sectors with all-zeroes.
  
  The zeroes come from a static buffer; null(4) uses a dynamic buffer for
  the same purpose (for /dev/zero).  It might be a good idea to have a
  static, shared, read-only all-zeroes page somewhere in the kernel that
  md(4), null(4) and any other code that needs zeroes could use.
  
  Reviewed by:	kib
  MFC after:	3 weeks

Modified:
  head/sys/dev/md/md.c

Modified: head/sys/dev/md/md.c
==============================================================================
--- head/sys/dev/md/md.c	Fri Apr 29 21:10:45 2011	(r221228)
+++ head/sys/dev/md/md.c	Fri Apr 29 21:18:41 2011	(r221229)
@@ -205,6 +205,9 @@ struct md_s {
 	vm_object_t object;
 };
 
+/* Used for BIO_DELETE on MD_VNODE */
+static u_char zero[PAGE_SIZE];
+
 static struct indir *
 new_indir(u_int shift)
 {
@@ -514,10 +517,12 @@ mdstart_vnode(struct md_s *sc, struct bi
 	struct mount *mp;
 	struct vnode *vp;
 	struct thread *td;
+	off_t end, zerosize;
 
 	switch (bp->bio_cmd) {
 	case BIO_READ:
 	case BIO_WRITE:
+	case BIO_DELETE:
 	case BIO_FLUSH:
 		break;
 	default:
@@ -548,6 +553,43 @@ mdstart_vnode(struct md_s *sc, struct bi
 
 	bzero(&auio, sizeof(auio));
 
+	/*
+	 * Special case for BIO_DELETE.  On the surface, this is very
+	 * similar to BIO_WRITE, except that we write from our own
+	 * fixed-length buffer, so we have to loop.  The net result is
+	 * that the two cases end up having very little in common.
+	 */
+	if (bp->bio_cmd == BIO_DELETE) {
+		zerosize = sizeof(zero) - (sizeof(zero) % sc->sectorsize);
+		auio.uio_iov = &aiov;
+		auio.uio_iovcnt = 1;
+		auio.uio_offset = (vm_ooffset_t)bp->bio_offset;
+		auio.uio_segflg = UIO_SYSSPACE;
+		auio.uio_rw = UIO_WRITE;
+		auio.uio_td = td;
+		end = bp->bio_offset + bp->bio_length;
+		vfslocked = VFS_LOCK_GIANT(vp->v_mount);
+		(void) vn_start_write(vp, &mp, V_WAIT);
+		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
+		error = 0;
+		while (auio.uio_offset < end) {
+			aiov.iov_base = zero;
+			aiov.iov_len = end - auio.uio_offset;
+			if (aiov.iov_len > zerosize)
+				aiov.iov_len = zerosize;
+			auio.uio_resid = aiov.iov_len;
+			error = VOP_WRITE(vp, &auio,
+			    sc->flags & MD_ASYNC ? 0 : IO_SYNC, sc->cred);
+			if (error != 0)
+				break;
+		}
+		VOP_UNLOCK(vp, 0);
+		vn_finished_write(mp);
+		bp->bio_resid = end - auio.uio_offset;
+		VFS_UNLOCK_GIANT(vfslocked);
+		return (error);
+	}
+
 	aiov.iov_base = bp->bio_data;
 	aiov.iov_len = bp->bio_length;
 	auio.uio_iov = &aiov;



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