summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjulian <julian@FreeBSD.org>1998-12-15 03:29:52 +0000
committerjulian <julian@FreeBSD.org>1998-12-15 03:29:52 +0000
commitc179278e548f9ebedb0b73893f43d9922092c431 (patch)
tree0d8427d43019117007c0821c800e63a4a8884873
parent062fd6b56789371d98c92baba31dba21b1438462 (diff)
downloadFreeBSD-src-c179278e548f9ebedb0b73893f43d9922092c431.zip
FreeBSD-src-c179278e548f9ebedb0b73893f43d9922092c431.tar.gz
Add comments to code that I was trying to understand.
Hopefully will save others time. Someone who understands this better might check for correctness.
-rw-r--r--sys/ufs/ufs/ufs_readwrite.c112
1 files changed, 107 insertions, 5 deletions
diff --git a/sys/ufs/ufs/ufs_readwrite.c b/sys/ufs/ufs/ufs_readwrite.c
index 2f5b7f3..9200b39 100644
--- a/sys/ufs/ufs/ufs_readwrite.c
+++ b/sys/ufs/ufs/ufs_readwrite.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_readwrite.c 8.11 (Berkeley) 5/8/95
- * $Id: ufs_readwrite.c,v 1.52 1998/09/07 11:50:19 bde Exp $
+ * $Id: ufs_readwrite.c,v 1.53 1998/10/07 13:59:26 luoqi Exp $
*/
#define BLKSIZE(a, b, c) blksize(a, b, c)
@@ -107,17 +107,35 @@ READ(ap)
if (object)
vm_object_reference(object);
#if 1
+ /*
+ * If IO optimisation is turned on,
+ * and we are NOT a VM based IO request,
+ * (i.e. not headed for the buffer cache)
+ * but there IS a vm object associated with it.
+ */
if ((ioflag & IO_VMIO) == 0 && (vfs_ioopt > 1) && object) {
int nread, toread;
+
toread = uio->uio_resid;
if (toread > bytesinfile)
toread = bytesinfile;
if (toread >= PAGE_SIZE) {
+ /*
+ * Then if it's at least a page in size, try
+ * get the data from the object using vm tricks
+ */
error = uioread(toread, uio, object, &nread);
if ((uio->uio_resid == 0) || (error != 0)) {
+ /*
+ * If we finished or there was an error
+ * then finish up.
+ */
if (!(vp->v_mount->mnt_flag & MNT_NOATIME))
ip->i_flag |= IN_ACCESS;
if (object)
+ /*
+ * This I don't understand
+ */
vm_object_vndeallocate(object);
return error;
}
@@ -125,15 +143,29 @@ READ(ap)
}
#endif
+ /*
+ * Ok so we couldn't do it all in one vm trick...
+ * so cycle around trying smaller bites..
+ */
for (error = 0, bp = NULL; uio->uio_resid > 0; bp = NULL) {
if ((bytesinfile = ip->i_size - uio->uio_offset) <= 0)
break;
#if 1
if ((ioflag & IO_VMIO) == 0 && (vfs_ioopt > 1) && object) {
+ /*
+ * Obviously we didn't finish above, but we
+ * didn't get an error either. Try the same trick again.
+ * but this time we are looping.
+ */
int nread, toread;
toread = uio->uio_resid;
if (toread > bytesinfile)
toread = bytesinfile;
+
+ /*
+ * Once again, if there isn't enough for a
+ * whole page, don't try optimising.
+ */
if (toread >= PAGE_SIZE) {
error = uioread(toread, uio, object, &nread);
if ((uio->uio_resid == 0) || (error != 0)) {
@@ -143,6 +175,11 @@ READ(ap)
vm_object_vndeallocate(object);
return error;
}
+ /*
+ * To get here we didnt't finish or err.
+ * If we did get some data,
+ * loop to try another bite.
+ */
if (nread > 0) {
continue;
}
@@ -154,29 +191,68 @@ READ(ap)
nextlbn = lbn + 1;
size = BLKSIZE(fs, ip, lbn);
blkoffset = blkoff(fs, uio->uio_offset);
-
+
+ /*
+ * The amount we want to transfer in this iteration is
+ * one FS block less the amount of the data before
+ * our startpoint (duh!)
+ */
xfersize = fs->fs_bsize - blkoffset;
+
+ /*
+ * But if we actually want less than the block,
+ * or the file doesn't have a whole block more of data,
+ * then use the lesser number.
+ */
if (uio->uio_resid < xfersize)
xfersize = uio->uio_resid;
if (bytesinfile < xfersize)
xfersize = bytesinfile;
if (lblktosize(fs, nextlbn) >= ip->i_size)
+ /*
+ * Don't do readahead if this is the end of the file.
+ */
error = bread(vp, lbn, size, NOCRED, &bp);
else if ((vp->v_mount->mnt_flag & MNT_NOCLUSTERR) == 0)
+ /*
+ * Otherwise if we are allowed to cluster,
+ * grab as much as we can.
+ *
+ * XXX This may not be a win if we are not
+ * doing sequential access.
+ */
error = cluster_read(vp, ip->i_size, lbn,
size, NOCRED, uio->uio_resid, seqcount, &bp);
else if (lbn - 1 == vp->v_lastr) {
+ /*
+ * If we are NOT allowed to cluster, then
+ * if we appear to be acting sequentially,
+ * fire off a request for a readahead
+ * as well as a read. Note that the 4th and 5th
+ * arguments point to arrays of the size specified in
+ * the 6th argument.
+ */
int nextsize = BLKSIZE(fs, ip, nextlbn);
error = breadn(vp, lbn,
size, &nextlbn, &nextsize, 1, NOCRED, &bp);
} else
+ /*
+ * Failing all of the above, just read what the
+ * user asked for. Interestingly, the same as
+ * the first option above.
+ */
error = bread(vp, lbn, size, NOCRED, &bp);
if (error) {
brelse(bp);
bp = NULL;
break;
}
+
+ /*
+ * Remember where we read so we can see latter if we start
+ * acting sequential.
+ */
vp->v_lastr = lbn;
/*
@@ -194,13 +270,22 @@ READ(ap)
}
if (vfs_ioopt && object &&
- (bp->b_flags & B_VMIO) &&
- ((blkoffset & PAGE_MASK) == 0) &&
- ((xfersize & PAGE_MASK) == 0)) {
+ (bp->b_flags & B_VMIO) &&
+ ((blkoffset & PAGE_MASK) == 0) &&
+ ((xfersize & PAGE_MASK) == 0)) {
+ /*
+ * If VFS IO optimisation is turned on,
+ * and it's an exact page multiple
+ * And a normal VM based op,
+ * then use uiomiveco()
+ */
error =
uiomoveco((char *)bp->b_data + blkoffset,
(int)xfersize, uio, object);
} else {
+ /*
+ * otherwise use the general form
+ */
error =
uiomove((char *)bp->b_data + blkoffset,
(int)xfersize, uio);
@@ -211,13 +296,30 @@ READ(ap)
if ((ioflag & IO_VMIO) &&
(LIST_FIRST(&bp->b_dep) == NULL)) {
+ /*
+ * If there are no dependencies, and
+ * it's VMIO, then we don't need the buf,
+ * mark it available for freeing. The VM has the data.
+ */
bp->b_flags |= B_RELBUF;
brelse(bp);
} else {
+ /*
+ * Otherwise let whoever
+ * made the request take care of
+ * freeing it. We just queue
+ * it onto another list.
+ */
bqrelse(bp);
}
}
+ /*
+ * This can only happen in the case of an error
+ * because the loop above resets bp to NULL on each iteration
+ * and on normal completion has not set a new value into it.
+ * so it must have come from a 'break' statement
+ */
if (bp != NULL) {
if ((ioflag & IO_VMIO) &&
(LIST_FIRST(&bp->b_dep) == NULL)) {
OpenPOWER on IntegriCloud