From: Martin Brandenburg <mar...@omnibond.com>

With this and the previous commit, OrangeFS is capable of writing
through the page cache.

Signed-off-by: Martin Brandenburg <mar...@omnibond.com>
---
 fs/orangefs/file.c  | 132 +++++++++++++++++++++++-----------------------------
 fs/orangefs/inode.c |   2 +
 fs/orangefs/super.c |   8 ++++
 3 files changed, 67 insertions(+), 75 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index d80e1e6c1d95..200c72c21b0b 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -397,69 +397,11 @@ static ssize_t orangefs_file_read_iter(struct kiocb *iocb,
        return generic_file_read_iter(iocb, iter);
 }
 
-static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter 
*iter)
+static ssize_t orangefs_file_write_iter(struct kiocb *iocb,
+    struct iov_iter *iter)
 {
-       struct file *file = iocb->ki_filp;
-       loff_t pos;
-       ssize_t rc;
-
-       BUG_ON(iocb->private);
-
-       gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_write_iter\n");
-
-       inode_lock(file->f_mapping->host);
-
-       /* Make sure generic_write_checks sees an up to date inode size. */
-       if (file->f_flags & O_APPEND) {
-               rc = orangefs_inode_getattr(file->f_mapping->host, 0, 1,
-                   STATX_SIZE);
-               if (rc == -ESTALE)
-                       rc = -EIO;
-               if (rc) {
-                       gossip_err("%s: orangefs_inode_getattr failed, "
-                           "rc:%zd:.\n", __func__, rc);
-                       goto out;
-               }
-       }
-
-       if (file->f_pos > i_size_read(file->f_mapping->host))
-               orangefs_i_size_write(file->f_mapping->host, file->f_pos);
-
-       rc = generic_write_checks(iocb, iter);
-
-       if (rc <= 0) {
-               gossip_err("%s: generic_write_checks failed, rc:%zd:.\n",
-                          __func__, rc);
-               goto out;
-       }
-
-       /*
-        * if we are appending, generic_write_checks would have updated
-        * pos to the end of the file, so we will wait till now to set
-        * pos...
-        */
-       pos = *(&iocb->ki_pos);
-
-       rc = do_readv_writev(ORANGEFS_IO_WRITE,
-                            file,
-                            &pos,
-                            iter);
-       if (rc < 0) {
-               gossip_err("%s: do_readv_writev failed, rc:%zd:.\n",
-                          __func__, rc);
-               goto out;
-       }
-
-       iocb->ki_pos = pos;
        orangefs_stats.writes++;
-
-       if (pos > i_size_read(file->f_mapping->host))
-               orangefs_i_size_write(file->f_mapping->host, pos);
-
-out:
-
-       inode_unlock(file->f_mapping->host);
-       return rc;
+       return generic_file_write_iter(iocb, iter);
 }
 
 /*
@@ -554,9 +496,6 @@ static int orangefs_file_mmap(struct file *file, struct 
vm_area_struct *vma)
                        (char *)file->f_path.dentry->d_name.name :
                        (char *)"Unknown"));
 
-       if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_MAYWRITE))
-               return -EINVAL;
-
        /* set the sequential readahead hint */
        vma->vm_flags |= VM_SEQ_READ;
        vma->vm_flags &= ~VM_RAND_READ;
@@ -579,9 +518,8 @@ static int orangefs_file_release(struct inode *inode, 
struct file *file)
                     file);
 
        /*
-        * remove all associated inode pages from the page cache and
-        * readahead cache (if any); this forces an expensive refresh of
-        * data for the next caller of mmap (or 'get_block' accesses)
+        * remove all associated inode pages from the readahead cache
+        * (if any)
         */
        if (file_inode(file) &&
            file_inode(file)->i_mapping &&
@@ -594,8 +532,6 @@ static int orangefs_file_release(struct inode *inode, 
struct file *file)
                        gossip_debug(GOSSIP_INODE_DEBUG,
                            "flush_racache finished\n");
                }
-               truncate_inode_pages(file_inode(file)->i_mapping,
-                                    0);
        }
        return 0;
 }
@@ -707,6 +643,41 @@ const struct file_operations orangefs_file_operations = {
        .fsync          = orangefs_fsync,
 };
 
