From: Martin Brandenburg <mar...@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 <mar...@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

Reply via email to