From afd9fb2a31797b4c787034294a4062df0c19c37e Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 13 Feb 2018 20:13:46 +0000 Subject: orangefs: reorganize setattr functions to track attribute changes OrangeFS accepts a mask indicating which attributes were changed. The kernel must not set any bits except those that were actually changed. The kernel must set the uid/gid of the request to the actual uid/gid responsible for the change. Code path for notify_change initiated setattrs is orangefs_setattr(dentry, iattr) -> __orangefs_setattr(inode, iattr) In kernel changes are initiated by calling __orangefs_setattr. Code path for writeback is orangefs_write_inode -> orangefs_inode_setattr attr_valid and attr_uid and attr_gid change together under i_lock. I_DIRTY changes separately. __orangefs_setattr lock if needs to be cleaned first, unlock and retry set attr_valid copy data in unlock mark_inode_dirty orangefs_inode_setattr lock copy attributes out unlock clear getattr_time # __writeback_single_inode clears dirty orangefs_inode_getattr # possible to get here with attr_valid set and not dirty lock if getattr_time ok or attr_valid set, unlock and return unlock do server operation # another thread may getattr or setattr, so check for that lock if getattr_time ok or attr_valid, unlock and return else, copy in update getattr_time unlock Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-utils.c | 114 +++++++++++++++++-------------------------- 1 file changed, 44 insertions(+), 70 deletions(-) (limited to 'fs/orangefs/orangefs-utils.c') diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index d44cbe96719a..a4fac527f85d 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -136,51 +136,37 @@ static int orangefs_inode_perms(struct ORANGEFS_sys_attr_s *attrs) * NOTE: in kernel land, we never use the sys_attr->link_target for * anything, so don't bother copying it into the sys_attr object here. */ -static inline int copy_attributes_from_inode(struct inode *inode, - struct ORANGEFS_sys_attr_s *attrs, - struct iattr *iattr) +static inline void copy_attributes_from_inode(struct inode *inode, + struct ORANGEFS_sys_attr_s *attrs) { - umode_t tmp_mode; - - if (!iattr || !inode || !attrs) { - gossip_err("NULL iattr (%p), inode (%p), attrs (%p) " - "in copy_attributes_from_inode!\n", - iattr, - inode, - attrs); - return -EINVAL; - } - /* - * We need to be careful to only copy the attributes out of the - * iattr object that we know are valid. - */ + struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); attrs->mask = 0; - if (iattr->ia_valid & ATTR_UID) { - attrs->owner = from_kuid(&init_user_ns, iattr->ia_uid); + if (orangefs_inode->attr_valid & ATTR_UID) { + attrs->owner = from_kuid(&init_user_ns, inode->i_uid); attrs->mask |= ORANGEFS_ATTR_SYS_UID; gossip_debug(GOSSIP_UTILS_DEBUG, "(UID) %d\n", attrs->owner); } - if (iattr->ia_valid & ATTR_GID) { - attrs->group = from_kgid(&init_user_ns, iattr->ia_gid); + if (orangefs_inode->attr_valid & ATTR_GID) { + attrs->group = from_kgid(&init_user_ns, inode->i_gid); attrs->mask |= ORANGEFS_ATTR_SYS_GID; gossip_debug(GOSSIP_UTILS_DEBUG, "(GID) %d\n", attrs->group); } - if (iattr->ia_valid & ATTR_ATIME) { + if (orangefs_inode->attr_valid & ATTR_ATIME) { attrs->mask |= ORANGEFS_ATTR_SYS_ATIME; - if (iattr->ia_valid & ATTR_ATIME_SET) { - attrs->atime = (time64_t)iattr->ia_atime.tv_sec; + if (orangefs_inode->attr_valid & ATTR_ATIME_SET) { + attrs->atime = (time64_t)inode->i_atime.tv_sec; attrs->mask |= ORANGEFS_ATTR_SYS_ATIME_SET; } } - if (iattr->ia_valid & ATTR_MTIME) { + if (orangefs_inode->attr_valid & ATTR_MTIME) { attrs->mask |= ORANGEFS_ATTR_SYS_MTIME; - if (iattr->ia_valid & ATTR_MTIME_SET) { - attrs->mtime = (time64_t)iattr->ia_mtime.tv_sec; + if (orangefs_inode->attr_valid & ATTR_MTIME_SET) { + attrs->mtime = (time64_t)inode->i_mtime.tv_sec; attrs->mask |= ORANGEFS_ATTR_SYS_MTIME_SET; } } - if (iattr->ia_valid & ATTR_CTIME) + if (orangefs_inode->attr_valid & ATTR_CTIME) attrs->mask |= ORANGEFS_ATTR_SYS_CTIME; /* @@ -189,36 +175,10 @@ static inline int copy_attributes_from_inode(struct inode *inode, * worry about ATTR_SIZE */ - if (iattr->ia_valid & ATTR_MODE) { - tmp_mode = iattr->ia_mode; - if (tmp_mode & (S_ISVTX)) { - if (is_root_handle(inode)) { - /* - * allow sticky bit to be set on root (since - * it shows up that way by default anyhow), - * but don't show it to the server - */ - tmp_mode -= S_ISVTX; - } else { - gossip_debug(GOSSIP_UTILS_DEBUG, - "%s: setting sticky bit not supported.\n", - __func__); - return -EINVAL; - } - } - - if (tmp_mode & (S_ISUID)) { - gossip_debug(GOSSIP_UTILS_DEBUG, - "%s: setting setuid bit not supported.\n", - __func__); - return -EINVAL; - } - - attrs->perms = ORANGEFS_util_translate_mode(tmp_mode); + if (orangefs_inode->attr_valid & ATTR_MODE) { + attrs->perms = ORANGEFS_util_translate_mode(inode->i_mode); attrs->mask |= ORANGEFS_ATTR_SYS_PERM; } - - return 0; } static int orangefs_inode_type(enum orangefs_ds_type objtype) @@ -283,10 +243,16 @@ int orangefs_inode_getattr(struct inode *inode, int flags) gossip_debug(GOSSIP_UTILS_DEBUG, "%s: called on inode %pU flags %d\n", __func__, get_khandle_from_ino(inode), flags); +again: spin_lock(&inode->i_lock); /* Must have all the attributes in the mask and be within cache time. */ if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) || - inode->i_state & I_DIRTY) { + orangefs_inode->attr_valid) { + if (orangefs_inode->attr_valid) { + spin_unlock(&inode->i_lock); + write_inode_now(inode, 1); + goto again; + } spin_unlock(&inode->i_lock); return 0; } @@ -311,10 +277,16 @@ int orangefs_inode_getattr(struct inode *inode, int flags) if (ret != 0) goto out; +again2: spin_lock(&inode->i_lock); /* Must have all the attributes in the mask and be within cache time. */ if ((!flags && time_before(jiffies, orangefs_inode->getattr_time)) || - inode->i_state & I_DIRTY) { + orangefs_inode->attr_valid) { + if (orangefs_inode->attr_valid) { + spin_unlock(&inode->i_lock); + write_inode_now(inode, 1); + goto again2; + } gossip_debug(GOSSIP_UTILS_DEBUG, "%s: in cache or dirty\n", __func__); ret = 0; @@ -438,7 +410,7 @@ out: * issues a orangefs setattr request to make sure the new attribute values * take effect if successful. returns 0 on success; -errno otherwise */ -int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) +int orangefs_inode_setattr(struct inode *inode) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); struct orangefs_kernel_op_s *new_op; @@ -448,24 +420,26 @@ int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) if (!new_op) return -ENOMEM; + spin_lock(&inode->i_lock); + new_op->upcall.uid = from_kuid(&init_user_ns, orangefs_inode->attr_uid); + new_op->upcall.gid = from_kgid(&init_user_ns, orangefs_inode->attr_gid); new_op->upcall.req.setattr.refn = orangefs_inode->refn; - ret = copy_attributes_from_inode(inode, - &new_op->upcall.req.setattr.attributes, - iattr); - if (ret >= 0) { - ret = service_operation(new_op, __func__, - get_interruptible_flag(inode)); + copy_attributes_from_inode(inode, + &new_op->upcall.req.setattr.attributes); + orangefs_inode->attr_valid = 0; + spin_unlock(&inode->i_lock); - gossip_debug(GOSSIP_UTILS_DEBUG, - "orangefs_inode_setattr: returning %d\n", - ret); - } + ret = service_operation(new_op, __func__, + get_interruptible_flag(inode)); + gossip_debug(GOSSIP_UTILS_DEBUG, + "orangefs_inode_setattr: returning %d\n", ret); + if (ret) + orangefs_make_bad_inode(inode); op_release(new_op); if (ret == 0) orangefs_inode->getattr_time = jiffies - 1; - return ret; } -- cgit v1.2.3