+
+static int orangefs_writepage(struct page *page,
+    struct writeback_control *wbc)
+{
+       struct inode *inode = page->mapping->host;
+       struct iov_iter iter;
+       struct bio_vec bv;
+       loff_t off;
+       size_t len;
+       ssize_t r;
+
+       off = page_offset(page);
+       len = i_size_read(inode);
+       if (off + PAGE_SIZE > len)
+               len = len - off;
+       else
+               len = PAGE_SIZE;
+
+       bv.bv_page = page;
+       bv.bv_len = len;
+       bv.bv_offset = 0;
+       iov_iter_bvec(&iter, ITER_BVEC | WRITE, &bv, 1, len);
+
+       set_page_writeback(page);
+
+       r = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter,
+           len, 0);
+       if (r < 0)
+               mapping_set_error(inode->i_mapping, r);
+
+       end_page_writeback(page);
+       unlock_page(page);
+       return 0;
+}
+
 static int orangefs_readpage(struct file *file, struct page *page)
 {
        int ret;
@@ -752,6 +723,17 @@ static int orangefs_readpage(struct file *file, struct 
page *page)
        return ret;
 }
 
+static int orangefs_write_end(struct file *file,
+    struct address_space *mapping, loff_t pos, unsigned len,
+    unsigned copied, struct page *page, void *fsdata)
+{
+       int r;
+       r = simple_write_end(file, mapping, pos, len, copied, page,
+           fsdata);
+       mark_inode_dirty_sync(file_inode(file));
+       return r;
+}
+
 static void orangefs_invalidatepage(struct page *page,
                                 unsigned int offset,
                                 unsigned int length)
@@ -781,17 +763,17 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb,
 {
        struct file *file = iocb->ki_filp;
        loff_t pos = *(&iocb->ki_pos);
-       /*
-        * This cannot happen until write_iter becomes
-        * generic_file_write_iter.
-        */
-       BUG_ON(iov_iter_rw(iter) != READ);
-       return do_readv_writev(ORANGEFS_IO_READ, file, &pos, iter);
+       return do_readv_writev(iov_iter_rw(iter) == WRITE ?
+           ORANGEFS_IO_WRITE : ORANGEFS_IO_READ, file, &pos, iter);
 }
 
 /** ORANGEFS2 implementation of address space operations */
 const struct address_space_operations orangefs_address_operations = {
+       .writepage = orangefs_writepage,
        .readpage = orangefs_readpage,
+       .set_page_dirty = __set_page_dirty_nobuffers,
+       .write_begin = simple_write_begin,
+       .write_end = orangefs_write_end,
        .invalidatepage = orangefs_invalidatepage,
        .releasepage = orangefs_releasepage,
        .direct_IO = orangefs_direct_IO,
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 2c4f57c5d830..231242a4856e 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -65,6 +65,8 @@ int orangefs_setattr(struct dentry *dentry, struct iattr 
*iattr)
        r = setattr_prepare(dentry, iattr);
        if (r)
                return r;
+       if (d_is_reg(dentry))
+               filemap_write_and_wait(d_inode(dentry)->i_mapping);
        if (iattr->ia_valid & ATTR_SIZE)
                if (i_size_read(d_inode(dentry)) != iattr->ia_size)
                        iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index 5c17709862ab..5c1a343ba026 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -315,11 +315,19 @@ static int orangefs_write_inode(struct inode *inode,
        return r;
 }
 
+static void orangefs_evict_inode(struct inode *inode)
+{
+       truncate_inode_pages_final(&inode->i_data);
+       clear_inode(inode);
+       filemap_fdatawrite(&inode->i_data);
+}
+
 static const struct super_operations orangefs_s_ops = {
        .alloc_inode = orangefs_alloc_inode,
        .destroy_inode = orangefs_destroy_inode,
        .write_inode = orangefs_write_inode,
        .drop_inode = generic_drop_inode,
+       .evict_inode = orangefs_evict_inode,
        .statfs = orangefs_statfs,
        .remount_fs = orangefs_remount_fs,
        .show_options = orangefs_show_options,
-- 
2.15.1

Reply via email to