All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/18] orangefs: page cache
@ 2017-12-12 18:34 Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 01/18] orangefs: open code short single-use functions Martin Brandenburg
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

The first five patches were sent up two weeks ago.

https://marc.info/?l=linux-fsdevel&m=151190064825337&w=2

There is a bug in the original "implement vm_ops->fault" which is fixed
here.  When expanding generic_file_readonly_mmap, I neglected to include
the test for VM_SHARED and VM_MAYWRITE.  The test is removed later in
"implement write through the page cache," but if only the first five are
accepted for the next kernel, they should be taken from here.

I sent this up some time ago

https://marc.info/?l=linux-fsdevel&m=149548681910978&w=2

I hope the code is faily self-explanatory.  This isn't quite in a fully
finished or tested state, but it's starting to come together.
Unfortunately most of the changes from last time are fixes for subtle
bugs and are rebased in, which makes them hard to see.

This is significantly more stable than it was six months ago, but I'm
still worried about how it will act when run for days, weeks, months at
a time and across multiple machines.  This is the next step in my
testing.

I'd appreciate any reviews, even if just to tell me that I've done
everything completely wrong.

Martin Brandenburg (18):
  orangefs: open code short single-use functions
  orangefs: implement vm_ops->fault
  orangefs: do not invalidate attributes on inode create
  orangefs: do not invalidate attribute cache on setattr
  orangefs: reverse sense of revalidate is-inode-stale test
  orangefs: move orangefs_address_operations to file.c
  orangefs: remove orangefs_readpages
  orangefs: make orangefs_inode_read static
  orangefs: only set a_ops for regular files
  orangefs: BUG_ON if i_mode invalid
  orangefs: remove mapping_nrpages macro
  orangefs: set up and use backing_dev_info
  orangefs: inodes linger in cache
  orangefs: implement direct_IO for the read case
  orangefs: call generic_file_read_iter
  orangefs: implement write through the page cache
  orangefs: no more explicit setattr
  orangefs: implement xattr cache

 fs/orangefs/acl.c             |  11 +-
 fs/orangefs/dcache.c          |  17 +-
 fs/orangefs/file.c            | 353 +++++++++++++++++++++++-------------------
 fs/orangefs/inode.c           | 259 ++++---------------------------
 fs/orangefs/namei.c           |  75 ++++++---
 fs/orangefs/orangefs-kernel.h |  19 +--
 fs/orangefs/orangefs-utils.c  |  11 +-
 fs/orangefs/super.c           |  60 ++++++-
 fs/orangefs/symlink.c         |   2 -
 fs/orangefs/xattr.c           |  62 ++++++++
 10 files changed, 409 insertions(+), 460 deletions(-)

-- 
2.15.1

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 01/18] orangefs: open code short single-use functions
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 02/18] orangefs: implement vm_ops->fault Martin Brandenburg
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c | 95 +++++++++++-------------------------------------------
 1 file changed, 19 insertions(+), 76 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 1668fd645c45..44879b1ff33e 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -41,70 +41,6 @@ static int flush_racache(struct inode *inode)
 	return ret;
 }
 
-/*
- * Copy to client-core's address space from the buffers specified
- * by the iovec upto total_size bytes.
- * NOTE: the iovector can either contain addresses which
- *       can futher be kernel-space or user-space addresses.
- *       or it can pointers to struct page's
- */
-static int precopy_buffers(int buffer_index,
-			   struct iov_iter *iter,
-			   size_t total_size)
-{
-	int ret = 0;
-	/*
-	 * copy data from application/kernel by pulling it out
-	 * of the iovec.
-	 */
-
-
-	if (total_size) {
-		ret = orangefs_bufmap_copy_from_iovec(iter,
-						      buffer_index,
-						      total_size);
-		if (ret < 0)
-		gossip_err("%s: Failed to copy-in buffers. Please make sure that the pvfs2-client is running. %ld\n",
-			   __func__,
-			   (long)ret);
-	}
-
-	if (ret < 0)
-		gossip_err("%s: Failed to copy-in buffers. Please make sure that the pvfs2-client is running. %ld\n",
-			__func__,
-			(long)ret);
-	return ret;
-}
-
-/*
- * Copy from client-core's address space to the buffers specified
- * by the iovec upto total_size bytes.
- * NOTE: the iovector can either contain addresses which
- *       can futher be kernel-space or user-space addresses.
- *       or it can pointers to struct page's
- */
-static int postcopy_buffers(int buffer_index,
-			    struct iov_iter *iter,
-			    size_t total_size)
-{
-	int ret = 0;
-	/*
-	 * copy data to application/kernel by pushing it out to
-	 * the iovec. NOTE; target buffers can be addresses or
-	 * struct page pointers.
-	 */
-	if (total_size) {
-		ret = orangefs_bufmap_copy_to_iovec(iter,
-						    buffer_index,
-						    total_size);
-		if (ret < 0)
-			gossip_err("%s: Failed to copy-out buffers. Please make sure that the pvfs2-client is running (%ld)\n",
-				__func__,
-				(long)ret);
-	}
-	return ret;
-}
-
 /*
  * Post and wait for the I/O upcall to finish
  */
@@ -157,14 +93,15 @@ static ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inod
 		     total_size);
 	/*
 	 * Stage 1: copy the buffers into client-core's address space
-	 * precopy_buffers only pertains to writes.
 	 */
-	if (type == ORANGEFS_IO_WRITE) {
-		ret = precopy_buffers(buffer_index,
-				      iter,
-				      total_size);
-		if (ret < 0)
+	if (type == ORANGEFS_IO_WRITE && total_size) {
+		ret = orangefs_bufmap_copy_from_iovec(iter, buffer_index,
+		    total_size);
+		if (ret < 0) {
+			gossip_err("%s: Failed to copy-in buffers. Please make sure that the pvfs2-client is running. %ld\n",
+			    __func__, (long)ret);
 			goto out;
+		}
 	}
 
 	gossip_debug(GOSSIP_FILE_DEBUG,
@@ -260,14 +197,20 @@ static ssize_t wait_for_direct_io(enum ORANGEFS_io_type type, struct inode *inod
 
 	/*
 	 * Stage 3: Post copy buffers from client-core's address space
-	 * postcopy_buffers only pertains to reads.
 	 */
-	if (type == ORANGEFS_IO_READ) {
-		ret = postcopy_buffers(buffer_index,
-				       iter,
-				       new_op->downcall.resp.io.amt_complete);
-		if (ret < 0)
+	if (type == ORANGEFS_IO_READ && new_op->downcall.resp.io.amt_complete) {
+		/*
+		 * NOTE: the iovector can either contain addresses which
+		 *       can futher be kernel-space or user-space addresses.
+		 *       or it can pointers to struct page's
+		 */
+		ret = orangefs_bufmap_copy_to_iovec(iter, buffer_index,
+		    new_op->downcall.resp.io.amt_complete);
+		if (ret < 0) {
+			gossip_err("%s: Failed to copy-out buffers. Please make sure that the pvfs2-client is running (%ld)\n",
+			    __func__, (long)ret);
 			goto out;
+		}
 	}
 	gossip_debug(GOSSIP_FILE_DEBUG,
 	    "%s(%pU): Amount %s, returned by the sys-io call:%d\n",
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 02/18] orangefs: implement vm_ops->fault
  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 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 03/18] orangefs: do not invalidate attributes on inode create Martin Brandenburg
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Must retrieve size before running filemap_fault so the kernel has
an up-to-date size.

This should have been caught by xfstests generic/246, but it was masked
by orangefs_new_inode, which set i_size to PAGE_SIZE.  When nothing
caused a getattr prior to a pagefault, i_size was still PAGE_SIZE.
Since xfstests only read 10 bytes, it did not catch this bug.

When orangefs_new_inode was modified to perform a getattr instead,
i_size was set to zero, as it was a newly created file.  Then
orangefs_file_write_iter did NOT set i_size, instead prefering to
invalidate the attribute cache and letting the next caller retrieve
i_size.  But the fault handler did not know it was supposed to retrieve
i_size.  So during xfstests, i_size was still zero, and filemap_fault
returned VM_FAULT_SIGBUS.

Fixes xfstests generic/080, generic/141, generic/215, generic/247,
generic/248, generic/437, and generic/452.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 44879b1ff33e..70909ee27323 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -531,6 +531,28 @@ static long orangefs_ioctl(struct file *file, unsigned int cmd, unsigned long ar
 	return ret;
 }
 
+static int orangefs_fault(struct vm_fault *vmf)
+{
+	struct file *file = vmf->vma->vm_file;
+	int rc;
+	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:%d:.\n", __func__, rc);
+		return rc;
+	}
+	return filemap_fault(vmf);
+}
+
+const struct vm_operations_struct orangefs_file_vm_ops = {
+	.fault = orangefs_fault,
+	.map_pages = filemap_map_pages,
+	.page_mkwrite = filemap_page_mkwrite,
+};
+
 /*
  * Memory map a region of a file.
  */
@@ -542,12 +564,16 @@ 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;
 
-	/* Use readonly mmap since we cannot support writable maps. */
-	return generic_file_readonly_mmap(file, vma);
+	file_accessed(file);
+	vma->vm_ops = &orangefs_file_vm_ops;
+	return 0;
 }
 
 #define mapping_nrpages(idata) ((idata)->nrpages)
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 03/18] orangefs: do not invalidate attributes on inode create
  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 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 04/18] orangefs: do not invalidate attribute cache on setattr Martin Brandenburg
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

When an inode is created, we fetch attributes from the server.  There is
no need to turn around and invalidate them.

No need to initialize attributes after the getattr either.  Either we'll
do nothing or do something wrong.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/inode.c | 6 ------
 fs/orangefs/namei.c | 6 ------
 2 files changed, 12 deletions(-)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index fe1d705ad91f..ff0c799f09e2 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -448,12 +448,6 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
 		goto out_iput;
 
 	orangefs_init_iops(inode);
-
-	inode->i_mode = mode;
-	inode->i_uid = current_fsuid();
-	inode->i_gid = current_fsgid();
-	inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
-	inode->i_size = PAGE_SIZE;
 	inode->i_rdev = dev;
 
 	error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index c98bba2dbc94..f79401b2486a 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -78,8 +78,6 @@ static int orangefs_create(struct inode *dir,
 	d_instantiate(dentry, inode);
 	unlock_new_inode(inode);
 	orangefs_set_timeout(dentry);
-	ORANGEFS_I(inode)->getattr_time = jiffies - 1;
-	ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
 
 	gossip_debug(GOSSIP_NAME_DEBUG,
 		     "%s: dentry instantiated for %pd\n",
@@ -335,8 +333,6 @@ static int orangefs_symlink(struct inode *dir,
 	d_instantiate(dentry, inode);
 	unlock_new_inode(inode);
 	orangefs_set_timeout(dentry);
-	ORANGEFS_I(inode)->getattr_time = jiffies - 1;
-	ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
 
 	gossip_debug(GOSSIP_NAME_DEBUG,
 		     "Inode (Symlink) %pU -> %pd\n",
@@ -405,8 +401,6 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 	d_instantiate(dentry, inode);
 	unlock_new_inode(inode);
 	orangefs_set_timeout(dentry);
-	ORANGEFS_I(inode)->getattr_time = jiffies - 1;
-	ORANGEFS_I(inode)->getattr_mask = STATX_BASIC_STATS;
 
 	gossip_debug(GOSSIP_NAME_DEBUG,
 		     "Inode (Directory) %pU -> %pd\n",
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 04/18] orangefs: do not invalidate attribute cache on setattr
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (2 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 03/18] orangefs: do not invalidate attributes on inode create Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 05/18] orangefs: reverse sense of revalidate is-inode-stale test Martin Brandenburg
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/orangefs-utils.c | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c
index 97fe93129f38..553b3ded51cd 100644
--- a/fs/orangefs/orangefs-utils.c
+++ b/fs/orangefs/orangefs-utils.c
@@ -437,10 +437,6 @@ int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr)
 	}
 
 	op_release(new_op);
-
-	if (ret == 0)
-		orangefs_inode->getattr_time = jiffies - 1;
-
 	return ret;
 }
 
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 05/18] orangefs: reverse sense of revalidate is-inode-stale test
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (3 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 04/18] orangefs: do not invalidate attribute cache on setattr Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 06/18] orangefs: move orangefs_address_operations to file.c Martin Brandenburg
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/dcache.c | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c
index ae782df5c063..c7aa5c923477 100644
--- a/fs/orangefs/dcache.c
+++ b/fs/orangefs/dcache.c
@@ -118,8 +118,12 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
 		return 0;
 
 	/* We do not need to continue with negative dentries. */
-	if (!dentry->d_inode)
-		goto out;
+	if (!dentry->d_inode) {
+		gossip_debug(GOSSIP_DCACHE_DEBUG,
+		    "%s: negative dentry or positive dentry and inode valid.\n",
+		    __func__);
+		return 1;
+	}
 
 	/* Now we must perform a getattr to validate the inode contents. */
 
@@ -129,14 +133,7 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags)
 		    __FILE__, __func__, __LINE__);
 		return 0;
 	}
-	if (ret == 0)
-		return 0;
-
-out:
-	gossip_debug(GOSSIP_DCACHE_DEBUG,
-	    "%s: negative dentry or positive dentry and inode valid.\n",
-	    __func__);
-	return 1;
+	return !ret;
 }
 
 const struct dentry_operations orangefs_dentry_operations = {
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 06/18] orangefs: move orangefs_address_operations to file.c
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (4 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 05/18] orangefs: reverse sense of revalidate is-inode-stale test Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 07/18] orangefs: remove orangefs_readpages Martin Brandenburg
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

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

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 70909ee27323..f9c1dc5aaf78 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -718,3 +718,135 @@ const struct file_operations orangefs_file_operations = {
 	.release	= orangefs_file_release,
 	.fsync		= orangefs_fsync,
 };
