svn commit: r221229 - head/sys/dev/md
Dag-Erling Smorgrav
des at FreeBSD.org
Fri Apr 29 21:18:41 UTC 2011
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;
More information about the svn-src-all
mailing list