diff mbox

[13/18] orangefs: inodes linger in cache

Message ID 20171212183424.26406-14-martin@martinbrandenburg.com (mailing list archive)
State New, archived
Headers show

Commit Message

Martin Brandenburg Dec. 12, 2017, 6:34 p.m. UTC
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 mbox

Patch

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,
 };