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;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to