aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/9p/acl.c74
-rw-r--r--fs/9p/v9fs_vfs.h1
-rw-r--r--fs/9p/vfs_inode.c2
3 files changed, 75 insertions, 2 deletions
diff --git a/fs/9p/acl.c b/fs/9p/acl.c
index 4293b4599ff6..cad38bc1710e 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -17,9 +17,11 @@
17#include <net/9p/9p.h> 17#include <net/9p/9p.h>
18#include <net/9p/client.h> 18#include <net/9p/client.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/sched.h>
20#include <linux/posix_acl_xattr.h> 21#include <linux/posix_acl_xattr.h>
21#include "xattr.h" 22#include "xattr.h"
22#include "acl.h" 23#include "acl.h"
24#include "v9fs_vfs.h"
23 25
24static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) 26static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name)
25{ 27{
@@ -119,7 +121,77 @@ static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name,
119 const void *value, size_t size, 121 const void *value, size_t size,
120 int flags, int type) 122 int flags, int type)
121{ 123{
122 return 0; 124 int retval;
125 struct posix_acl *acl;
126 struct inode *inode = dentry->d_inode;
127
128 if (strcmp(name, "") != 0)
129 return -EINVAL;
130 if (S_ISLNK(inode->i_mode))
131 return -EOPNOTSUPP;
132 if (!is_owner_or_cap(inode))
133 return -EPERM;
134 if (value) {
135 /* update the cached acl value */
136 acl = posix_acl_from_xattr(value, size);
137 if (IS_ERR(acl))
138 return PTR_ERR(acl);
139 else if (acl) {
140 retval = posix_acl_valid(acl);
141 if (retval)
142 goto err_out;
143 }
144 } else
145 acl = NULL;
146
147 switch (type) {
148 case ACL_TYPE_ACCESS:
149 name = POSIX_ACL_XATTR_ACCESS;
150 if (acl) {
151 mode_t mode = inode->i_mode;
152 retval = posix_acl_equiv_mode(acl, &mode);
153 if (retval < 0)
154 goto err_out;
155 else {
156 struct iattr iattr;
157 if (retval == 0) {
158 /*
159 * ACL can be represented
160 * by the mode bits. So don't
161 * update ACL.
162 */
163 acl = NULL;
164 value = NULL;
165 size = 0;
166 }
167 /* Updte the mode bits */
168 iattr.ia_mode = ((mode & S_IALLUGO) |
169 (inode->i_mode & ~S_IALLUGO));
170 iattr.ia_valid = ATTR_MODE;
171 /* FIXME should we update ctime ?
172 * What is the following setxattr update the
173 * mode ?
174 */
175 v9fs_vfs_setattr_dotl(dentry, &iattr);
176 }
177 }
178 break;
179 case ACL_TYPE_DEFAULT:
180 name = POSIX_ACL_XATTR_DEFAULT;
181 if (!S_ISDIR(inode->i_mode)) {
182 retval = -EINVAL;
183 goto err_out;
184 }
185 break;
186 default:
187 BUG();
188 }
189 retval = v9fs_xattr_set(dentry, name, value, size, flags);
190 if (!retval)
191 set_cached_acl(inode, type, acl);
192err_out:
193 posix_acl_release(acl);
194 return retval;
123} 195}
124 196
125const struct xattr_handler v9fs_xattr_acl_access_handler = { 197const struct xattr_handler v9fs_xattr_acl_access_handler = {
diff --git a/fs/9p/v9fs_vfs.h b/fs/9p/v9fs_vfs.h
index 88418c419ea7..09861295eef9 100644
--- a/fs/9p/v9fs_vfs.h
+++ b/fs/9p/v9fs_vfs.h
@@ -64,3 +64,4 @@ int v9fs_uflags2omode(int uflags, int extended);
64 64
65ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); 65ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64);
66void v9fs_blank_wstat(struct p9_wstat *wstat); 66void v9fs_blank_wstat(struct p9_wstat *wstat);
67int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 1249b8323961..4b67bf1fb1d5 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1242,7 +1242,7 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr)
1242 * 1242 *
1243 */ 1243 */
1244 1244
1245static int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) 1245int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr)
1246{ 1246{
1247 int retval; 1247 int retval;
1248 struct v9fs_session_info *v9ses; 1248 struct v9fs_session_info *v9ses;