[PATCH 13/18] orangefs: inodes linger in cache

From: Martin Brandenburg
Date: Tue Dec 12 2017 - 13:35:17 EST


From: Martin Brandenburg <martin@xxxxxxxxxxxx>

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@xxxxxxxxxxxx>
---
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