[Ocfs2-commits] zab commits r1622 - in trunk: . src

svn-commits at oss.oracle.com svn-commits at oss.oracle.com
Wed Nov 3 18:08:59 CST 2004


Author: zab
Date: 2004-11-03 18:08:57 -0600 (Wed, 03 Nov 2004)
New Revision: 1622

Modified:
   trunk/configure.in
   trunk/src/24io.c
   trunk/src/file.c
   trunk/src/inode.h
Log:
o clean up 2.4 aio.  requires that aio_complete exported from the kernel.  this
  was mostly rolled to stop partial aio_write results.  this survives that
  unit test and aio-stress on an smp box. 


Modified: trunk/configure.in
===================================================================
--- trunk/configure.in	2004-11-03 23:43:03 UTC (rev 1621)
+++ trunk/configure.in	2004-11-04 00:08:57 UTC (rev 1622)
@@ -239,7 +239,7 @@
 if test "x$OCFS_AIO" = "xyes"; then
   if test "x$KERNEL_26" = "xyes"; then
     have_aio=yes
-  elif egrep "EXPORT_SYMBOL.*\(brw_kvec_async\);" "$kernelsrc/kernel/ksyms.c" "$kernelsrc/fs/buffer.c" >/dev/null 2>&1; then
+  elif egrep "EXPORT_SYMBOL.*\(aio_complete\);" "$kerneldir/fs/aio.c" >/dev/null 2>&1; then
     have_aio=yes
   else
     have_aio=no

Modified: trunk/src/24io.c
===================================================================
--- trunk/src/24io.c	2004-11-03 23:43:03 UTC (rev 1621)
+++ trunk/src/24io.c	2004-11-04 00:08:57 UTC (rev 1622)
@@ -352,115 +352,167 @@
 }				/* ocfs_rw_direct */
 
 #ifdef AIO_ENABLED
-static int ocfs_kvec_rw(struct file *filp, int rw, kvec_cb_t cb,
-		size_t size, loff_t pos)
+static void ocfs_aio_issue(void * _iocb);
+
+static void ocfs_aio_complete(struct kiocb *iocb, long res) { 
+
+	if (iocb->nr_transferred)
+		res = iocb->nr_transferred;
+
+	aio_complete(iocb, res, 0);
+}
+
+static void ocfs_aio_complete_rw(int rw, void *_iocb, struct kvec *vec,
+				 ssize_t res)
 {
-	int	     err = 0;
-	int max_sectors = 25000;
-	struct inode *inode = filp->f_dentry->d_inode;
-	unsigned long blocknr, blocks, iosize,myiosize;
-	long firstphys;
-	int clustersize;
-	unsigned long blocks_end_cluster = 0;
- 
+	struct kiocb *iocb = _iocb;
+
+	unmap_kvec(vec, rw == READ);
+	free_kvec(vec);
+	
+	if (res <= 0)
+		ocfs_aio_complete(iocb, res);
+
+	iocb->nr_transferred += res;
+
+	if ((res != iocb->this_size) || iocb->ctx->dead ||
+	    (iocb->nr_transferred == iocb->size)) {
+		ocfs_aio_complete(iocb, 0);
+		return;
+	}
+
+	iocb->this_size = rw;
+	INIT_TQUEUE(&iocb->u.tq, ocfs_aio_issue, iocb);
+	schedule_task(&iocb->u.tq);
+}
+
+static void ocfs_aio_complete_read(void *_iocb, struct kvec *vec, ssize_t res)
+{
+	ocfs_aio_complete_rw(READ, _iocb, vec, res);
+}
+static void ocfs_aio_complete_write(void *_iocb, struct kvec *vec, ssize_t res)
+{
+	ocfs_aio_complete_rw(WRITE, _iocb, vec, res);
+}
+
+static void ocfs_aio_issue(void *_iocb)
+{
+	struct kiocb *iocb = _iocb;
+	struct inode *inode = iocb->filp->f_dentry->d_inode;
+	unsigned long blocknr, blocks, iosize, this, aio_max_blocks;
+	int rc = 0, rw = iocb->this_size;
+	long firstphys, phys;
+	kvec_cb_t cb;
+		
 	/* FIXME: Need to differentiate betwen sectors and blocksize */
 	int sector_bits = OCFS_SB(inode->i_sb)->s_sectsize_bits;
-	int sector_size = 1 << OCFS_SB(inode->i_sb)->s_sectsize_bits;
-	int sector_mask = sector_size - 1;
+	int clustersize = inode->i_blksize >> sector_bits;
 
-	unsigned long firstlogic;
-	long nextphys;
-	unsigned long nextlogic = 0;
-	unsigned long totalioblocks = 0;
+	iocb->this_size = 0;
 
-	if (!size || (pos == inode->i_size)) {
-		cb.fn(cb.data, cb.vec, err);
-		return err;
-	}
+	iosize = (iocb->size - iocb->nr_transferred) >> sector_bits;
+	BUG_ON(iosize == 0);
+	blocknr = (iocb->pos + iocb->nr_transferred) >> sector_bits;
+	firstphys = 0;
+	blocks = 0;
 
-	err = -ENXIO;
-	if (pos >= inode->i_size) {
-		return err;
-	}
+	aio_max_blocks = aio_max_size >> sector_bits;
 
-	err = -EINVAL;
-	if ((pos < 0) || (pos & sector_mask) || (size & sector_mask)) {
-		return err;
+	while (iosize > 0 && blocks < aio_max_blocks) {
+		rc = ocfs_get_sector(inode, blocknr, &phys);
+		if (rc < 0)
+			goto out;
+
+		if (firstphys == 0)
+			firstphys = phys;
+
+		/* issue the io when it stops being contiguous */
+		if (firstphys + blocks != phys)
+			break;
+
+		/* clamp when the rest of the io fits in the cluster */
+		this = min(clustersize - (blocknr % clustersize), iosize);
+		this = min(this, aio_max_blocks - blocks);
+
+		blocks += this;
+		blocknr += this;
+		iosize -= this;
 	}
 
-	blocknr = pos >> sector_bits;
+	/* we either got the first phys or returned an error from getblock */
+	BUG_ON(blocks == 0);
 
-	blocks = size >> sector_bits;;
-	if (blocks > max_sectors)
-		blocks = max_sectors;
-	if (!blocks) {
-		err = -ENXIO;
-		return err;
+	iocb->this_size = blocks << sector_bits;
+
+	cb.fn = (rw == READ) ? ocfs_aio_complete_read : 
+				ocfs_aio_complete_write;
+	cb.data = iocb;
+	cb.vec = mm_map_user_kvec(iocb->ctx->mm, rw, 
+				  iocb->buf + iocb->nr_transferred, 
+				  iocb->this_size);
+	if (unlikely(IS_ERR(cb.vec))) {
+		rc = PTR_ERR(cb.vec);
+		goto out;
 	}
 
-	iosize = blocks << sector_bits;
-	clustersize = inode->i_blksize >> sector_bits;
-	blocks_end_cluster = clustersize - (blocknr % clustersize);
-	myiosize = size >> sector_bits;
-	firstlogic = blocknr;
-	totalioblocks = 0;
+	rc = brw_kvec_async(rw, cb, inode->i_dev, blocks, firstphys, 
+			      sector_bits);
+out:
+	if (rc)
+		ocfs_aio_complete(iocb, rc);
+}
 
-	err = ocfs_get_sector(inode, blocknr, &firstphys);
-	if (err)
-		return err;
+static ssize_t ocfs_aio_rw(int rw, struct file *file, struct kiocb *req,
+				struct iocb *iocb)
+{
+	struct inode *inode = req->filp->f_dentry->d_inode;
+	loff_t pos = req->pos;
+	size_t size = req->size;
 
-		if (blocks_end_cluster + 1 > myiosize) {
-			totalioblocks += myiosize;
-			myiosize = 0;
-			goto doio;
-		} else {
-			totalioblocks += blocks_end_cluster;
-			myiosize -= blocks_end_cluster;
-			nextlogic = firstlogic + blocks_end_cluster;
-		}
-again:
-		err = ocfs_get_sector(inode, nextlogic, &nextphys);
-		if (err)
-			return err;
+	int sector_size = 1 << OCFS_SB(inode->i_sb)->s_sectsize_bits;
+	int sector_mask = (1 << sector_size) - 1;
 
-	    if (nextphys == (firstphys + totalioblocks)) {
-		blocks_end_cluster = clustersize - (nextlogic % clustersize);
-		if (blocks_end_cluster + 1 > myiosize) {
-		   totalioblocks += myiosize;
-		   myiosize = 0;
-		} else {
-		   totalioblocks += blocks_end_cluster;
-		   myiosize -= blocks_end_cluster;
-		   nextlogic = nextlogic + blocks_end_cluster;
-		   goto again;
-		}
-	    }
-doio:
-	blocks = totalioblocks;
-	err = brw_kvec_async(rw, cb, inode->i_dev, blocks, firstphys, sector_bits);
-	return err;
+	if (!size || (pos == inode->i_size)) {
+		ocfs_aio_complete(req, 0);
+		return 0;
+  	}
+  
+	if (aio_max_size < sector_size)
+		return -EINVAL;
 
+	if (pos >= inode->i_size)
+		return -ENXIO;
+
+	if ((pos < 0) || (pos & sector_mask) || (size & sector_mask))
+		return -EINVAL;
+
+	req->nr_transferred = 0;
+
+	/* from this point on errors are communicated through completion */
+	req->this_size = rw;
+	ocfs_aio_issue(req);
+	return 0;
 }
 
-int ocfs_kvec_read(struct file *file, kvec_cb_t cb, size_t size, loff_t pos) 
+int ocfs_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb)
 {
 	int ret;
 
 	LOG_SET_CONTEXT(KVEC_READ);
 
-	ret = ocfs_kvec_rw(file, READ, cb, size, pos);
+	ret = ocfs_aio_rw(READ, file, req, iocb);
 
 	LOG_CLEAR_CONTEXT();
 	return ret;
 }
 
-int ocfs_kvec_write(struct file *file, kvec_cb_t cb, size_t size, loff_t pos) 
+int ocfs_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb)
 {
 	int ret;
 
 	LOG_SET_CONTEXT(KVEC_WRITE);
 
-	ret = ocfs_kvec_rw(file, WRITE, cb, size, pos);
+	ret = ocfs_aio_rw(WRITE, file, req, iocb);
 
 	LOG_CLEAR_CONTEXT();
 	return ret;

Modified: trunk/src/file.c
===================================================================
--- trunk/src/file.c	2004-11-03 23:43:03 UTC (rev 1621)
+++ trunk/src/file.c	2004-11-04 00:08:57 UTC (rev 1622)
@@ -699,13 +699,13 @@
 	.release = ocfs_file_release,
 	.open = ocfs_file_open,
 	.ioctl = ocfs_ioctl,
-#if defined(AIO_ENABLED) || defined(AIO_26_ENABLED)
+#if defined(AIO_26_ENABLED)
 	.aio_read = generic_file_aio_read,
 	.aio_write = generic_file_aio_write,
-#ifdef AIO_ENABLED
-	.kvec_read = ocfs_kvec_read,
-	.kvec_write = ocfs_kvec_write,
 #endif
+#if defined(AIO_ENABLED)
+	.aio_read = ocfs_aio_read,
+	.aio_write = ocfs_aio_write,
 #endif
 };
 

Modified: trunk/src/inode.h
===================================================================
--- trunk/src/inode.h	2004-11-03 23:43:03 UTC (rev 1621)
+++ trunk/src/inode.h	2004-11-04 00:08:57 UTC (rev 1622)
@@ -48,8 +48,8 @@
 			  struct inode *inode, 
 			  struct buffer_head *bh);
 #ifdef AIO_ENABLED
-int ocfs_kvec_read(struct file *file, kvec_cb_t cb, size_t size, loff_t pos); 
-int ocfs_kvec_write(struct file *file, kvec_cb_t cb, size_t size, loff_t pos); 
+int ocfs_aio_read(struct file *file, struct kiocb *req, struct iocb *iocb);
+int ocfs_aio_write(struct file *file, struct kiocb *req, struct iocb *iocb);
 #endif
 
 #endif /* OCFS2_INODE_H */



More information about the Ocfs2-commits mailing list