+
+static int read_one_page(struct page *page)
+{
+	int ret;
+	int max_block;
+	ssize_t bytes_read = 0;
+	struct inode *inode = page->mapping->host;
+	const __u32 blocksize = PAGE_SIZE;	/* inode->i_blksize */
+	const __u32 blockbits = PAGE_SHIFT;	/* inode->i_blkbits */
+	struct iov_iter to;
+	struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE};
+
+	iov_iter_bvec(&to, ITER_BVEC | READ, &bv, 1, PAGE_SIZE);
+
+	gossip_debug(GOSSIP_INODE_DEBUG,
+		    "orangefs_readpage called with page %p\n",
+		     page);
+
+	max_block = ((inode->i_size / blocksize) + 1);
+
+	if (page->index < max_block) {
+		loff_t blockptr_offset = (((loff_t) page->index) << blockbits);
+
+		bytes_read = orangefs_inode_read(inode,
+						 &to,
+						 &blockptr_offset,
+						 inode->i_size);
+	}
+	/* this will only zero remaining unread portions of the page data */
+	iov_iter_zero(~0U, &to);
+	/* takes care of potential aliasing */
+	flush_dcache_page(page);
+	if (bytes_read < 0) {
+		ret = bytes_read;
+		SetPageError(page);
+	} else {
+		SetPageUptodate(page);
+		if (PageError(page))
+			ClearPageError(page);
+		ret = 0;
+	}
+	/* unlock the page after the ->readpage() routine completes */
+	unlock_page(page);
+	return ret;
+}
+
+static int orangefs_readpage(struct file *file, struct page *page)
+{
+	return read_one_page(page);
+}
+
+static int orangefs_readpages(struct file *file,
+			   struct address_space *mapping,
+			   struct list_head *pages,
+			   unsigned nr_pages)
+{
+	int page_idx;
+	int ret;
+
+	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_readpages called\n");
+
+	for (page_idx = 0; page_idx < nr_pages; page_idx++) {
+		struct page *page;
+
+		page = list_entry(pages->prev, struct page, lru);
+		list_del(&page->lru);
+		if (!add_to_page_cache(page,
+				       mapping,
+				       page->index,
+				       readahead_gfp_mask(mapping))) {
+			ret = read_one_page(page);
+			gossip_debug(GOSSIP_INODE_DEBUG,
+				"failure adding page to cache, read_one_page returned: %d\n",
+				ret);
+	      } else {
+			put_page(page);
+	      }
+	}
+	BUG_ON(!list_empty(pages));
+	return 0;
+}
+
+static void orangefs_invalidatepage(struct page *page,
+				 unsigned int offset,
+				 unsigned int length)
+{
+	gossip_debug(GOSSIP_INODE_DEBUG,
+		     "orangefs_invalidatepage called on page %p "
+		     "(offset is %u)\n",
+		     page,
+		     offset);
+
+	ClearPageUptodate(page);
+	ClearPageMappedToDisk(page);
+	return;
+
+}
+
+static int orangefs_releasepage(struct page *page, gfp_t foo)
+{
+	gossip_debug(GOSSIP_INODE_DEBUG,
+		     "orangefs_releasepage called on page %p\n",
+		     page);
+	return 0;
+}
+
+/*
+ * Having a direct_IO entry point in the address_space_operations
+ * struct causes the kernel to allows us to use O_DIRECT on
+ * open. Nothing will ever call this thing, but in the future we
+ * will need to be able to use O_DIRECT on open in order to support
+ * AIO. Modeled after NFS, they do this too.
+ */
+
+static ssize_t orangefs_direct_IO(struct kiocb *iocb,
+				  struct iov_iter *iter)
+{
+	gossip_debug(GOSSIP_INODE_DEBUG,
+		     "orangefs_direct_IO: %pD\n",
+		     iocb->ki_filp);
+
+	return -EINVAL;
+}
+
+/** ORANGEFS2 implementation of address space operations */
+const struct address_space_operations orangefs_address_operations = {
+	.readpage = orangefs_readpage,
+	.readpages = orangefs_readpages,
+	.invalidatepage = orangefs_invalidatepage,
+	.releasepage = orangefs_releasepage,
+	.direct_IO = orangefs_direct_IO,
+};
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index ff0c799f09e2..5c451e245cf7 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -14,138 +14,6 @@
 #include "orangefs-kernel.h"
 #include "orangefs-bufmap.h"
 
-static int read_one_page(struct page *page)
-{
-	int ret;
-	int max_block;
-	ssize_t bytes_read = 0;
-	struct inode *inode = page->mapping->host;
-	const __u32 blocksize = PAGE_SIZE;	/* inode->i_blksize */
-	const __u32 blockbits = PAGE_SHIFT;	/* inode->i_blkbits */
-	struct iov_iter to;
-	struct bio_vec bv = {.bv_page = page, .bv_len = PAGE_SIZE};
-
-	iov_iter_bvec(&to, ITER_BVEC | READ, &bv, 1, PAGE_SIZE);
-
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		    "orangefs_readpage called with page %p\n",
-		     page);
-
-	max_block = ((inode->i_size / blocksize) + 1);
-
-	if (page->index < max_block) {
-		loff_t blockptr_offset = (((loff_t) page->index) << blockbits);
-
-		bytes_read = orangefs_inode_read(inode,
-						 &to,
-						 &blockptr_offset,
-						 inode->i_size);
-	}
-	/* this will only zero remaining unread portions of the page data */
-	iov_iter_zero(~0U, &to);
-	/* takes care of potential aliasing */
-	flush_dcache_page(page);
-	if (bytes_read < 0) {
-		ret = bytes_read;
-		SetPageError(page);
-	} else {
-		SetPageUptodate(page);
-		if (PageError(page))
-			ClearPageError(page);
-		ret = 0;
-	}
-	/* unlock the page after the ->readpage() routine completes */
-	unlock_page(page);
-	return ret;
-}
-
-static int orangefs_readpage(struct file *file, struct page *page)
-{
-	return read_one_page(page);
-}
-
-static int orangefs_readpages(struct file *file,
-			   struct address_space *mapping,
-			   struct list_head *pages,
-			   unsigned nr_pages)
-{
-	int page_idx;
-	int ret;
-
-	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_readpages called\n");
-
-	for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-		struct page *page;
-
-		page = list_entry(pages->prev, struct page, lru);
-		list_del(&page->lru);
-		if (!add_to_page_cache(page,
-				       mapping,
-				       page->index,
-				       readahead_gfp_mask(mapping))) {
-			ret = read_one_page(page);
-			gossip_debug(GOSSIP_INODE_DEBUG,
-				"failure adding page to cache, read_one_page returned: %d\n",
-				ret);
-	      } else {
-			put_page(page);
-	      }
-	}
-	BUG_ON(!list_empty(pages));
-	return 0;
-}
-
-static void orangefs_invalidatepage(struct page *page,
-				 unsigned int offset,
-				 unsigned int length)
-{
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_invalidatepage called on page %p "
-		     "(offset is %u)\n",
-		     page,
-		     offset);
-
-	ClearPageUptodate(page);
-	ClearPageMappedToDisk(page);
-	return;
-
-}
-
-static int orangefs_releasepage(struct page *page, gfp_t foo)
-{
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_releasepage called on page %p\n",
-		     page);
-	return 0;
-}
-
-/*
- * Having a direct_IO entry point in the address_space_operations
- * struct causes the kernel to allows us to use O_DIRECT on
- * open. Nothing will ever call this thing, but in the future we
- * will need to be able to use O_DIRECT on open in order to support
- * AIO. Modeled after NFS, they do this too.
- */
-
-static ssize_t orangefs_direct_IO(struct kiocb *iocb,
-				  struct iov_iter *iter)
-{
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_direct_IO: %pD\n",
-		     iocb->ki_filp);
-
-	return -EINVAL;
-}
-
-/** ORANGEFS2 implementation of address space operations */
-const struct address_space_operations orangefs_address_operations = {
-	.readpage = orangefs_readpage,
-	.readpages = orangefs_readpages,
-	.invalidatepage = orangefs_invalidatepage,
-	.releasepage = orangefs_releasepage,
-	.direct_IO = orangefs_direct_IO,
-};
-
 static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
 {
 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 07/18] orangefs: remove orangefs_readpages
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (5 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 06/18] orangefs: move orangefs_address_operations to file.c Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 08/18] orangefs: make orangefs_inode_read static Martin Brandenburg
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

It's a copy of the loop which runs if it's not implemented from
read_pages from mm/readahead.c.  Best to just use the generic code.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c | 39 +--------------------------------------
 1 file changed, 1 insertion(+), 38 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index f9c1dc5aaf78..3e5d467e24e6 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -719,7 +719,7 @@ const struct file_operations orangefs_file_operations = {
 	.fsync		= orangefs_fsync,
 };
 
-static int read_one_page(struct page *page)
+static int orangefs_readpage(struct file *file, struct page *page)
 {
 	int ret;
 	int max_block;
@@ -764,42 +764,6 @@ static int read_one_page(struct page *page)
 	return ret;
 }
 
