Commit ad77dbce authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Eric Van Hensbergen

fs/9p: Implement create time inheritance

Inherit default ACL on create
Signed-off-by: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarVenkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 6e8dc555
...@@ -152,6 +152,58 @@ int v9fs_acl_chmod(struct dentry *dentry) ...@@ -152,6 +152,58 @@ int v9fs_acl_chmod(struct dentry *dentry)
return retval; return retval;
} }
int v9fs_set_create_acl(struct dentry *dentry,
struct posix_acl *dpacl, struct posix_acl *pacl)
{
if (dpacl)
v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, dpacl);
if (pacl)
v9fs_set_acl(dentry, ACL_TYPE_ACCESS, pacl);
posix_acl_release(dpacl);
posix_acl_release(pacl);
return 0;
}
int v9fs_acl_mode(struct inode *dir, mode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl)
{
int retval = 0;
mode_t mode = *modep;
struct posix_acl *acl = NULL;
if (!S_ISLNK(mode)) {
acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT);
if (IS_ERR(acl))
return PTR_ERR(acl);
if (!acl)
mode &= ~current_umask();
}
if (acl) {
struct posix_acl *clone;
if (S_ISDIR(mode))
*dpacl = acl;
clone = posix_acl_clone(acl, GFP_NOFS);
retval = -ENOMEM;
if (!clone)
goto cleanup;
retval = posix_acl_create_masq(clone, &mode);
if (retval < 0) {
posix_acl_release(clone);
goto cleanup;
}
if (retval > 0)
*pacl = clone;
}
*modep = mode;
return 0;
cleanup:
posix_acl_release(acl);
return retval;
}
static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name,
void *buffer, size_t size, int type) void *buffer, size_t size, int type)
{ {
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
extern int v9fs_get_acl(struct inode *, struct p9_fid *); extern int v9fs_get_acl(struct inode *, struct p9_fid *);
extern int v9fs_check_acl(struct inode *inode, int mask); extern int v9fs_check_acl(struct inode *inode, int mask);
extern int v9fs_acl_chmod(struct dentry *); extern int v9fs_acl_chmod(struct dentry *);
extern int v9fs_set_create_acl(struct dentry *,
struct posix_acl *, struct posix_acl *);
extern int v9fs_acl_mode(struct inode *dir, mode_t *modep,
struct posix_acl **dpacl, struct posix_acl **pacl);
#else #else
#define v9fs_check_acl NULL #define v9fs_check_acl NULL
static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid)
...@@ -28,5 +32,18 @@ static inline int v9fs_acl_chmod(struct dentry *dentry) ...@@ -28,5 +32,18 @@ static inline int v9fs_acl_chmod(struct dentry *dentry)
{ {
return 0; return 0;
} }
static inline int v9fs_set_create_acl(struct dentry *dentry,
struct posix_acl *dpacl,
struct posix_acl *pacl)
{
return 0;
}
static inline int v9fs_acl_mode(struct inode *dir, mode_t *modep,
struct posix_acl **dpacl,
struct posix_acl **pacl)
{
return 0;
}
#endif #endif
#endif /* FS_9P_XATTR_H */ #endif /* FS_9P_XATTR_H */
...@@ -662,19 +662,21 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, ...@@ -662,19 +662,21 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
*/ */
static int static int
v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
struct nameidata *nd) struct nameidata *nd)
{ {
int err = 0; int err = 0;
char *name = NULL; char *name = NULL;
gid_t gid; gid_t gid;
int flags; int flags;
mode_t mode;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL; struct p9_fid *fid = NULL;
struct p9_fid *dfid, *ofid; struct p9_fid *dfid, *ofid;
struct file *filp; struct file *filp;
struct p9_qid qid; struct p9_qid qid;
struct inode *inode; struct inode *inode;
struct posix_acl *pacl = NULL, *dacl = NULL;
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);
if (nd && nd->flags & LOOKUP_OPEN) if (nd && nd->flags & LOOKUP_OPEN)
...@@ -684,7 +686,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, ...@@ -684,7 +686,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
name = (char *) dentry->d_name.name; name = (char *) dentry->d_name.name;
P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x " P9_DPRINTK(P9_DEBUG_VFS, "v9fs_vfs_create_dotl: name:%s flags:0x%x "
"mode:0x%x\n", name, flags, mode); "mode:0x%x\n", name, flags, omode);
dfid = v9fs_fid_lookup(dentry->d_parent); dfid = v9fs_fid_lookup(dentry->d_parent);
if (IS_ERR(dfid)) { if (IS_ERR(dfid)) {
...@@ -702,6 +704,15 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, ...@@ -702,6 +704,15 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
} }
gid = v9fs_get_fsgid_for_create(dir); gid = v9fs_get_fsgid_for_create(dir);
mode = omode;
/* Update mode based on ACL value */
err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
if (err) {
P9_DPRINTK(P9_DEBUG_VFS,
"Failed to get acl values in creat %d\n", err);
goto error;
}
err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid); err = p9_client_create_dotl(ofid, name, flags, mode, gid, &qid);
if (err < 0) { if (err < 0) {
P9_DPRINTK(P9_DEBUG_VFS, P9_DPRINTK(P9_DEBUG_VFS,
...@@ -709,42 +720,48 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode, ...@@ -709,42 +720,48 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int mode,
err); err);
goto error; goto error;
} }
/* instantiate inode and assign the unopened fid to the dentry */
if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE ||
(nd && nd->flags & LOOKUP_OPEN)) {
fid = p9_client_walk(dfid, 1, &name, 1);
if (IS_ERR(fid)) {
err = PTR_ERR(fid);
P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n",
err);
fid = NULL;
goto error;
}
/* No need to populate the inode if we are not opening the file AND inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
* not in cached mode. if (IS_ERR(inode)) {
*/ err = PTR_ERR(inode);
if (!v9ses->cache && !(nd && nd->flags & LOOKUP_OPEN)) { P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
/* Not in cached mode. No need to populate inode with stat */ err);
dentry->d_op = &v9fs_dentry_operations; goto error;
p9_client_clunk(ofid); }
d_instantiate(dentry, NULL);
return 0;
}
/* Now walk from the parent so we can get an unopened fid. */
fid = p9_client_walk(dfid, 1, &name, 1);
if (IS_ERR(fid)) {
err = PTR_ERR(fid);
P9_DPRINTK(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
fid = NULL;
goto error;
}
/* instantiate inode and assign the unopened fid to dentry */
inode = v9fs_inode_from_fid(v9ses, fid, dir->i_sb);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
goto error;
}
if (v9ses->cache)
dentry->d_op = &v9fs_cached_dentry_operations; dentry->d_op = &v9fs_cached_dentry_operations;
else d_instantiate(dentry, inode);
err = v9fs_fid_add(dentry, fid);
if (err < 0)
goto error;
/* The fid would get clunked via a dput */
fid = NULL;
} else {
/*
* Not in cached mode. No need to populate
* inode with stat. We need to get an inode
* so that we can set the acl with dentry
*/
inode = v9fs_get_inode(dir->i_sb, mode);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto error;
}
dentry->d_op = &v9fs_dentry_operations; dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
err = v9fs_fid_add(dentry, fid); }
if (err < 0) /* Now set the ACL based on the default value */
goto error; v9fs_set_create_acl(dentry, dacl, pacl);
/* if we are opening a file, assign the open fid to the file */ /* if we are opening a file, assign the open fid to the file */
if (nd && nd->flags & LOOKUP_OPEN) { if (nd && nd->flags & LOOKUP_OPEN) {
...@@ -866,25 +883,28 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) ...@@ -866,25 +883,28 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
* *
*/ */
static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, static int v9fs_vfs_mkdir_dotl(struct inode *dir,
int mode) struct dentry *dentry, int omode)
{ {
int err; int err;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL; struct p9_fid *fid = NULL, *dfid = NULL;
gid_t gid; gid_t gid;
char *name; char *name;
mode_t mode;
struct inode *inode; struct inode *inode;
struct p9_qid qid; struct p9_qid qid;
struct dentry *dir_dentry; struct dentry *dir_dentry;
struct posix_acl *dacl = NULL, *pacl = NULL;
P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name);
err = 0; err = 0;
v9ses = v9fs_inode2v9ses(dir); v9ses = v9fs_inode2v9ses(dir);
mode |= S_IFDIR; omode |= S_IFDIR;
if (dir->i_mode & S_ISGID) if (dir->i_mode & S_ISGID)
mode |= S_ISGID; omode |= S_ISGID;
dir_dentry = v9fs_dentry_from_dir_inode(dir); dir_dentry = v9fs_dentry_from_dir_inode(dir);
dfid = v9fs_fid_lookup(dir_dentry); dfid = v9fs_fid_lookup(dir_dentry);
if (IS_ERR(dfid)) { if (IS_ERR(dfid)) {
...@@ -895,7 +915,14 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, ...@@ -895,7 +915,14 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
} }
gid = v9fs_get_fsgid_for_create(dir); gid = v9fs_get_fsgid_for_create(dir);
mode = omode;
/* Update mode based on ACL value */
err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
if (err) {
P9_DPRINTK(P9_DEBUG_VFS,
"Failed to get acl values in mkdir %d\n", err);
goto error;
}
name = (char *) dentry->d_name.name; name = (char *) dentry->d_name.name;
err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid);
if (err < 0) if (err < 0)
...@@ -925,7 +952,23 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry, ...@@ -925,7 +952,23 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, struct dentry *dentry,
if (err < 0) if (err < 0)
goto error; goto error;
fid = NULL; fid = NULL;
} else {
/*
* Not in cached mode. No need to populate
* inode with stat. We need to get an inode
* so that we can set the acl with dentry
*/
inode = v9fs_get_inode(dir->i_sb, mode);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
goto error;
}
dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode);
} }
/* Now set the ACL based on the default value */
v9fs_set_create_acl(dentry, dacl, pacl);
error: error:
if (fid) if (fid)
p9_client_clunk(fid); p9_client_clunk(fid);
...@@ -1861,21 +1904,23 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev) ...@@ -1861,21 +1904,23 @@ v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t rdev)
* *
*/ */
static int static int
v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
dev_t rdev) dev_t rdev)
{ {
int err; int err;
char *name; char *name;
mode_t mode;
struct v9fs_session_info *v9ses; struct v9fs_session_info *v9ses;
struct p9_fid *fid = NULL, *dfid = NULL; struct p9_fid *fid = NULL, *dfid = NULL;
struct inode *inode; struct inode *inode;
gid_t gid; gid_t gid;
struct p9_qid qid; struct p9_qid qid;
struct dentry *dir_dentry; struct dentry *dir_dentry;
struct posix_acl *dacl = NULL, *pacl = NULL;
P9_DPRINTK(P9_DEBUG_VFS, P9_DPRINTK(P9_DEBUG_VFS,
" %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, " %lu,%s mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino,
dentry->d_name.name, mode, MAJOR(rdev), MINOR(rdev)); dentry->d_name.name, omode, MAJOR(rdev), MINOR(rdev));
if (!new_valid_dev(rdev)) if (!new_valid_dev(rdev))
return -EINVAL; return -EINVAL;
...@@ -1891,7 +1936,14 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, ...@@ -1891,7 +1936,14 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
} }
gid = v9fs_get_fsgid_for_create(dir); gid = v9fs_get_fsgid_for_create(dir);
mode = omode;
/* Update mode based on ACL value */
err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
if (err) {
P9_DPRINTK(P9_DEBUG_VFS,
"Failed to get acl values in mknod %d\n", err);
goto error;
}
name = (char *) dentry->d_name.name; name = (char *) dentry->d_name.name;
err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid);
...@@ -1935,7 +1987,8 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode, ...@@ -1935,7 +1987,8 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int mode,
dentry->d_op = &v9fs_dentry_operations; dentry->d_op = &v9fs_dentry_operations;
d_instantiate(dentry, inode); d_instantiate(dentry, inode);
} }
/* Now set the ACL based on the default value */
v9fs_set_create_acl(dentry, dacl, pacl);
error: error:
if (fid) if (fid)
p9_client_clunk(fid); p9_client_clunk(fid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment