Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Oct 2013 06:44:55 +0000 (UTC)
From:      Alexander Motin <mav@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r256830 - head/sys/kern
Message-ID:  <201310210644.r9L6itBR085432@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mav
Date: Mon Oct 21 06:44:55 2013
New Revision: 256830
URL: http://svnweb.freebsd.org/changeset/base/256830

Log:
  MFprojects/camlock r256619:
  Restore BIO_UNMAPPED and BIO_TRANSIENT_MAPPING in biodonne() when unmapping
  temporary mapped buffer.  That fixes double unmap if biodone() called twice
  for the same BIO (but with different done methods).
  
  Move mapping removal before calling bio_done() method.  I believe that it is
  very wrong to do anything to BIO after reporting completion.  kib@ thinks
  it was done for some forgotten now case when bio_done() method needed mapped
  buffer. But 1) if BIO was sent as unmapped, then IMO done() should be called
  in the same way; 2) IMO there is no guatantee that buffer will be mapped at
  this point at all, for example, if all underlying stack supports unmapped
  I/O, so bio_done() handler can not expect that.

Modified:
  head/sys/kern/vfs_bio.c

Modified: head/sys/kern/vfs_bio.c
==============================================================================
--- head/sys/kern/vfs_bio.c	Mon Oct 21 06:31:56 2013	(r256829)
+++ head/sys/kern/vfs_bio.c	Mon Oct 21 06:44:55 2013	(r256830)
@@ -3557,15 +3557,15 @@ biodone(struct bio *bp)
 	struct mtx *mtxp;
 	void (*done)(struct bio *);
 	vm_offset_t start, end;
-	int transient;
 
 	if ((bp->bio_flags & BIO_TRANSIENT_MAPPING) != 0) {
+		bp->bio_flags &= ~BIO_TRANSIENT_MAPPING;
+		bp->bio_flags |= BIO_UNMAPPED;
 		start = trunc_page((vm_offset_t)bp->bio_data);
 		end = round_page((vm_offset_t)bp->bio_data + bp->bio_length);
-		transient = 1;
-	} else {
-		transient = 0;
-		start = end = 0;
+		pmap_qremove(start, OFF_TO_IDX(end - start));
+		vmem_free(transient_arena, start, end - start);
+		atomic_add_int(&inflight_transient_maps, -1);
 	}
 	done = bp->bio_done;
 	if (done == NULL) {
@@ -3578,11 +3578,6 @@ biodone(struct bio *bp)
 		bp->bio_flags |= BIO_DONE;
 		done(bp);
 	}
-	if (transient) {
-		pmap_qremove(start, OFF_TO_IDX(end - start));
-		vmem_free(transient_arena, start, end - start);
-		atomic_add_int(&inflight_transient_maps, -1);
-	}
 }
 
 /*



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