-static int orangefs_readpage(struct file *file, struct page *page)
-{
-	return read_one_page(page);
-}
-
-static int orangefs_readpages(struct file *file,
-			   struct address_space *mapping,
-			   struct list_head *pages,
-			   unsigned nr_pages)
-{
-	int page_idx;
-	int ret;
-
-	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_readpages called\n");
-
-	for (page_idx = 0; page_idx < nr_pages; page_idx++) {
-		struct page *page;
-
-		page = list_entry(pages->prev, struct page, lru);
-		list_del(&page->lru);
-		if (!add_to_page_cache(page,
-				       mapping,
-				       page->index,
-				       readahead_gfp_mask(mapping))) {
-			ret = read_one_page(page);
-			gossip_debug(GOSSIP_INODE_DEBUG,
-				"failure adding page to cache, read_one_page returned: %d\n",
-				ret);
-	      } else {
-			put_page(page);
-	      }
-	}
-	BUG_ON(!list_empty(pages));
-	return 0;
-}
-
 static void orangefs_invalidatepage(struct page *page,
 				 unsigned int offset,
 				 unsigned int length)
@@ -845,7 +809,6 @@ static ssize_t orangefs_direct_IO(struct kiocb *iocb,
 /** ORANGEFS2 implementation of address space operations */
 const struct address_space_operations orangefs_address_operations = {
 	.readpage = orangefs_readpage,
-	.readpages = orangefs_readpages,
 	.invalidatepage = orangefs_invalidatepage,
 	.releasepage = orangefs_releasepage,
 	.direct_IO = orangefs_direct_IO,
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 08/18] orangefs: make orangefs_inode_read static
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (6 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 07/18] orangefs: remove orangefs_readpages Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 09/18] orangefs: only set a_ops for regular files Martin Brandenburg
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c            | 6 ++----
 fs/orangefs/orangefs-kernel.h | 5 -----
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 3e5d467e24e6..afb94ed7cef3 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -351,10 +351,8 @@ static ssize_t do_readv_writev(enum ORANGEFS_io_type type, struct file *file,
  * Read data from a specified offset in a file (referenced by inode).
  * Data may be placed either in a user or kernel buffer.
  */
-ssize_t orangefs_inode_read(struct inode *inode,
-			    struct iov_iter *iter,
-			    loff_t *offset,
-			    loff_t readahead_size)
+static ssize_t orangefs_inode_read(struct inode *inode,
+    struct iov_iter *iter, loff_t *offset, loff_t readahead_size)
 {
 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 	size_t count = iov_iter_count(iter);
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 97adf7d100b5..ba62de332e04 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -433,11 +433,6 @@ ssize_t orangefs_listxattr(struct dentry *dentry, char *buffer, size_t size);
 struct inode *orangefs_iget(struct super_block *sb,
 			 struct orangefs_object_kref *ref);
 
-ssize_t orangefs_inode_read(struct inode *inode,
-			    struct iov_iter *iter,
-			    loff_t *offset,
-			    loff_t readahead_size);
-
 /*
  * defined in devorangefs-req.c
  */
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 09/18] orangefs: only set a_ops for regular files
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (7 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 08/18] orangefs: make orangefs_inode_read static Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 10/18] orangefs: BUG_ON if i_mode invalid Martin Brandenburg
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/inode.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 5c451e245cf7..cf6924c36a22 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -187,12 +187,11 @@ const struct inode_operations orangefs_file_inode_operations = {
 
 static int orangefs_init_iops(struct inode *inode)
 {
-	inode->i_mapping->a_ops = &orangefs_address_operations;
-
 	switch (inode->i_mode & S_IFMT) {
 	case S_IFREG:
 		inode->i_op = &orangefs_file_inode_operations;
 		inode->i_fop = &orangefs_file_operations;
+		inode->i_data.a_ops = &orangefs_address_operations;
 		inode->i_blkbits = PAGE_SHIFT;
 		break;
 	case S_IFLNK:
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 10/18] orangefs: BUG_ON if i_mode invalid
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (8 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 09/18] orangefs: only set a_ops for regular files Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 11/18] orangefs: remove mapping_nrpages macro Martin Brandenburg
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

This can't happen since it would have been caught (and a graceful
error returned) earlier.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/inode.c          | 14 ++++----------
 fs/orangefs/orangefs-utils.c |  4 ++++
 2 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index cf6924c36a22..f3a157571a6a 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -193,22 +193,16 @@ static int orangefs_init_iops(struct inode *inode)
 		inode->i_fop = &orangefs_file_operations;
 		inode->i_data.a_ops = &orangefs_address_operations;
 		inode->i_blkbits = PAGE_SHIFT;
-		break;
+		return 0;
 	case S_IFLNK:
 		inode->i_op = &orangefs_symlink_inode_operations;
-		break;
+		return 0;
 	case S_IFDIR:
 		inode->i_op = &orangefs_dir_inode_operations;
 		inode->i_fop = &orangefs_dir_operations;
-		break;
-	default:
-		gossip_debug(GOSSIP_INODE_DEBUG,
-			     "%s: unsupported mode\n",
-			     __func__);
-		return -EINVAL;
+		return 0;
 	}
-
-	return 0;
+	BUG_ON(1);
 }
 
 /*
diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c
index 553b3ded51cd..2c5b7a3d7793 100644
--- a/fs/orangefs/orangefs-utils.c
+++ b/fs/orangefs/orangefs-utils.c
@@ -296,6 +296,10 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
 
 	type = orangefs_inode_type(new_op->
 	    downcall.resp.getattr.attributes.objtype);
+	if (type == -1) {
+		ret = -EIO;
+		goto out;
+	}
 	ret = orangefs_inode_is_stale(inode, new,
 	    &new_op->downcall.resp.getattr.attributes,
 	    new_op->downcall.resp.getattr.link_target);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 11/18] orangefs: remove mapping_nrpages macro
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (9 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 10/18] orangefs: BUG_ON if i_mode invalid Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 12/18] orangefs: set up and use backing_dev_info Martin Brandenburg
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c  | 4 +---
 fs/orangefs/namei.c | 4 ++++
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index afb94ed7cef3..8dfa0e8c7326 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -574,8 +574,6 @@ static int orangefs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	return 0;
 }
 
-#define mapping_nrpages(idata) ((idata)->nrpages)
-
 /*
  * Called to notify the module that there are no more references to
  * this file (i.e. no processes have it open).
@@ -595,7 +593,7 @@ static int orangefs_file_release(struct inode *inode, struct file *file)
 	 */
 	if (file_inode(file) &&
 	    file_inode(file)->i_mapping &&
-	    mapping_nrpages(&file_inode(file)->i_data)) {
+	    file_inode(file)->i_mapping->nrpages) {
 		if (orangefs_features & ORANGEFS_FEATURE_READAHEAD) {
 			gossip_debug(GOSSIP_INODE_DEBUG,
 			    "calling flush_racache on %pU\n",
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index f79401b2486a..d3a62e52c724 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -330,6 +330,8 @@ static int orangefs_symlink(struct inode *dir,
 		     "Assigned symlink inode new number of %pU\n",
 		     get_khandle_from_ino(inode));
 
+	inode->i_size = strlen(symname);
+
 	d_instantiate(dentry, inode);
 	unlock_new_inode(inode);
 	orangefs_set_timeout(dentry);
@@ -398,6 +400,8 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 		     "Assigned dir inode new number of %pU\n",
 		     get_khandle_from_ino(inode));
 
+	inode->i_size = PAGE_SIZE;
+
 	d_instantiate(dentry, inode);
 	unlock_new_inode(inode);
 	orangefs_set_timeout(dentry);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 12/18] orangefs: set up and use backing_dev_info
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (10 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 11/18] orangefs: remove mapping_nrpages macro Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 13/18] orangefs: inodes linger in cache Martin Brandenburg
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

This is a heavily modified revert of
70823b9bf3290855a7df895d89bd8209182b52e3.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/super.c | 21 ++++++++++++++-------
 1 file changed, 14 insertions(+), 7 deletions(-)

diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index 366750eef201..314c4a816983 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -396,15 +396,11 @@ static int orangefs_fill_sb(struct super_block *sb,
 		struct orangefs_fs_mount_response *fs_mount,
 		void *data, int silent)
 {
-	int ret = -EINVAL;
-	struct inode *root = NULL;
-	struct dentry *root_dentry = NULL;
+	int ret;
+	struct inode *root;
+	struct dentry *root_dentry;
 	struct orangefs_object_kref root_object;
 
-	/* alloc and init our private orangefs sb info */
-	sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
-	if (!ORANGEFS_SB(sb))
-		return -ENOMEM;
 	ORANGEFS_SB(sb)->sb = sb;
 
 	ORANGEFS_SB(sb)->root_khandle = fs_mount->root_khandle;
@@ -427,6 +423,10 @@ static int orangefs_fill_sb(struct super_block *sb,
 	sb->s_blocksize_bits = orangefs_bufmap_shift_query();
 	sb->s_maxbytes = MAX_LFS_FILESIZE;
 
+	ret = super_setup_bdi(sb);
+	if (ret)
+		return ret;
+
 	root_object.khandle = ORANGEFS_SB(sb)->root_khandle;
 	root_object.fs_id = ORANGEFS_SB(sb)->fs_id;
 	gossip_debug(GOSSIP_SUPER_DEBUG,
@@ -505,6 +505,13 @@ struct dentry *orangefs_mount(struct file_system_type *fst,
 		goto free_op;
 	}
 
+	/* alloc and init our private orangefs sb info */
+	sb->s_fs_info = kzalloc(sizeof(struct orangefs_sb_info_s), GFP_KERNEL);
+	if (!ORANGEFS_SB(sb)) {
+		d = ERR_PTR(-ENOMEM);
+		goto free_op;
+	}
+
 	ret = orangefs_fill_sb(sb,
 	      &new_op->downcall.resp.fs_mount, data,
 	      flags & MS_SILENT ? 1 : 0);
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 13/18] orangefs: inodes linger in cache
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (11 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 12/18] orangefs: set up and use backing_dev_info Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 14/18] orangefs: implement direct_IO for the read case Martin Brandenburg
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

This is a big change, but it boils down to implementing write_inode,
changing generic_delete_inode to generic_drop_inode, and changing
set/getattr to set/get from the in-memory inode.

The OrangeFS client requires a real getattr prior to any directory
operations.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c            |  3 ++
 fs/orangefs/inode.c           | 84 ++++++++++---------------------------------
 fs/orangefs/namei.c           | 48 +++++++++++++++++++++++--
 fs/orangefs/orangefs-kernel.h |  2 --
 fs/orangefs/orangefs-utils.c  |  3 ++
 fs/orangefs/super.c           | 22 +++++++++++-
 fs/orangefs/symlink.c         |  1 -
 7 files changed, 92 insertions(+), 71 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 8dfa0e8c7326..1c30e9abb8cb 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -464,6 +464,9 @@ static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *ite
 	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);
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index f3a157571a6a..2c4f57c5d830 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -18,7 +18,6 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
 {
 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 	struct orangefs_kernel_op_s *new_op;
-	loff_t orig_size;
 	int ret = -EINVAL;
 
 	gossip_debug(GOSSIP_INODE_DEBUG,
@@ -29,17 +28,6 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
 		     orangefs_inode->refn.fs_id,
 		     iattr->ia_size);
 
-	/* Ensure that we have a up to date size, so we know if it changed. */
-	ret = orangefs_inode_getattr(inode, 0, 1, STATX_SIZE);
-	if (ret == -ESTALE)
-		ret = -EIO;
-	if (ret) {
-		gossip_err("%s: orangefs_inode_getattr failed, ret:%d:.\n",
-		    __func__, ret);
-		return ret;
-	}
-	orig_size = i_size_read(inode);
-
 	truncate_setsize(inode, iattr->ia_size);
 
 	new_op = op_alloc(ORANGEFS_VFS_OP_TRUNCATE);
@@ -65,9 +53,6 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
 	if (ret != 0)
 		return ret;
 
-	if (orig_size != i_size_read(inode))
-		iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
-
 	return ret;
 }
 
@@ -76,38 +61,25 @@ static int orangefs_setattr_size(struct inode *inode, struct iattr *iattr)
  */
 int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
 {
-	int ret = -EINVAL;
-	struct inode *inode = dentry->d_inode;
-
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_setattr: called on %pd\n",
-		     dentry);
-
-	ret = setattr_prepare(dentry, iattr);
-	if (ret)
-		goto out;
-
+	int r;
+	r = setattr_prepare(dentry, iattr);
+	if (r)
+		return r;
+	if (iattr->ia_valid & ATTR_SIZE)
+		if (i_size_read(d_inode(dentry)) != iattr->ia_size)
+			iattr->ia_valid |= ATTR_CTIME | ATTR_MTIME;
+	setattr_copy(d_inode(dentry), iattr);
+	mark_inode_dirty(d_inode(dentry));
 	if (iattr->ia_valid & ATTR_SIZE) {
-		ret = orangefs_setattr_size(inode, iattr);
-		if (ret)
-			goto out;
+		r = orangefs_setattr_size(d_inode(dentry), iattr);
+		if (r)
+			return r;
 	}
-
-	setattr_copy(inode, iattr);
-	mark_inode_dirty(inode);
-
-	ret = orangefs_inode_setattr(inode, iattr);
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_setattr: inode_setattr returned %d\n",
-		     ret);
-
-	if (!ret && (iattr->ia_valid & ATTR_MODE))
-		/* change mod on a file that has ACLs */
-		ret = posix_acl_chmod(inode, inode->i_mode);
-
-out:
-	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n", ret);
-	return ret;
+	if (iattr->ia_valid & ATTR_MODE) {
+		return posix_acl_chmod(d_inode(dentry),
+		    d_inode(dentry)->i_mode);
+	}
+	return 0;
 }
 
 /*
@@ -116,14 +88,14 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr)
 int orangefs_getattr(const struct path *path, struct kstat *stat,
 		     u32 request_mask, unsigned int flags)
 {
-	int ret = -ENOENT;
 	struct inode *inode = path->dentry->d_inode;
 	struct orangefs_inode_s *orangefs_inode = NULL;
+	int ret;
 
 	gossip_debug(GOSSIP_INODE_DEBUG,
 		     "orangefs_getattr: called on %pd\n",
 		     path->dentry);
-
+ 
 	ret = orangefs_inode_getattr(inode, 0, 0, request_mask);
 	if (ret == 0) {
 		generic_fillattr(inode, stat);
@@ -141,23 +113,6 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
 	return ret;
 }
 
-int orangefs_permission(struct inode *inode, int mask)
-{
-	int ret;
-
-	if (mask & MAY_NOT_BLOCK)
-		return -ECHILD;
-
-	gossip_debug(GOSSIP_INODE_DEBUG, "%s: refreshing\n", __func__);
-
-	/* Make sure the permission (and other common attrs) are up to date. */
-	ret = orangefs_inode_getattr(inode, 0, 0, STATX_MODE);
-	if (ret < 0)
-		return ret;
-
-	return generic_permission(inode, mask);
-}
-
 int orangefs_update_time(struct inode *inode, struct timespec *time, int flags)
 {
 	struct iattr iattr;
@@ -181,7 +136,6 @@ const struct inode_operations orangefs_file_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.permission = orangefs_permission,
 	.update_time = orangefs_update_time,
 };
 
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index d3a62e52c724..37d7d8214e3e 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -31,6 +31,13 @@ static int orangefs_create(struct inode *dir,
 		     __func__,
 		     dentry);
 
