mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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 <martin@omnibond.com> Signed-off-by: Mike Marshall <hubcap@omnibond.com>
This commit is contained in:
parent
df2d7337b5
commit
afd9fb2a31
6 changed files with 129 additions and 119 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue