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