+	/* Need directory updates to be on server prior to issuing op. */
+	write_inode_now(dir, 1);
+	/* Need OrangeFS client to update capability. */
+	ret = orangefs_inode_getattr(dir, 1, 1, STATX_ALL);
+	if (ret)
+		goto out;
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_CREATE);
 	if (!new_op)
 		return -ENOMEM;
@@ -236,6 +243,13 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
 		     &parent->refn.khandle,
 		     parent->refn.fs_id);
 
+	/* Need directory updates to be on server prior to issuing op. */
+	write_inode_now(dir, 1);
+	/* Need OrangeFS client to update capability. */
+	ret = orangefs_inode_getattr(dir, 1, 1, STATX_ALL);
+	if (ret)
+		return ret;
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_REMOVE);
 	if (!new_op)
 		return -ENOMEM;
@@ -286,6 +300,13 @@ static int orangefs_symlink(struct inode *dir,
 	if (strlen(symname)+1 > ORANGEFS_NAME_MAX)
 		return -ENAMETOOLONG;
 
+	/* Need directory updates to be on server prior to issuing op. */
+	write_inode_now(dir, 1);
+	/* Need OrangeFS client to update capability. */
+	ret = orangefs_inode_getattr(dir, 1, 1, STATX_ALL);
+	if (ret)
+		goto out;
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_SYMLINK);
 	if (!new_op)
 		return -ENOMEM;
@@ -360,6 +381,13 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 	struct iattr iattr;
 	int ret;
 
+	/* Need directory updates to be on server prior to issuing op. */
+	write_inode_now(dir, 1);
+	/* Need OrangeFS client to update capability. */
+	ret = orangefs_inode_getattr(dir, 1, 1, STATX_ALL);
+	if (ret)
+		goto out;
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR);
 	if (!new_op)
 		return -ENOMEM;
@@ -442,6 +470,17 @@ static int orangefs_rename(struct inode *old_dir,
 
 	ORANGEFS_I(new_dentry->d_parent->d_inode)->getattr_time = jiffies - 1;
 
+	/* Need directory updates to be on server prior to issuing op. */
+	write_inode_now(old_dir, 1);
+	write_inode_now(new_dir, 1);
+	/* Need OrangeFS client to update capability. */
+	ret = orangefs_inode_getattr(old_dir, 1, 1, STATX_ALL);
+	if (ret)
+		return ret;
+	ret = orangefs_inode_getattr(new_dir, 1, 1, STATX_ALL);
+	if (ret)
+		return ret;
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_RENAME);
 	if (!new_op)
 		return -EINVAL;
@@ -459,14 +498,20 @@ static int orangefs_rename(struct inode *old_dir,
 	ret = service_operation(new_op,
 				"orangefs_rename",
 				get_interruptible_flag(old_dentry->d_inode));
-
 	gossip_debug(GOSSIP_NAME_DEBUG,
 		     "orangefs_rename: got downcall status %d\n",
 		     ret);
 
+	if (ret < 0)
+		goto out;
+
 	if (new_dentry->d_inode)
 		new_dentry->d_inode->i_ctime = current_time(new_dentry->d_inode);
 
+	new_dir->i_mtime = current_time(new_dir);
+	new_dir->i_ctime = current_time(new_dir);
+
+out:
 	op_release(new_op);
 	return ret;
 }
@@ -485,6 +530,5 @@ const struct inode_operations orangefs_dir_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.permission = orangefs_permission,
 	.update_time = orangefs_update_time,
 };
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index ba62de332e04..9c0b575a16e8 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -407,8 +407,6 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr);
 int orangefs_getattr(const struct path *path, struct kstat *stat,
 		     u32 request_mask, unsigned int flags);
 
-int orangefs_permission(struct inode *inode, int mask);
-
 int orangefs_update_time(struct inode *, struct timespec *, int);
 
 /*
diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c
index 2c5b7a3d7793..0953ada47cac 100644
--- a/fs/orangefs/orangefs-utils.c
+++ b/fs/orangefs/orangefs-utils.c
@@ -264,6 +264,9 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass,
 	gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU\n", __func__,
 	    get_khandle_from_ino(inode));
 
+	if (inode->i_state & I_DIRTY)
+		return 0;
+
 	if (!new && !bypass) {
 		/*
 		 * Must have all the attributes in the mask and be within cache
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index 314c4a816983..5c17709862ab 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -296,10 +296,30 @@ void fsid_key_table_finalize(void)
 {
 }
 
+static int orangefs_write_inode(struct inode *inode,
+    struct writeback_control *wbc)
+{
+	struct iattr iattr;
+	int r;
+	iattr.ia_valid = ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_ATIME |
+	    ATTR_ATIME_SET | ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME;
+	iattr.ia_mode = inode->i_mode;
+	iattr.ia_uid = inode->i_uid;
+	iattr.ia_gid = inode->i_gid;
+	iattr.ia_atime = inode->i_atime;
+	iattr.ia_mtime = inode->i_mtime;
+	iattr.ia_ctime = inode->i_ctime;
+	r = orangefs_inode_setattr(inode, &iattr);
+	if (r)
+		return r;
+	return r;
+}
+
 static const struct super_operations orangefs_s_ops = {
 	.alloc_inode = orangefs_alloc_inode,
 	.destroy_inode = orangefs_destroy_inode,
-	.drop_inode = generic_delete_inode,
+	.write_inode = orangefs_write_inode,
+	.drop_inode = generic_drop_inode,
 	.statfs = orangefs_statfs,
 	.remount_fs = orangefs_remount_fs,
 	.show_options = orangefs_show_options,
diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c
index db107fe91ab3..c08f81af1090 100644
--- a/fs/orangefs/symlink.c
+++ b/fs/orangefs/symlink.c
@@ -14,6 +14,5 @@ const struct inode_operations orangefs_symlink_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.permission = orangefs_permission,
 	.update_time = orangefs_update_time,
 };
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 14/18] orangefs: implement direct_IO for the read case
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (12 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 13/18] orangefs: inodes linger in cache Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 15/18] orangefs: call generic_file_read_iter Martin Brandenburg
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

Since orangefs_file_read_iter now calls generic_file_read_iter, O_DIRECT
now goes through direct_IO in the read case.  In the write case,
orangefs_file_write_iter never calls direct_IO, but handles the direct
write manually.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c | 21 ++++++++-------------
 1 file changed, 8 insertions(+), 13 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 1c30e9abb8cb..0223a0351d11 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -787,22 +787,17 @@ static int orangefs_releasepage(struct page *page, gfp_t foo)
 	return 0;
 }
 
-/*
- * Having a direct_IO entry point in the address_space_operations
- * struct causes the kernel to allows us to use O_DIRECT on
- * open. Nothing will ever call this thing, but in the future we
- * will need to be able to use O_DIRECT on open in order to support
- * AIO. Modeled after NFS, they do this too.
- */
-
 static ssize_t orangefs_direct_IO(struct kiocb *iocb,
 				  struct iov_iter *iter)
 {
-	gossip_debug(GOSSIP_INODE_DEBUG,
-		     "orangefs_direct_IO: %pD\n",
-		     iocb->ki_filp);
-
-	return -EINVAL;
+	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);
 }
 
 /** ORANGEFS2 implementation of address space operations */
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 15/18] orangefs: call generic_file_read_iter
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (13 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 14/18] orangefs: implement direct_IO for the read case Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 16/18] orangefs: implement write through the page cache Martin Brandenburg
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

From: Martin Brandenburg <martin@omnibond.com>

No need to manually implement this.  The generic implementation handles
direct IO as well.

Signed-off-by: Martin Brandenburg <martin@omnibond.com>
---
 fs/orangefs/file.c | 17 +++--------------
 1 file changed, 3 insertions(+), 14 deletions(-)

diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c
index 0223a0351d11..d80e1e6c1d95 100644
--- a/fs/orangefs/file.c
+++ b/fs/orangefs/file.c
@@ -390,22 +390,11 @@ static ssize_t orangefs_inode_read(struct inode *inode,
 	return ret;
 }
 
-static ssize_t orangefs_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
+static ssize_t orangefs_file_read_iter(struct kiocb *iocb,
+    struct iov_iter *iter)
 {
-	struct file *file = iocb->ki_filp;
-	loff_t pos = *(&iocb->ki_pos);
-	ssize_t rc = 0;
-
-	BUG_ON(iocb->private);
-
-	gossip_debug(GOSSIP_FILE_DEBUG, "orangefs_file_read_iter\n");
-
 	orangefs_stats.reads++;
-
-	rc = do_readv_writev(ORANGEFS_IO_READ, file, &pos, iter);
-	iocb->ki_pos = pos;
-
-	return rc;
+	return generic_file_read_iter(iocb, iter);
 }
 
 static ssize_t orangefs_file_write_iter(struct kiocb *iocb, struct iov_iter *iter)
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 16/18] orangefs: implement write through the page cache
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (14 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 15/18] orangefs: call generic_file_read_iter Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  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
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

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

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 17/18] orangefs: no more explicit setattr
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (15 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 16/18] orangefs: implement write through the page cache Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  2017-12-12 18:34 ` [PATCH 18/18] orangefs: implement xattr cache Martin Brandenburg
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

Now inodes will be marked dirty and written back at the appopriate time.

Signed-off-by: Martin Brandenburg <martin@martinbrandenburg.com>
---
 fs/orangefs/acl.c             | 11 +++--------
 fs/orangefs/inode.c           | 17 -----------------
 fs/orangefs/namei.c           | 17 -----------------
 fs/orangefs/orangefs-kernel.h |  2 --
 fs/orangefs/symlink.c         |  1 -
 5 files changed, 3 insertions(+), 45 deletions(-)

diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c
index 480ea059a680..90c25ae741b2 100644
--- a/fs/orangefs/acl.c
+++ b/fs/orangefs/acl.c
@@ -121,8 +121,6 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 {
 	int error;
 	struct iattr iattr;
-	int rc;
-
 	if (type == ACL_TYPE_ACCESS && acl) {
 		/*
 		 * posix_acl_update_mode checks to see if the permissions
@@ -140,14 +138,11 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
 		}
 
 		if (acl) {
-			rc = __orangefs_set_acl(inode, acl, type);
+			return __orangefs_set_acl(inode, acl, type);
 		} else {
-			iattr.ia_valid = ATTR_MODE;
-			rc = orangefs_inode_setattr(inode, &iattr);
+			mark_inode_dirty(inode);
+			return 0;
 		}
-
-		return rc;
-
 	} else {
 		return -EINVAL;
 	}
diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 231242a4856e..66c40ac7c4ac 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -115,22 +115,6 @@ int orangefs_getattr(const struct path *path, struct kstat *stat,
 	return ret;
 }
 
-int orangefs_update_time(struct inode *inode, struct timespec *time, int flags)
-{
-	struct iattr iattr;
-	gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_update_time: %pU\n",
-	    get_khandle_from_ino(inode));
-	generic_update_time(inode, time, flags);
-	memset(&iattr, 0, sizeof iattr);
-        if (flags & S_ATIME)
-		iattr.ia_valid |= ATTR_ATIME;
-	if (flags & S_CTIME)
-		iattr.ia_valid |= ATTR_CTIME;
-	if (flags & S_MTIME)
-		iattr.ia_valid |= ATTR_MTIME;
-	return orangefs_inode_setattr(inode, &iattr);
-}
-
 /* ORANGEDS2 implementation of VFS inode operations for files */
 const struct inode_operations orangefs_file_inode_operations = {
 	.get_acl = orangefs_get_acl,
@@ -138,7 +122,6 @@ const struct inode_operations orangefs_file_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.update_time = orangefs_update_time,
 };
 
 static int orangefs_init_iops(struct inode *inode)
diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c
index 37d7d8214e3e..13ef64fd6302 100644
--- a/fs/orangefs/namei.c
+++ b/fs/orangefs/namei.c
@@ -24,7 +24,6 @@ static int orangefs_create(struct inode *dir,
 	struct orangefs_kernel_op_s *new_op;
 	struct orangefs_object_kref ref;
 	struct inode *inode;
-	struct iattr iattr;
 	int ret;
 
 	gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n",
@@ -92,9 +91,6 @@ static int orangefs_create(struct inode *dir,
 		     dentry);
 
 	dir->i_mtime = dir->i_ctime = current_time(dir);
-	memset(&iattr, 0, sizeof iattr);
-	iattr.ia_valid |= ATTR_MTIME;
-	orangefs_inode_setattr(dir, &iattr);
 	mark_inode_dirty_sync(dir);
 	ret = 0;
 out:
@@ -231,7 +227,6 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
 	struct inode *inode = dentry->d_inode;
 	struct orangefs_inode_s *parent = ORANGEFS_I(dir);
 	struct orangefs_kernel_op_s *new_op;
-	struct iattr iattr;
 	int ret;
 
 	gossip_debug(GOSSIP_NAME_DEBUG,
@@ -272,9 +267,6 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry)
 		drop_nlink(inode);
 
 		dir->i_mtime = dir->i_ctime = current_time(dir);
-		memset(&iattr, 0, sizeof iattr);
-		iattr.ia_valid |= ATTR_MTIME;
-		orangefs_inode_setattr(dir, &iattr);
 		mark_inode_dirty_sync(dir);
 	}
 	return ret;
@@ -288,7 +280,6 @@ static int orangefs_symlink(struct inode *dir,
 	struct orangefs_kernel_op_s *new_op;
 	struct orangefs_object_kref ref;
 	struct inode *inode;
-	struct iattr iattr;
 	int mode = 755;
 	int ret;
 
@@ -363,9 +354,6 @@ static int orangefs_symlink(struct inode *dir,
 		     dentry);
 
 	dir->i_mtime = dir->i_ctime = current_time(dir);
-	memset(&iattr, 0, sizeof iattr);
-	iattr.ia_valid |= ATTR_MTIME;
-	orangefs_inode_setattr(dir, &iattr);
 	mark_inode_dirty_sync(dir);
 	ret = 0;
 out:
@@ -378,7 +366,6 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 	struct orangefs_kernel_op_s *new_op;
 	struct orangefs_object_kref ref;
 	struct inode *inode;
-	struct iattr iattr;
 	int ret;
 
 	/* Need directory updates to be on server prior to issuing op. */
@@ -444,9 +431,6 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
 	 * across clients; keep constant at 1.
 	 */
 	dir->i_mtime = dir->i_ctime = current_time(dir);
-	memset(&iattr, 0, sizeof iattr);
-	iattr.ia_valid |= ATTR_MTIME;
-	orangefs_inode_setattr(dir, &iattr);
 	mark_inode_dirty_sync(dir);
 out:
 	return ret;
@@ -530,5 +514,4 @@ const struct inode_operations orangefs_dir_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.update_time = orangefs_update_time,
 };
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 9c0b575a16e8..4cabde0a5e9f 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -407,8 +407,6 @@ int orangefs_setattr(struct dentry *dentry, struct iattr *iattr);
 int orangefs_getattr(const struct path *path, struct kstat *stat,
 		     u32 request_mask, unsigned int flags);
 
-int orangefs_update_time(struct inode *, struct timespec *, int);
-
 /*
  * defined in xattr.c
  */
diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c
index c08f81af1090..4e72f289d3de 100644
--- a/fs/orangefs/symlink.c
+++ b/fs/orangefs/symlink.c
@@ -14,5 +14,4 @@ const struct inode_operations orangefs_symlink_inode_operations = {
 	.setattr = orangefs_setattr,
 	.getattr = orangefs_getattr,
 	.listxattr = orangefs_listxattr,
-	.update_time = orangefs_update_time,
 };
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

* [PATCH 18/18] orangefs: implement xattr cache
  2017-12-12 18:34 [PATCH 00/18] orangefs: page cache Martin Brandenburg
                   ` (16 preceding siblings ...)
  2017-12-12 18:34 ` [PATCH 17/18] orangefs: no more explicit setattr Martin Brandenburg
@ 2017-12-12 18:34 ` Martin Brandenburg
  17 siblings, 0 replies; 19+ messages in thread
