Skip to content

Commit

Permalink
orangefs: rework posix acl handling when creating new filesystem objects
Browse files Browse the repository at this point in the history
When creating new filesytem objects orangefs used to create posix acls
after it had created and inserted a new inode. This made it necessary to
all posix_acl_chmod() on the newly created inode in case the mode of the
inode would be changed by the posix acls.

Instead of doing it this way calculate the correct mode directly before
actually creating the inode. So we first create posix acls, then pass
the mode that posix acls mandate into the orangefs getattr helper and
calculate the correct mode. This is needed so we can simply change
posix_acl_chmod() to take a dentry instead of an inode argument in the
next patch.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner (Microsoft) <brauner@kernel.org>
  • Loading branch information
Christian Brauner committed Oct 19, 2022
1 parent 9abf231 commit 4053d25
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 54 deletions.
44 changes: 2 additions & 42 deletions fs/orangefs/acl.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu)
return acl;
}

static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl,
int type)
int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
{
int error = 0;
void *value = NULL;
Expand Down Expand Up @@ -153,46 +152,7 @@ int orangefs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
rc = __orangefs_set_acl(inode, acl, type);

if (!rc && (iattr.ia_valid == ATTR_MODE))
rc = __orangefs_setattr(inode, &iattr);
rc = __orangefs_setattr_mode(inode, &iattr);

return rc;
}

int orangefs_init_acl(struct inode *inode, struct inode *dir)
{
struct posix_acl *default_acl, *acl;
umode_t mode = inode->i_mode;
struct iattr iattr;
int error = 0;

error = posix_acl_create(dir, &mode, &default_acl, &acl);
if (error)
return error;

if (default_acl) {
error = __orangefs_set_acl(inode, default_acl,
ACL_TYPE_DEFAULT);
posix_acl_release(default_acl);
} else {
inode->i_default_acl = NULL;
}

if (acl) {
if (!error)
error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
posix_acl_release(acl);
} else {
inode->i_acl = NULL;
}

/* If mode of the inode was changed, then do a forcible ->setattr */
if (mode != inode->i_mode) {
memset(&iattr, 0, sizeof iattr);
inode->i_mode = mode;
iattr.ia_mode = mode;
iattr.ia_valid |= ATTR_MODE;
__orangefs_setattr(inode, &iattr);
}

return error;
}
44 changes: 36 additions & 8 deletions fs/orangefs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -828,15 +828,22 @@ int __orangefs_setattr(struct inode *inode, struct iattr *iattr)
spin_unlock(&inode->i_lock);
mark_inode_dirty(inode);

if (iattr->ia_valid & ATTR_MODE)
/* change mod on a file that has ACLs */
ret = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);

ret = 0;
out:
return ret;
}

int __orangefs_setattr_mode(struct inode *inode, struct iattr *iattr)
{
int ret;

ret = __orangefs_setattr(inode, iattr);
/* change mode on a file that has ACLs */
if (!ret && (iattr->ia_valid & ATTR_MODE))
ret = posix_acl_chmod(&init_user_ns, inode, inode->i_mode);
return ret;
}

