[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