]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - fs/aufs/xattr.c
UBUNTU: SAUCE: Import aufs driver
[mirror_ubuntu-zesty-kernel.git] / fs / aufs / xattr.c
1 /*
2 * Copyright (C) 2014-2016 Junjiro R. Okajima
3 *
4 * This program, aufs is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 /*
19 * handling xattr functions
20 */
21
22 #include <linux/xattr.h>
23 #include "aufs.h"
24
25 static int au_xattr_ignore(int err, char *name, unsigned int ignore_flags)
26 {
27 if (!ignore_flags)
28 goto out;
29 switch (err) {
30 case -ENOMEM:
31 case -EDQUOT:
32 goto out;
33 }
34
35 if ((ignore_flags & AuBrAttr_ICEX) == AuBrAttr_ICEX) {
36 err = 0;
37 goto out;
38 }
39
40 #define cmp(brattr, prefix) do { \
41 if (!strncmp(name, XATTR_##prefix##_PREFIX, \
42 XATTR_##prefix##_PREFIX_LEN)) { \
43 if (ignore_flags & AuBrAttr_ICEX_##brattr) \
44 err = 0; \
45 goto out; \
46 } \
47 } while (0)
48
49 cmp(SEC, SECURITY);
50 cmp(SYS, SYSTEM);
51 cmp(TR, TRUSTED);
52 cmp(USR, USER);
53 #undef cmp
54
55 if (ignore_flags & AuBrAttr_ICEX_OTH)
56 err = 0;
57
58 out:
59 return err;
60 }
61
62 static const int au_xattr_out_of_list = AuBrAttr_ICEX_OTH << 1;
63
64 static int au_do_cpup_xattr(struct dentry *h_dst, struct dentry *h_src,
65 char *name, char **buf, unsigned int ignore_flags,
66 unsigned int verbose)
67 {
68 int err;
69 ssize_t ssz;
70 struct inode *h_idst;
71
72 ssz = vfs_getxattr_alloc(h_src, name, buf, 0, GFP_NOFS);
73 err = ssz;
74 if (unlikely(err <= 0)) {
75 if (err == -ENODATA
76 || (err == -EOPNOTSUPP
77 && ((ignore_flags & au_xattr_out_of_list)
78 || (au_test_nfs_noacl(d_inode(h_src))
79 && (!strcmp(name, XATTR_NAME_POSIX_ACL_ACCESS)
80 || !strcmp(name,
81 XATTR_NAME_POSIX_ACL_DEFAULT))))
82 ))
83 err = 0;
84 if (err && (verbose || au_debug_test()))
85 pr_err("%s, err %d\n", name, err);
86 goto out;
87 }
88
89 /* unlock it temporary */
90 h_idst = d_inode(h_dst);
91 inode_unlock(h_idst);
92 err = vfsub_setxattr(h_dst, name, *buf, ssz, /*flags*/0);
93 inode_lock_nested(h_idst, AuLsc_I_CHILD2);
94 if (unlikely(err)) {
95 if (verbose || au_debug_test())
96 pr_err("%s, err %d\n", name, err);
97 err = au_xattr_ignore(err, name, ignore_flags);
98 }
99
100 out:
101 return err;
102 }
103
104 int au_cpup_xattr(struct dentry *h_dst, struct dentry *h_src, int ignore_flags,
105 unsigned int verbose)
106 {
107 int err, unlocked, acl_access, acl_default;
108 ssize_t ssz;
109 struct inode *h_isrc, *h_idst;
110 char *value, *p, *o, *e;
111
112 /* try stopping to update the source inode while we are referencing */
113 /* there should not be the parent-child relationship between them */
114 h_isrc = d_inode(h_src);
115 h_idst = d_inode(h_dst);
116 inode_unlock(h_idst);
117 inode_lock_nested(h_isrc, AuLsc_I_CHILD);
118 inode_lock_nested(h_idst, AuLsc_I_CHILD2);
119 unlocked = 0;
120
121 /* some filesystems don't list POSIX ACL, for example tmpfs */
122 ssz = vfs_listxattr(h_src, NULL, 0);
123 err = ssz;
124 if (unlikely(err < 0)) {
125 AuTraceErr(err);
126 if (err == -ENODATA
127 || err == -EOPNOTSUPP)
128 err = 0; /* ignore */
129 goto out;
130 }
131
132 err = 0;
133 p = NULL;
134 o = NULL;
135 if (ssz) {
136 err = -ENOMEM;
137 p = kmalloc(ssz, GFP_NOFS);
138 o = p;
139 if (unlikely(!p))
140 goto out;
141 err = vfs_listxattr(h_src, p, ssz);
142 }
143 inode_unlock(h_isrc);
144 unlocked = 1;
145 AuDbg("err %d, ssz %zd\n", err, ssz);
146 if (unlikely(err < 0))
147 goto out_free;
148
149 err = 0;
150 e = p + ssz;
151 value = NULL;
152 acl_access = 0;
153 acl_default = 0;
154 while (!err && p < e) {
155 acl_access |= !strncmp(p, XATTR_NAME_POSIX_ACL_ACCESS,
156 sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1);
157 acl_default |= !strncmp(p, XATTR_NAME_POSIX_ACL_DEFAULT,
158 sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)
159 - 1);
160 err = au_do_cpup_xattr(h_dst, h_src, p, &value, ignore_flags,
161 verbose);
162 p += strlen(p) + 1;
163 }
164 AuTraceErr(err);
165 ignore_flags |= au_xattr_out_of_list;
166 if (!err && !acl_access) {
167 err = au_do_cpup_xattr(h_dst, h_src,
168 XATTR_NAME_POSIX_ACL_ACCESS, &value,
169 ignore_flags, verbose);
170 AuTraceErr(err);
171 }
172 if (!err && !acl_default) {
173 err = au_do_cpup_xattr(h_dst, h_src,
174 XATTR_NAME_POSIX_ACL_DEFAULT, &value,
175 ignore_flags, verbose);
176 AuTraceErr(err);
177 }
178
179 if (value)
180 au_delayed_kfree(value);
181
182 out_free:
183 if (o)
184 au_delayed_kfree(o);
185 out:
186 if (!unlocked)
187 inode_unlock(h_isrc);
188 AuTraceErr(err);
189 return err;
190 }
191
192 /* ---------------------------------------------------------------------- */
193
194 enum {
195 AU_XATTR_LIST,
196 AU_XATTR_GET
197 };
198
199 struct au_lgxattr {
200 int type;
201 union {
202 struct {
203 char *list;
204 size_t size;
205 } list;
206 struct {
207 const char *name;
208 void *value;
209 size_t size;
210 } get;
211 } u;
212 };
213
214 static ssize_t au_lgxattr(struct dentry *dentry, struct au_lgxattr *arg)
215 {
216 ssize_t err;
217 struct path h_path;
218 struct super_block *sb;
219
220 sb = dentry->d_sb;
221 err = si_read_lock(sb, AuLock_FLUSH | AuLock_NOPLM);
222 if (unlikely(err))
223 goto out;
224 err = au_h_path_getattr(dentry, /*force*/1, &h_path);
225 if (unlikely(err))
226 goto out_si;
227 if (unlikely(!h_path.dentry))
228 /* illegally overlapped or something */
229 goto out_di; /* pretending success */
230
231 /* always topmost entry only */
232 switch (arg->type) {
233 case AU_XATTR_LIST:
234 err = vfs_listxattr(h_path.dentry,
235 arg->u.list.list, arg->u.list.size);
236 break;
237 case AU_XATTR_GET:
238 AuDebugOn(d_is_negative(h_path.dentry));
239 err = vfs_getxattr(h_path.dentry,
240 arg->u.get.name, arg->u.get.value,
241 arg->u.get.size);
242 break;
243 }
244
245 out_di:
246 di_read_unlock(dentry, AuLock_IR);
247 out_si:
248 si_read_unlock(sb);
249 out:
250 AuTraceErr(err);
251 return err;
252 }
253
254 ssize_t aufs_listxattr(struct dentry *dentry, char *list, size_t size)
255 {
256 struct au_lgxattr arg = {
257 .type = AU_XATTR_LIST,
258 .u.list = {
259 .list = list,
260 .size = size
261 },
262 };
263
264 return au_lgxattr(dentry, &arg);
265 }
266
267 ssize_t aufs_getxattr(struct dentry *dentry, struct inode *inode __maybe_unused,
268 const char *name, void *value, size_t size)
269 {
270 struct au_lgxattr arg = {
271 .type = AU_XATTR_GET,
272 .u.get = {
273 .name = name,
274 .value = value,
275 .size = size
276 },
277 };
278
279 return au_lgxattr(dentry, &arg);
280 }
281
282 int aufs_setxattr(struct dentry *dentry, struct inode *inode, const char *name,
283 const void *value, size_t size, int flags)
284 {
285 struct au_srxattr arg = {
286 .type = AU_XATTR_SET,
287 .u.set = {
288 .name = name,
289 .value = value,
290 .size = size,
291 .flags = flags
292 },
293 };
294
295 return au_srxattr(dentry, inode, &arg);
296 }
297
298 int aufs_removexattr(struct dentry *dentry, const char *name)
299 {
300 struct au_srxattr arg = {
301 .type = AU_XATTR_REMOVE,
302 .u.remove = {
303 .name = name
304 },
305 };
306
307 return au_srxattr(dentry, d_inode(dentry), &arg);
308 }
309
310 /* ---------------------------------------------------------------------- */
311
312 #if 0
313 static size_t au_xattr_list(struct dentry *dentry, char *list, size_t list_size,
314 const char *name, size_t name_len, int type)
315 {
316 return aufs_listxattr(dentry, list, list_size);
317 }
318
319 static int au_xattr_get(struct dentry *dentry, const char *name, void *buffer,
320 size_t size, int type)
321 {
322 return aufs_getxattr(dentry, name, buffer, size);
323 }
324
325 static int au_xattr_set(struct dentry *dentry, const char *name,
326 const void *value, size_t size, int flags, int type)
327 {
328 return aufs_setxattr(dentry, name, value, size, flags);
329 }
330
331 static const struct xattr_handler au_xattr_handler = {
332 /* no prefix, no flags */
333 .list = au_xattr_list,
334 .get = au_xattr_get,
335 .set = au_xattr_set
336 /* why no remove? */
337 };
338
339 static const struct xattr_handler *au_xattr_handlers[] = {
340 &au_xattr_handler
341 };
342
343 void au_xattr_init(struct super_block *sb)
344 {
345 /* sb->s_xattr = au_xattr_handlers; */
346 }
347 #endif