From: Martin Brandenburg @ 2017-12-12 18:34 UTC (permalink / raw)
  To: hubcap, devel, linux-fsdevel, linux-kernel; +Cc: Martin Brandenburg

This uses the same timeout as the getattr cache.  This substantially
increases performance when writing files with smaller buffer sizes.

When writing, the size is (often) changed, which causes a call to
notify_change which calls security_inode_need_killpriv which needs a
getxattr.  Caching it reduces traffic to the server.

Without:

$ time (dd if=/dev/zero of=/orangefs/foo bs=256 count=32768; sync)
32768+0 records in
32768+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 11.0343 s, 760 kB/s

real    0m11.788s
user    0m0.013s
sys     0m0.703s

With:

$ time (dd if=/dev/zero of=/orangefs/foo bs=256 count=32768; sync)
32768+0 records in
32768+0 records out
8388608 bytes (8.4 MB, 8.0 MiB) copied, 0.0438278 s, 191 MB/s

real    0m2.181s
user    0m0.002s
sys     0m0.048s

Signed-off-by: Martin Brandenburg <martin@martinbrandenburg.com>
---
 fs/orangefs/inode.c           |  1 +
 fs/orangefs/orangefs-kernel.h | 10 +++++++
 fs/orangefs/super.c           |  9 +++++++
 fs/orangefs/xattr.c           | 62 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 82 insertions(+)

diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c
index 66c40ac7c4ac..31d655239f09 100644
--- a/fs/orangefs/inode.c
+++ b/fs/orangefs/inode.c
@@ -164,6 +164,7 @@ static int orangefs_set_inode(struct inode *inode, void *data)
 	struct orangefs_object_kref *ref = (struct orangefs_object_kref *) data;
 	ORANGEFS_I(inode)->refn.fs_id = ref->fs_id;
 	ORANGEFS_I(inode)->refn.khandle = ref->khandle;
+	hash_init(ORANGEFS_I(inode)->xattr_cache);
 	return 0;
 }
 
diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h
index 4cabde0a5e9f..ff9a874440a5 100644
--- a/fs/orangefs/orangefs-kernel.h
+++ b/fs/orangefs/orangefs-kernel.h
@@ -211,6 +211,8 @@ struct orangefs_inode_s {
 
 	unsigned long getattr_time;
 	u32 getattr_mask;
+
+	DECLARE_HASHTABLE(xattr_cache, 4);
 };
 
 /* per superblock private orangefs info */
@@ -268,6 +270,14 @@ struct orangefs_stats {
 	unsigned long writes;
 };
 
+struct orangefs_cached_xattr {
+	struct hlist_node node;
+	char key[ORANGEFS_MAX_XATTR_NAMELEN];
+	char val[ORANGEFS_MAX_XATTR_VALUELEN];
+	ssize_t length;
+	unsigned long timeout;
+};
+
 extern struct orangefs_stats orangefs_stats;
 
 /*
diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c
index 5c1a343ba026..dd1a768e84ff 100644
--- a/fs/orangefs/super.c
+++ b/fs/orangefs/super.c
@@ -128,6 +128,15 @@ static void orangefs_i_callback(struct rcu_head *head)
 {
 	struct inode *inode = container_of(head, struct inode, i_rcu);
 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+	struct orangefs_cached_xattr *cx;
+	struct hlist_node *tmp;
+	int i;
+
+	hash_for_each_safe(orangefs_inode->xattr_cache, i, tmp, cx, node) {
+		hlist_del(&cx->node);
+		kfree(cx);
+	}
+
 	kmem_cache_free(orangefs_inode_cache, orangefs_inode);
 }
 
diff --git a/fs/orangefs/xattr.c b/fs/orangefs/xattr.c
index 03bcb871544d..dac297870d40 100644
--- a/fs/orangefs/xattr.c
+++ b/fs/orangefs/xattr.c
@@ -50,6 +50,35 @@ static inline int convert_to_internal_xattr_flags(int setxattr_flags)
 	return internal_flag;
 }
 
+static unsigned int xattr_key(const char *key)
+{
+	unsigned int i = 0;
+	while (key)
+		i += *key++;
+	return i % 16;
+}
+
+static struct orangefs_cached_xattr *find_cached_xattr(struct inode *inode,
+    const char *key)
+{
+	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
+	struct orangefs_cached_xattr *cx;
+	struct hlist_head *h;
+	struct hlist_node *tmp;
+	h = &orangefs_inode->xattr_cache[xattr_key(key)];
+	if (hlist_empty(h))
+		return NULL;
+	hlist_for_each_entry_safe(cx, tmp, h, node) {
+		if (!time_before(jiffies, cx->timeout)) {
+			hlist_del(&cx->node);
+			kfree(cx);
+			continue;
+		}
+		if (!strcmp(cx->key, key))
+			return cx;
+	}
+	return NULL;
+}
 
 /*
  * Tries to get a specified key's attributes of a given
@@ -65,6 +94,7 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
 {
 	struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
 	struct orangefs_kernel_op_s *new_op = NULL;
+	struct orangefs_cached_xattr *cx;
 	ssize_t ret = -ENOMEM;
 	ssize_t length = 0;
 	int fsuid;
@@ -93,6 +123,19 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
 
 	down_read(&orangefs_inode->xattr_sem);
 
+	cx = find_cached_xattr(inode, name);
+	if (cx) {
+		if (cx->length == -1) {
+			ret = -ENODATA;
+			goto out_unlock;
+		} else {
+			memcpy(buffer, cx->val, cx->length);
+			memset(buffer + cx->length, 0, size - cx->length);
+			ret = cx->length;
+			goto out_unlock;
+		}
+	}
+
 	new_op = op_alloc(ORANGEFS_VFS_OP_GETXATTR);
 	if (!new_op)
 		goto out_unlock;
@@ -117,6 +160,15 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
 				     " does not exist!\n",
 				     get_khandle_from_ino(inode),
 				     (char *)new_op->upcall.req.getxattr.key);
+			cx = kmalloc(sizeof *cx, GFP_KERNEL);
+			if (cx) {
+				strcpy(cx->key, name);
+				cx->length = -1;
+				cx->timeout = jiffies +
+				    orangefs_getattr_timeout_msecs*HZ/1000;
+				hash_add(orangefs_inode->xattr_cache, &cx->node,
+				    xattr_key(cx->key));
+			}
 		}
 		goto out_release_op;
 	}
@@ -156,6 +208,16 @@ ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name,
 
 	ret = length;
 
+	cx = kmalloc(sizeof *cx, GFP_KERNEL);
+	if (cx) {
+		strcpy(cx->key, name);
+		memcpy(cx->val, name, length);
+		cx->length = length;
+		cx->timeout = jiffies + HZ;
+		hash_add(orangefs_inode->xattr_cache, &cx->node,
+		    xattr_key(cx->key));
+	}
+
 out_release_op:
 	op_release(new_op);
 out_unlock:
-- 
2.15.1

^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2017-12-12 18:40 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 16/18] orangefs: implement write through the page cache Martin Brandenburg
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

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.