All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Brandenburg <martin@omnibond.com>
To: hubcap@omnibond.com, devel@lists.orangefs.org,
	linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: Martin Brandenburg <martin@omnibond.com>
Subject: [PATCH 16/18] orangefs: implement write through the page cache
Date: Tue, 12 Dec 2017 13:34:22 -0500	[thread overview]
Message-ID: <20171212183424.26406-17-martin@martinbrandenburg.com> (raw)
In-Reply-To: <20171212183424.26406-1-martin@martinbrandenburg.com>

From: Martin Brandenburg <martin@omnibond.com>

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

Signed-off-by: Martin Brandenburg <martin@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

  parent reply	other threads:[~2017-12-12 18:36 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
2017-12-12 18:34 ` [PATCH 01/18] orangefs: open code short single-use functions Martin Brandenburg
2017-12-12 18:34 ` [PATCH 02/18] orangefs: implement vm_ops->fault Martin Brandenburg
2017-12-12 18:34 ` [PATCH 03/18] orangefs: do not invalidate attributes on inode create Martin Brandenburg
2017-12-12 18:34 ` [PATCH 04/18] orangefs: do not invalidate attribute cache on setattr Martin Brandenburg
2017-12-12 18:34 ` [PATCH 05/18] orangefs: reverse sense of revalidate is-inode-stale test Martin Brandenburg
2017-12-12 18:34 ` [PATCH 06/18] orangefs: move orangefs_address_operations to file.c Martin Brandenburg
2017-12-12 18:34 ` [PATCH 07/18] orangefs: remove orangefs_readpages Martin Brandenburg
2017-12-12 18:34 ` [PATCH 08/18] orangefs: make orangefs_inode_read static Martin Brandenburg
2017-12-12 18:34 ` [PATCH 09/18] orangefs: only set a_ops for regular files Martin Brandenburg
2017-12-12 18:34 ` [PATCH 10/18] orangefs: BUG_ON if i_mode invalid Martin Brandenburg
2017-12-12 18:34 ` [PATCH 11/18] orangefs: remove mapping_nrpages macro Martin Brandenburg
2017-12-12 18:34 ` [PATCH 12/18] orangefs: set up and use backing_dev_info Martin Brandenburg
2017-12-12 18:34 ` [PATCH 13/18] orangefs: inodes linger in cache Martin Brandenburg
2017-12-12 18:34 ` [PATCH 14/18] orangefs: implement direct_IO for the read case Martin Brandenburg
2017-12-12 18:34 ` [PATCH 15/18] orangefs: call generic_file_read_iter Martin Brandenburg
2017-12-12 18:34 ` Martin Brandenburg [this message]
2017-12-12 18:34 ` [PATCH 17/18] orangefs: no more explicit setattr Martin Brandenburg
2017-12-12 18:34 ` [PATCH 18/18] orangefs: implement xattr cache Martin Brandenburg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171212183424.26406-17-martin@martinbrandenburg.com \
    --to=martin@omnibond.com \
    --cc=devel@lists.orangefs.org \
    --cc=hubcap@omnibond.com \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.