[PATCH v3 3/3] PMFS: Add support for AIO and direct_IO

Vishal Verma vishal.l.verma at linux.intel.com
Tue Jun 11 13:53:18 EDT 2013


Signed-off-by: Vishal Verma <vishal.l.verma at linux.intel.com>
---
 fs/pmfs/file.c  |    2 ++
 fs/pmfs/inode.c |   52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/pmfs/xip.c   |   22 +++++++++++++++++++---
 fs/pmfs/xip.h   |    2 ++
 4 files changed, 75 insertions(+), 3 deletions(-)

diff --git a/fs/pmfs/file.c b/fs/pmfs/file.c
index fa49037..e5805c5 100644
--- a/fs/pmfs/file.c
+++ b/fs/pmfs/file.c
@@ -318,6 +318,8 @@ const struct file_operations pmfs_xip_file_operations = {
 	.llseek			= pmfs_llseek,
 	.read			= pmfs_xip_file_read,
 	.write			= pmfs_xip_file_write,
+	.aio_read		= xip_file_aio_read,
+	.aio_write		= xip_file_aio_write,
 	.mmap			= pmfs_xip_file_mmap,
 	.open			= generic_file_open,
 	.fsync			= pmfs_fsync,
diff --git a/fs/pmfs/inode.c b/fs/pmfs/inode.c
index ea10bd9..9e301b3 100644
--- a/fs/pmfs/inode.c
+++ b/fs/pmfs/inode.c
@@ -1564,7 +1564,59 @@ void pmfs_get_inode_flags(struct inode *inode, struct pmfs_inode *pi)
 	pi->i_flags = cpu_to_le32(pmfs_flags);
 }
 
+static ssize_t pmfs_direct_IO(int rw, struct kiocb *iocb,
+	const struct iovec *iov, loff_t offset, unsigned long nr_segs)
+{
+	struct file *filp = iocb->ki_filp;
+	struct inode *inode = filp->f_mapping->host;
+	struct pmfs_inode *pi;
+	loff_t end = offset;
+	ssize_t err = -EINVAL;
+	unsigned long seg;
+	loff_t eof;
+	uint32_t blk_size;
+
+	pi = pmfs_get_inode(inode->i_sb, inode->i_ino);
+	blk_size = pmfs_inode_blk_size(pi);
+	eof = (i_size_read(inode) + blk_size - 1) & ~(blk_size - 1);
+
+	for (seg = 0; seg < nr_segs; seg++)
+		end += iov[seg].iov_len;
+
+	if ((rw & WRITE) && end > i_size_read(inode)) {
+		/* FIXME: Does grow exist? Does it need to be implemented? */
+		printk(KERN_ERR "pmfs: needs to grow (size = %lld)\n", end);
+		return err;
+	} else if (rw == READ && end > eof) {
+		if (offset >= eof) {
+			if (!is_sync_kiocb(iocb))
+				aio_complete(iocb, 0, 0);
+			return 0;
+		}
+		end = eof;
+	}
+
+	for (seg = 0; seg < nr_segs; seg++) {
+		const struct iovec *iv = &iov[seg];
+		if (rw == READ)
+			err = pmfs_xip_file_read(filp, iv->iov_base,
+					iv->iov_len, &offset);
+		else if (rw == WRITE)
+			err = pmfs_xip_file_write_nolock(filp, iv->iov_base,
+					iv->iov_len, &offset);
+		if (err <= 0)
+			goto err;
+	}
+	if (offset != end)
+		printk(KERN_ERR "pmfs: direct_IO: end = %lld"
+			"but offset = %lld\n", end, offset);
+	err = 0;
+err:
+	return err;
+}
+
 const struct address_space_operations pmfs_aops_xip = {
 	.get_xip_mem		= pmfs_get_xip_mem,
+	.direct_IO		= pmfs_direct_IO,
 	/*.xip_mem_protect	= pmfs_xip_mem_protect,*/
 };
diff --git a/fs/pmfs/xip.c b/fs/pmfs/xip.c
index f0f93b2..51d3a14 100644
--- a/fs/pmfs/xip.c
+++ b/fs/pmfs/xip.c
@@ -186,6 +186,25 @@ ssize_t pmfs_xip_file_write(struct file *filp, const char __user *buf,
 {
 	struct address_space *mapping = filp->f_mapping;
 	struct inode    *inode = mapping->host;
+	size_t ret;
+
+	mutex_lock(&inode->i_mutex);
+	ret = pmfs_xip_file_write_nolock(filp, buf, len, ppos);
+	mutex_unlock(&inode->i_mutex);
+
+	return ret;
+}
+
+/* When aops->direct_IO (pmfs_direct_IO) is called, i_mutex is
+ * already held by VFS, and we don't need to lock it.
+ * Use the following interface for this case.
+ */
+
+ssize_t pmfs_xip_file_write_nolock(struct file *filp, const char __user *buf,
+          size_t len, loff_t *ppos)
+{
+	struct address_space *mapping = filp->f_mapping;
+	struct inode    *inode = mapping->host;
 	struct super_block *sb = inode->i_sb;
 	pmfs_transaction_t *trans;
 	struct pmfs_inode *pi;
@@ -196,8 +215,6 @@ ssize_t pmfs_xip_file_write(struct file *filp, const char __user *buf,
 	size_t count, offset, ret;
 	unsigned long start_blk, num_blocks, max_logentries;
 
-	mutex_lock(&inode->i_mutex);
-
 	if (!access_ok(VERIFY_READ, buf, len)) {
 		ret = -EFAULT;
 		goto out;
@@ -277,7 +294,6 @@ ssize_t pmfs_xip_file_write(struct file *filp, const char __user *buf,
 out_backing:
 	current->backing_dev_info = NULL;
 out:
-	mutex_unlock(&inode->i_mutex);
 	return ret;
 }
 
diff --git a/fs/pmfs/xip.h b/fs/pmfs/xip.h
index 3bd9306..d539cfa 100644
--- a/fs/pmfs/xip.h
+++ b/fs/pmfs/xip.h
@@ -16,6 +16,8 @@ ssize_t pmfs_xip_file_read(struct file *filp, char __user *buf, size_t len,
 			    loff_t *ppos);
 ssize_t pmfs_xip_file_write(struct file *filp, const char __user *buf,
 		size_t len, loff_t *ppos);
+ssize_t pmfs_xip_file_write_nolock(struct file *filp, const char __user *buf,
+		size_t len, loff_t *ppos);
 int pmfs_xip_file_mmap(struct file *file, struct vm_area_struct *vma);
 
 static inline int pmfs_use_xip(struct super_block *sb)
-- 
1.7.0.4




More information about the Linux-pmfs mailing list