]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
orangefs: implement writepage
authorMartin Brandenburg <martin@omnibond.com>
Thu, 22 Feb 2018 18:10:43 +0000 (18:10 +0000)
committerMike Marshall <hubcap@omnibond.com>
Fri, 3 May 2019 18:32:38 +0000 (14:32 -0400)
Now orangefs_inode_getattr fills from cache if an inode has dirty pages.

also if attr_valid and dirty pages and !flags, we spin on inode writeback
before returning if pages still dirty after: should it be other way

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
Signed-off-by: Mike Marshall <hubcap@omnibond.com>
fs/orangefs/file.c
fs/orangefs/inode.c
fs/orangefs/orangefs-utils.c

index 934f102ce9e1b89e9e03287e856a29321f7ec353..d8c97b87bf265f99acd4ccdfb65214702b68cbe0 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * (C) 2001 Clemson University and The University of Chicago
+ * Copyright 2018 Omnibond Systems, L.L.C.
  *
  * See COPYING in top-level directory.
  */
@@ -348,63 +349,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;
-
-       truncate_inode_pages(file->f_mapping, 0);
-
-       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,
-                   ORANGEFS_GETATTR_SIZE);
-               if (rc == -ESTALE)
-                       rc = -EIO;
-               if (rc) {
-                       gossip_err("%s: orangefs_inode_getattr failed, "
-                           "rc:%zd:.\n", __func__, rc);
-                       goto out;
-               }
-       }
-
-       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++;
-
-out:
-
-       inode_unlock(file->f_mapping->host);
-       return rc;
+       return generic_file_write_iter(iocb, iter);
 }
 
 /*
@@ -499,9 +448,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;
@@ -541,8 +487,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;
 }
@@ -560,6 +504,11 @@ static int orangefs_fsync(struct file *file,
                ORANGEFS_I(file_inode(file));
        struct orangefs_kernel_op_s *new_op = NULL;
 
+       ret = filemap_write_and_wait_range(file_inode(file)->i_mapping,
+           start, end);
+       if (ret < 0)
+               return ret;
+
        new_op = op_alloc(ORANGEFS_VFS_OP_FSYNC);
        if (!new_op)
                return -ENOMEM;
@@ -641,6 +590,11 @@ static int orangefs_lock(struct file *filp, int cmd, struct file_lock *fl)
        return rc;
 }
 
+static int orangefs_flush(struct file *file, fl_owner_t id)
+{
+       return vfs_fsync(file, 0);
+}
+
 /** ORANGEFS implementation of VFS file operations */
 const struct file_operations orangefs_file_operations = {
        .llseek         = orangefs_file_llseek,
@@ -650,6 +604,7 @@ const struct file_operations orangefs_file_operations = {
        .unlocked_ioctl = orangefs_ioctl,
        .mmap           = orangefs_file_mmap,
        .open           = generic_file_open,
+       .flush          = orangefs_flush,
        .release        = orangefs_file_release,
        .fsync          = orangefs_fsync,
 };
index 31ee3cb67fe0806bf9ed5c1d097d0d9c9f231518..3b54974817ea8ee18e172f83960e54c3a20bce58 100644 (file)
 #include "orangefs-kernel.h"
 #include "orangefs-bufmap.h"
 
+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;
+       size_t len, wlen;
+       ssize_t ret;
+       loff_t off;
+
+       set_page_writeback(page);
+
+       off = page_offset(page);
+       len = i_size_read(inode);
+       if (off > len) {
+               /* The file was truncated; there is nothing to write. */
+               unlock_page(page);
+               end_page_writeback(page);
+               return 0;
+       }
+       if (off + PAGE_SIZE > len)
+               wlen = len - off;
+       else
+               wlen = PAGE_SIZE;
+
+       bv.bv_page = page;
+       bv.bv_len = wlen;
+       bv.bv_offset = off % PAGE_SIZE;
+       if (wlen == 0)
+               dump_stack();
+       iov_iter_bvec(&iter, WRITE, &bv, 1, wlen);
+
+       ret = wait_for_direct_io(ORANGEFS_IO_WRITE, inode, &off, &iter, wlen,
+           len);
+       if (ret < 0) {
+               SetPageError(page);
+               mapping_set_error(page->mapping, ret);
+       } else {
+               ret = 0;
+       }
+       unlock_page(page);
+       end_page_writeback(page);
+       return ret;
+}
+
 static int orangefs_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
@@ -48,6 +92,15 @@ 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)
@@ -77,17 +130,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 */
 static 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,
index 9221c4a3398e4a14b524456a2c949394b2dd548d..d6093a468db989b2a982e7dda512ca7a513ad802 100644 (file)
@@ -247,7 +247,7 @@ int orangefs_inode_getattr(struct inode *inode, int flags)
        spin_lock(&inode->i_lock);
        /* Must have all the attributes in the mask and be within cache time. */
        if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
-           orangefs_inode->attr_valid) {
+           orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
                if (orangefs_inode->attr_valid) {
                        spin_unlock(&inode->i_lock);
                        write_inode_now(inode, 1);
@@ -281,12 +281,16 @@ int orangefs_inode_getattr(struct inode *inode, int flags)
        spin_lock(&inode->i_lock);
        /* Must have all the attributes in the mask and be within cache time. */
        if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) ||
-           orangefs_inode->attr_valid) {
+           orangefs_inode->attr_valid || inode->i_state & I_DIRTY_PAGES) {
                if (orangefs_inode->attr_valid) {
                        spin_unlock(&inode->i_lock);
                        write_inode_now(inode, 1);
                        goto again2;
                }
+               if (inode->i_state & I_DIRTY_PAGES) {
+                       ret = 0;
+                       goto out_unlock;
+               }
                gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n",
                    __func__);
                ret = 0;