[Cluster-devel] cluster/gfs-kernel/src/gfs dir.c file.c file.h ...

wcheng at sourceware.org wcheng at sourceware.org
Tue Oct 17 19:02:36 UTC 2006


CVSROOT:	/cvs/cluster
Module name:	cluster
Changes by:	wcheng at sourceware.org	2006-10-17 19:02:35

Modified files:
	gfs-kernel/src/gfs: dir.c file.c file.h ioctl.c ops_file.c 

Log message:
	Port RHEL4 GFS AIO (asynchronous IO) implementation into RHEL5/FC6 and
	community-version of GFS1.

Patches:
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/dir.c.diff?cvsroot=cluster&r1=1.13&r2=1.14
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/file.c.diff?cvsroot=cluster&r1=1.8&r2=1.9
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/file.h.diff?cvsroot=cluster&r1=1.4&r2=1.5
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.c.diff?cvsroot=cluster&r1=1.12&r2=1.13
http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_file.c.diff?cvsroot=cluster&r1=1.25&r2=1.26

--- cluster/gfs-kernel/src/gfs/dir.c	2006/07/10 23:22:34	1.13
+++ cluster/gfs-kernel/src/gfs/dir.c	2006/10/17 19:02:35	1.14
@@ -2210,7 +2210,7 @@
 		dip->i_di.di_blocks--;
 	}
 
-	error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks);
+	error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks, NULL);
 
 	if (error != size) {
 		if (error >= 0)
--- cluster/gfs-kernel/src/gfs/file.c	2006/07/10 23:22:34	1.8
+++ cluster/gfs-kernel/src/gfs/file.c	2006/10/17 19:02:35	1.9
@@ -306,7 +306,8 @@
 int
 gfs_writei(struct gfs_inode *ip, void *buf,
 	   uint64_t offset, unsigned int size,
-	   write_copy_fn_t copy_fn)
+	   write_copy_fn_t copy_fn,
+           struct kiocb *iocb)
 {
 	struct gfs_sbd *sdp = ip->i_sbd;
 	struct buffer_head *dibh, *bh;
--- cluster/gfs-kernel/src/gfs/file.h	2006/07/10 23:22:34	1.4
+++ cluster/gfs-kernel/src/gfs/file.h	2006/10/17 19:02:35	1.5
@@ -32,7 +32,8 @@
 int gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
 		       unsigned int offset, unsigned int size, int new);
 int gfs_writei(struct gfs_inode *ip, void *buf, uint64_t offset,
-	       unsigned int size, write_copy_fn_t copy_fn);
+               unsigned int size, write_copy_fn_t copy_fn,
+               struct kiocb *iocb);
 
 int gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf,
 		    unsigned int offset, unsigned int size, int new);
@@ -48,7 +49,7 @@
 gfs_internal_write(struct gfs_inode *ip, char *buf, uint64_t offset,
 		   unsigned int size)
 {
-	return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem);
+	return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem, NULL);
 }
 
 #endif /* __FILE_DOT_H__ */
--- cluster/gfs-kernel/src/gfs/ioctl.c	2006/08/11 14:32:32	1.12
+++ cluster/gfs-kernel/src/gfs/ioctl.c	2006/10/17 19:02:35	1.13
@@ -1229,7 +1229,7 @@
 	}
 
 	error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size,
-			   gfs_copy_from_user);
+			   gfs_copy_from_user, NULL);
 
 	gfs_trans_end(sdp);
 
--- cluster/gfs-kernel/src/gfs/ops_file.c	2006/08/11 14:32:32	1.25
+++ cluster/gfs-kernel/src/gfs/ops_file.c	2006/10/17 19:02:35	1.26
@@ -23,6 +23,7 @@
 #include <linux/uio.h>
 #include <linux/blkdev.h>
 #include <linux/mm.h>
+#include <linux/aio.h>
 #include <asm/uaccess.h>
 
 #include "gfs_ioctl.h"
@@ -76,6 +77,7 @@
 typedef ssize_t(*do_rw_t) (struct file * file,
 			   char *buf,
 			   size_t size, loff_t * offset,
+                           struct kiocb *iocb,
 			   unsigned int num_gh, struct gfs_holder * ghs);
 
 /**
@@ -129,7 +131,7 @@
 
 static ssize_t
 walk_vm_hard(struct file *file, char *buf, size_t size, loff_t *offset,
-	     do_rw_t operation)
+             struct kiocb *iocb, do_rw_t operation)
 {
 	struct gfs_holder *ghs;
 	unsigned int num_gh = 0;
@@ -178,7 +180,7 @@
 		gfs_assert(get_v2sdp(sb), x == num_gh,);
 	}
 
-	count = operation(file, buf, size, offset, num_gh, ghs);
+	count = operation(file, buf, size, offset, iocb, num_gh, ghs);
 
 	while (num_gh--)
 		gfs_holder_uninit(&ghs[num_gh]);
@@ -204,6 +206,7 @@
 
 static ssize_t
 walk_vm(struct file *file, char *buf, size_t size, loff_t *offset,
+	struct kiocb *iocb,	
 	do_rw_t operation)
 {
 	if (current->mm) {
@@ -231,11 +234,11 @@
 
 	{
 		struct gfs_holder gh;
-		return operation(file, buf, size, offset, 0, &gh);
+		return operation(file, buf, size, offset, iocb, 0, &gh);
 	}
 
  do_locks:
-	return walk_vm_hard(file, buf, size, offset, operation);
+	return walk_vm_hard(file, buf, size, offset, iocb, operation);
 }
 
 /**
@@ -250,7 +253,8 @@
  */
 
 static ssize_t
-do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset)
+do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset,
+              struct kiocb *iocb)
 {
 	struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
 	ssize_t count = 0;
@@ -267,6 +271,8 @@
 			size = 0x7FFFFFFFull - *offset;
 	}
 
+	/* ToDo: not sure about iocb .. wcheng
+	 */
 	count = gfs_readi(ip, buf, *offset, size, gfs_copy2user);
 
 	if (count > 0)
@@ -291,7 +297,8 @@
 
 static ssize_t
 do_read_direct(struct file *file, char *buf, size_t size, loff_t *offset,
-	       unsigned int num_gh, struct gfs_holder *ghs)
+		struct kiocb *iocb,
+		unsigned int num_gh, struct gfs_holder *ghs)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct gfs_inode *ip = get_v2ip(inode);
@@ -324,10 +331,16 @@
 		if (((*offset) & mask) || (((unsigned long)buf) & mask))
 			goto out_gunlock;
 
-		count = do_read_readi(file, buf, size & ~mask, offset);
+		count = do_read_readi(file, buf, size & ~mask, offset, iocb);
+	}
+	else {
+		if (!iocb) 
+			count = generic_file_read(file, buf, size, offset);
+		else {
+		        struct iovec local_iov = { .iov_base = buf, .iov_len = size};
+			count = __generic_file_aio_read(iocb, &local_iov, 1, offset);
+		}
 	}
-	else
-		count = generic_file_read(file, buf, size, offset);
 
 	error = 0;
 
@@ -356,7 +369,8 @@
 
 static ssize_t
 do_read_buf(struct file *file, char *buf, size_t size, loff_t *offset,
-	    unsigned int num_gh, struct gfs_holder *ghs)
+		struct kiocb *iocb,
+		unsigned int num_gh, struct gfs_holder *ghs)
 {
 	struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
 	ssize_t count = 0;
@@ -370,9 +384,22 @@
 
 	if (gfs_is_jdata(ip) ||
 	    (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags)))
-		count = do_read_readi(file, buf, size, offset);
-	else
-		count = generic_file_read(file, buf, size, offset);
+		count = do_read_readi(file, buf, size, offset, iocb);
+	else {
+		if (!iocb) {
+			count = generic_file_read(file, buf, size, offset);
+		} else {
+			struct iovec local_iov = {
+				.iov_base = (char __user *)buf,
+				.iov_len = size 
+			};
+
+		        count = __generic_file_aio_read(iocb, 
+					&local_iov, 1, offset);
+			if (count == -EIOCBQUEUED)
+				count = wait_on_sync_kiocb(iocb);
+		}
+	}
 
 	gfs_glock_dq_m(num_gh + 1, ghs);
 
@@ -382,6 +409,17 @@
 	return (count) ? count : error;
 }
 
+static ssize_t
+__gfs_read(struct file *file, char *buf, size_t size, loff_t *offset, struct kiocb *iocb)
+{
+	atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file);
+
+	if (file->f_flags & O_DIRECT)
+		return walk_vm(file, buf, size, offset, iocb, do_read_direct);
+	else
+		return walk_vm(file, buf, size, offset, iocb, do_read_buf);
+}
+
 /**
  * gfs_read - Read bytes from a file
  * @file: The file to read from
@@ -397,12 +435,20 @@
 static ssize_t
 gfs_read(struct file *file, char *buf, size_t size, loff_t *offset)
 {
-	atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file);
+	return(__gfs_read(file, buf, size, offset, NULL));
+}
 
-	if (file->f_flags & O_DIRECT)
-		return walk_vm(file, buf, size, offset, do_read_direct);
-	else
-		return walk_vm(file, buf, size, offset, do_read_buf);
+/*
+ * gfs_aio_read: match with vfs generic_file_aio_read as:
+ * 	(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+ */
+static ssize_t
+gfs_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos)
+{
+	struct file *filp = iocb->ki_filp;
+
+	BUG_ON(iocb->ki_pos != pos);
+	return(__gfs_read(filp, buf, count, &iocb->ki_pos, iocb));
 }
 
 /**
@@ -449,7 +495,8 @@
  */
 
 static ssize_t
-do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset)
+do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset,
+			struct kiocb *iocb)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct gfs_inode *ip = get_v2ip(inode);
@@ -502,13 +549,15 @@
 		brelse(dibh);
 	}
 
-	if (gfs_is_stuffed(ip)) {
-		error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL);
-		if (error)
+	if (gfs_is_stuffed(ip)) { error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); if (error)
 			goto fail_end_trans;
 	}
 
-	count = generic_file_write_nolock(file, &local_iov, 1, offset);
+	if (!iocb)
+		count = generic_file_write_nolock(file, &local_iov, 1, offset);
+	else {
+		count = generic_file_aio_write_nolock(iocb, &local_iov, 1, offset);
+	}
 	if (count < 0) {
 		error = count;
 		goto fail_end_trans;
@@ -528,6 +577,10 @@
 
 	gfs_trans_end(sdp);
 
+	/* Question (wcheng)
+	 * 1. should IS_SYNC flush glock ?
+	 * 2. does gfs_log_flush_glock flush data ?
+	 */
 	if (file->f_flags & O_SYNC)
 		gfs_log_flush_glock(ip->i_gl);
 
@@ -576,6 +629,7 @@
 
 static ssize_t
 do_write_direct(struct file *file, char *buf, size_t size, loff_t *offset,
+		struct kiocb *iocb,
 		unsigned int num_gh, struct gfs_holder *ghs)
 {
 	struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
@@ -652,7 +706,7 @@
 			if (s > size)
 				s = size;
 
-			error = do_write_direct_alloc(file, buf, s, offset);
+			error = do_write_direct_alloc(file, buf, s, offset, iocb);
 			if (error < 0)
 				goto out_gunlock;
 
@@ -670,8 +724,16 @@
 		if (error)
 			goto out_gunlock;
 
-		count = generic_file_write_nolock(file, &local_iov, 1, offset);
-
+		/* Todo: It would be nice if init_sync_kiocb is exported.
+		 *  .. wcheng
+		 */
+		if (!iocb) 
+			count = 
+			generic_file_write_nolock(file, &local_iov, 1, offset);
+		else {
+			count = 
+			generic_file_aio_write_nolock(iocb, &local_iov, 1, offset);
+		}
 		gfs_glock_dq_uninit(&t_gh);
 	}
 
@@ -699,7 +761,8 @@
  */
 
 static ssize_t
-do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset)
+do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset,
+		struct kiocb *iocb)
 {
 	struct inode *inode = file->f_mapping->host;
 	struct gfs_inode *ip = get_v2ip(inode);
@@ -777,7 +840,7 @@
 	    (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags) &&
 	     *offset + size <= sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))) {
 
-		count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user);
+		count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user, iocb);
 		if (count < 0) {
 			error = count;
 			goto fail_end_trans;
@@ -794,7 +857,14 @@
 	} else {
 		struct iovec local_iov = { .iov_base = buf, .iov_len = size };
 
-		count = generic_file_write_nolock(file, &local_iov, 1, offset);
+		if (!iocb) {
+			count = generic_file_write_nolock(file, &local_iov, 1, offset);
+		} else {
+			count = generic_file_aio_write_nolock(iocb, 
+				&local_iov, 1, offset);
+			if (count == -EIOCBQUEUED)
+				count = wait_on_sync_kiocb(iocb);
+		}
 		if (count < 0) {
 			error = count;
 			goto fail_end_trans;
@@ -869,8 +939,9 @@
 
 static ssize_t
 do_write_buf(struct file *file,
-	     char *buf, size_t size, loff_t *offset,
-	     unsigned int num_gh, struct gfs_holder *ghs)
+		char *buf, size_t size, loff_t *offset,
+		struct kiocb *iocb,
+		unsigned int num_gh, struct gfs_holder *ghs)
 {
 	struct gfs_inode *ip = get_v2ip(file->f_mapping->host);
 	struct gfs_sbd *sdp = ip->i_sbd;
@@ -907,7 +978,7 @@
 		if (s > size)
 			s = size;
 
-		error = do_do_write_buf(file, buf, s, offset);
+		error = do_do_write_buf(file, buf, s, offset, iocb);
 		if (error < 0)
 			goto out_gunlock;
 
@@ -940,7 +1011,7 @@
  */
 
 static ssize_t
-gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset)
+__gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset, struct kiocb *iocb)
 {
 	struct inode *inode = file->f_mapping->host;
 	ssize_t count;
@@ -954,14 +1025,30 @@
 
 	mutex_lock(&inode->i_mutex);
 	if (file->f_flags & O_DIRECT)
-		count = walk_vm(file, (char *)buf, size, offset, do_write_direct);
+		count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_direct);
 	else
-		count = walk_vm(file, (char *)buf, size, offset, do_write_buf);
+		count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_buf);
 	mutex_unlock(&inode->i_mutex);
 
 	return count;
 }
 
+static ssize_t
+gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset)
+{
+	return(__gfs_write(file, buf, size, offset, NULL));
+}
+
+static ssize_t
+gfs_aio_write(struct kiocb *iocb, const char __user *buf, size_t size, loff_t pos)
+{
+	struct file *file = iocb->ki_filp;
+
+	BUG_ON(iocb->ki_pos != pos);
+
+	return(__gfs_write(file, buf, size, &iocb->ki_pos, iocb));
+}
+
 /**
  * filldir_reg_func - Report a directory entry to the caller of gfs_dir_read()
  * @opaque: opaque data used by the function
@@ -1642,6 +1729,8 @@
 	.llseek = gfs_llseek,
 	.read = gfs_read,
 	.write = gfs_write,
+        .aio_read = gfs_aio_read,
+        .aio_write = gfs_aio_write,
 	.ioctl = gfs_ioctl,
 	.mmap = gfs_mmap,
 	.open = gfs_open,




More information about the Cluster-devel mailing list