/*
* Change attributes of an object referenced by dentry.
*/
Expand All @@ -849,7 +856,7 @@ int orangefs_setattr(struct user_namespace *mnt_userns, struct dentry *dentry,
ret = setattr_prepare(&init_user_ns, dentry, iattr);
if (ret)
goto out;
ret = __orangefs_setattr(d_inode(dentry), iattr);
ret = __orangefs_setattr_mode(d_inode(dentry), iattr);
sync_inode_metadata(d_inode(dentry), 1);
out:
gossip_debug(GOSSIP_INODE_DEBUG, "orangefs_setattr: returning %d\n",
Expand Down Expand Up @@ -1097,8 +1104,9 @@ struct inode *orangefs_iget(struct super_block *sb,
* Allocate an inode for a newly created file and insert it into the inode hash.
*/
struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
int mode, dev_t dev, struct orangefs_object_kref *ref)
umode_t mode, dev_t dev, struct orangefs_object_kref *ref)
{
struct posix_acl *acl = NULL, *default_acl = NULL;
unsigned long hash = orangefs_handle_hash(ref);
struct inode *inode;
int error;
Expand All @@ -1115,27 +1123,47 @@ struct inode *orangefs_new_inode(struct super_block *sb, struct inode *dir,
if (!inode)
return ERR_PTR(-ENOMEM);

error = posix_acl_create(dir, &mode, &default_acl, &acl);
if (error)
goto out_iput;

orangefs_set_inode(inode, ref);
inode->i_ino = hash; /* needed for stat etc */

error = orangefs_inode_getattr(inode, ORANGEFS_GETATTR_NEW);
error = __orangefs_inode_getattr(inode, mode, ORANGEFS_GETATTR_NEW);
if (error)
goto out_iput;

orangefs_init_iops(inode);
inode->i_rdev = dev;

if (default_acl) {
error = __orangefs_set_acl(inode, default_acl,
ACL_TYPE_DEFAULT);
if (error)
goto out_iput;
}

if (acl) {
error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
if (error)
goto out_iput;
}

error = insert_inode_locked4(inode, hash, orangefs_test_inode, ref);
if (error < 0)
goto out_iput;

gossip_debug(GOSSIP_INODE_DEBUG,
"Initializing ACL's for inode %pU\n",
get_khandle_from_ino(inode));
orangefs_init_acl(inode, dir);
posix_acl_release(acl);
posix_acl_release(default_acl);
return inode;

out_iput:
iput(inode);
posix_acl_release(acl);
posix_acl_release(default_acl);
return ERR_PTR(error);
}
6 changes: 4 additions & 2 deletions fs/orangefs/orangefs-kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ enum orangefs_vfs_op_states {
#define ORANGEFS_CACHE_CREATE_FLAGS 0
#endif

extern int orangefs_init_acl(struct inode *inode, struct inode *dir);
extern const struct xattr_handler *orangefs_xattr_handlers[];

extern struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu);
extern int orangefs_set_acl(struct user_namespace *mnt_userns,
struct inode *inode, struct posix_acl *acl,
int type);
int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl, int type);

/*
* orangefs data structures
Expand Down Expand Up @@ -356,11 +356,12 @@ void fsid_key_table_finalize(void);
vm_fault_t orangefs_page_mkwrite(struct vm_fault *);
struct inode *orangefs_new_inode(struct super_block *sb,
struct inode *dir,
int mode,
umode_t mode,
dev_t dev,
struct orangefs_object_kref *ref);

int __orangefs_setattr(struct inode *, struct iattr *);
int __orangefs_setattr_mode(struct inode *inode, struct iattr *iattr);
int orangefs_setattr(struct user_namespace *, struct dentry *, struct iattr *);

int orangefs_getattr(struct user_namespace *mnt_userns, const struct path *path,
Expand Down Expand Up @@ -422,6 +423,7 @@ int orangefs_inode_setxattr(struct inode *inode,
#define ORANGEFS_GETATTR_SIZE 2

int orangefs_inode_getattr(struct inode *, int);
int __orangefs_inode_getattr(struct inode *inode, umode_t mode, int flags);

int orangefs_inode_check_changed(struct inode *inode);

Expand Down
10 changes: 8 additions & 2 deletions fs/orangefs/orangefs-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ static int orangefs_inode_is_stale(struct inode *inode,
return 0;
}

int orangefs_inode_getattr(struct inode *inode, int flags)
int __orangefs_inode_getattr(struct inode *inode, umode_t mode, int flags)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
struct orangefs_kernel_op_s *new_op;
Expand Down Expand Up @@ -369,7 +369,8 @@ int orangefs_inode_getattr(struct inode *inode, int flags)

/* special case: mark the root inode as sticky */
inode->i_mode = type | (is_root_handle(inode) ? S_ISVTX : 0) |
orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes);
orangefs_inode_perms(&new_op->downcall.resp.getattr.attributes) |
mode;

orangefs_inode->getattr_time = jiffies +
orangefs_getattr_timeout_msecs*HZ/1000;
Expand All @@ -381,6 +382,11 @@ int orangefs_inode_getattr(struct inode *inode, int flags)
return ret;
}

int orangefs_inode_getattr(struct inode *inode, int flags)
{
return __orangefs_inode_getattr(inode, 0, flags);
}

int orangefs_inode_check_changed(struct inode *inode)
{
struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode);
Expand Down

0 comments on commit 4053d25

Please sign in to comment.