diff --git a/fs/orangefs/acl.c b/fs/orangefs/acl.c index c2d8233b1e82..480ea059a680 100644 --- a/fs/orangefs/acl.c +++ b/fs/orangefs/acl.c @@ -155,13 +155,11 @@ int orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type) int orangefs_init_acl(struct inode *inode, struct inode *dir) { - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct posix_acl *default_acl, *acl; umode_t mode = inode->i_mode; + struct iattr iattr; int error = 0; - ClearModeFlag(orangefs_inode); - error = posix_acl_create(dir, &mode, &default_acl, &acl); if (error) return error; @@ -180,9 +178,11 @@ int orangefs_init_acl(struct inode *inode, struct inode *dir) /* If mode of the inode was changed, then do a forcible ->setattr */ if (mode != inode->i_mode) { - SetModeFlag(orangefs_inode); + memset(&iattr, 0, sizeof iattr); inode->i_mode = mode; - orangefs_flush_inode(inode); + iattr.ia_mode = mode; + iattr.ia_valid |= ATTR_MODE; + orangefs_inode_setattr(inode, &iattr); } return error; diff --git a/fs/orangefs/dir.c b/fs/orangefs/dir.c index a8cc588d6224..e2c2699d8016 100644 --- a/fs/orangefs/dir.c +++ b/fs/orangefs/dir.c @@ -386,7 +386,6 @@ static int orangefs_dir_release(struct inode *inode, struct file *file) { struct orangefs_dir *od = file->private_data; struct orangefs_dir_part *part = od->part; - orangefs_flush_inode(inode); while (part) { struct orangefs_dir_part *next = part->next; vfree(part); diff --git a/fs/orangefs/file.c b/fs/orangefs/file.c index e4a8e6a7eb17..1668fd645c45 100644 --- a/fs/orangefs/file.c +++ b/fs/orangefs/file.c @@ -383,9 +383,15 @@ out: if (type == ORANGEFS_IO_READ) { file_accessed(file); } else { - SetMtimeFlag(orangefs_inode); - inode->i_mtime = current_time(inode); - mark_inode_dirty_sync(inode); + file_update_time(file); + /* + * Must invalidate to ensure write loop doesn't + * prevent kernel from reading updated + * attribute. Size probably changed because of + * the write, and other clients could update + * any other attribute. + */ + orangefs_inode->getattr_time = jiffies - 1; } } @@ -615,8 +621,6 @@ static int orangefs_file_release(struct inode *inode, struct file *file) "orangefs_file_release: called on %pD\n", file); - orangefs_flush_inode(inode); - /* * remove all associated inode pages from the page cache and * readahead cache (if any); this forces an expensive refresh of @@ -666,8 +670,6 @@ static int orangefs_fsync(struct file *file, ret); op_release(new_op); - - orangefs_flush_inode(file_inode(file)); return ret; } diff --git a/fs/orangefs/inode.c b/fs/orangefs/inode.c index 28825a5b6d09..fe1d705ad91f 100644 --- a/fs/orangefs/inode.c +++ b/fs/orangefs/inode.c @@ -290,6 +290,22 @@ int orangefs_permission(struct inode *inode, int mask) return generic_permission(inode, mask); } +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, @@ -298,6 +314,7 @@ const struct inode_operations orangefs_file_inode_operations = { .getattr = orangefs_getattr, .listxattr = orangefs_listxattr, .permission = orangefs_permission, + .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 7e9e5d0ea3bc..ea6ae68e8a27 100644 --- a/fs/orangefs/namei.c +++ b/fs/orangefs/namei.c @@ -23,6 +23,7 @@ static int orangefs_create(struct inode *dir, struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; + struct iattr iattr; int ret; gossip_debug(GOSSIP_NAME_DEBUG, "%s: %pd\n", @@ -82,8 +83,10 @@ static int orangefs_create(struct inode *dir, __func__, dentry); - SetMtimeFlag(parent); 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: @@ -221,6 +224,7 @@ 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, @@ -253,8 +257,10 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry) if (!ret) { drop_nlink(inode); - SetMtimeFlag(parent); 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; @@ -267,6 +273,7 @@ static int orangefs_symlink(struct inode *dir, struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; + struct iattr iattr; int mode = 755; int ret; @@ -331,8 +338,10 @@ static int orangefs_symlink(struct inode *dir, get_khandle_from_ino(inode), dentry); - SetMtimeFlag(parent); 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: @@ -345,6 +354,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode struct orangefs_inode_s *parent = ORANGEFS_I(dir); struct orangefs_kernel_op_s *new_op; struct inode *inode; + struct iattr iattr; int ret; new_op = op_alloc(ORANGEFS_VFS_OP_MKDIR); @@ -400,8 +410,10 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode * NOTE: we have no good way to keep nlink consistent for directories * across clients; keep constant at 1. */ - SetMtimeFlag(parent); 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: op_release(new_op); @@ -470,4 +482,5 @@ const struct inode_operations orangefs_dir_inode_operations = { .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 004af348fb80..6d2bacac85f4 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -209,37 +209,10 @@ struct orangefs_inode_s { struct inode vfs_inode; sector_t last_failed_block_index_read; - /* - * State of in-memory attributes not yet flushed to disk associated - * with this object - */ - unsigned long pinode_flags; - unsigned long getattr_time; u32 getattr_mask; }; -#define P_ATIME_FLAG 0 -#define P_MTIME_FLAG 1 -#define P_CTIME_FLAG 2 -#define P_MODE_FLAG 3 - -#define ClearAtimeFlag(pinode) clear_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) -#define SetAtimeFlag(pinode) set_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) -#define AtimeFlag(pinode) test_bit(P_ATIME_FLAG, &(pinode)->pinode_flags) - -#define ClearMtimeFlag(pinode) clear_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) -#define SetMtimeFlag(pinode) set_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) -#define MtimeFlag(pinode) test_bit(P_MTIME_FLAG, &(pinode)->pinode_flags) - -#define ClearCtimeFlag(pinode) clear_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) -#define SetCtimeFlag(pinode) set_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) -#define CtimeFlag(pinode) test_bit(P_CTIME_FLAG, &(pinode)->pinode_flags) - -#define ClearModeFlag(pinode) clear_bit(P_MODE_FLAG, &(pinode)->pinode_flags) -#define SetModeFlag(pinode) set_bit(P_MODE_FLAG, &(pinode)->pinode_flags) -#define ModeFlag(pinode) test_bit(P_MODE_FLAG, &(pinode)->pinode_flags) - /* per superblock private orangefs info */ struct orangefs_sb_info_s { struct orangefs_khandle root_khandle; @@ -442,6 +415,8 @@ int orangefs_getattr(const struct path *path, struct kstat *stat, int orangefs_permission(struct inode *inode, int mask); +int orangefs_update_time(struct inode *, struct timespec *, int); + /* * defined in xattr.c */ @@ -484,8 +459,6 @@ bool __is_daemon_in_service(void); */ __s32 fsid_of_op(struct orangefs_kernel_op_s *op); -int orangefs_flush_inode(struct inode *inode); - ssize_t orangefs_inode_getxattr(struct inode *inode, const char *name, void *buffer, diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index 994a0604145a..97fe93129f38 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -438,89 +438,8 @@ int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) op_release(new_op); - /* - * successful setattr should clear the atime, mtime and - * ctime flags. - */ - if (ret == 0) { - ClearAtimeFlag(orangefs_inode); - ClearMtimeFlag(orangefs_inode); - ClearCtimeFlag(orangefs_inode); - ClearModeFlag(orangefs_inode); + if (ret == 0) orangefs_inode->getattr_time = jiffies - 1; - } - - return ret; -} - -int orangefs_flush_inode(struct inode *inode) -{ - /* - * If it is a dirty inode, this function gets called. - * Gather all the information that needs to be setattr'ed - * Right now, this will only be used for mode, atime, mtime - * and/or ctime. - */ - struct iattr wbattr; - int ret; - int mtime_flag; - int ctime_flag; - int atime_flag; - int mode_flag; - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); - - memset(&wbattr, 0, sizeof(wbattr)); - - /* - * check inode flags up front, and clear them if they are set. This - * will prevent multiple processes from all trying to flush the same - * inode if they call close() simultaneously - */ - mtime_flag = MtimeFlag(orangefs_inode); - ClearMtimeFlag(orangefs_inode); - ctime_flag = CtimeFlag(orangefs_inode); - ClearCtimeFlag(orangefs_inode); - atime_flag = AtimeFlag(orangefs_inode); - ClearAtimeFlag(orangefs_inode); - mode_flag = ModeFlag(orangefs_inode); - ClearModeFlag(orangefs_inode); - - /* -- Lazy atime,mtime and ctime update -- - * Note: all times are dictated by server in the new scheme - * and not by the clients - * - * Also mode updates are being handled now.. - */ - - if (mtime_flag) - wbattr.ia_valid |= ATTR_MTIME; - if (ctime_flag) - wbattr.ia_valid |= ATTR_CTIME; - if (atime_flag) - wbattr.ia_valid |= ATTR_ATIME; - - if (mode_flag) { - wbattr.ia_mode = inode->i_mode; - wbattr.ia_valid |= ATTR_MODE; - } - - gossip_debug(GOSSIP_UTILS_DEBUG, - "*********** orangefs_flush_inode: %pU " - "(ia_valid %d)\n", - get_khandle_from_ino(inode), - wbattr.ia_valid); - if (wbattr.ia_valid == 0) { - gossip_debug(GOSSIP_UTILS_DEBUG, - "orangefs_flush_inode skipping setattr()\n"); - return 0; - } - - gossip_debug(GOSSIP_UTILS_DEBUG, - "orangefs_flush_inode (%pU) writing mode %o\n", - get_khandle_from_ino(inode), - inode->i_mode); - - ret = orangefs_inode_setattr(inode, &wbattr); return ret; } diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index 43df511e69f2..366750eef201 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -117,7 +117,6 @@ static struct inode *orangefs_alloc_inode(struct super_block *sb) orangefs_inode->refn.fs_id = ORANGEFS_FS_ID_NULL; orangefs_inode->last_failed_block_index_read = 0; memset(orangefs_inode->link_target, 0, sizeof(orangefs_inode->link_target)); - orangefs_inode->pinode_flags = 0; gossip_debug(GOSSIP_SUPER_DEBUG, "orangefs_alloc_inode: allocated %p\n", @@ -297,21 +296,9 @@ void fsid_key_table_finalize(void) { } -/* Called whenever the VFS dirties the inode in response to atime updates */ -static void orangefs_dirty_inode(struct inode *inode, int flags) -{ - struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); - - gossip_debug(GOSSIP_SUPER_DEBUG, - "orangefs_dirty_inode: %pU\n", - get_khandle_from_ino(inode)); - SetAtimeFlag(orangefs_inode); -} - static const struct super_operations orangefs_s_ops = { .alloc_inode = orangefs_alloc_inode, .destroy_inode = orangefs_destroy_inode, - .dirty_inode = orangefs_dirty_inode, .drop_inode = generic_delete_inode, .statfs = orangefs_statfs, .remount_fs = orangefs_remount_fs, diff --git a/fs/orangefs/symlink.c b/fs/orangefs/symlink.c index d856cdf91763..db107fe91ab3 100644 --- a/fs/orangefs/symlink.c +++ b/fs/orangefs/symlink.c @@ -15,4 +15,5 @@ const struct inode_operations orangefs_symlink_inode_operations = { .getattr = orangefs_getattr, .listxattr = orangefs_listxattr, .permission = orangefs_permission, + .update_time = orangefs_update_time, };