2 * Copyright (C) 2014-2016 Junjiro R. Okajima
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.
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.
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/>.
19 * handling xattr functions
22 #include <linux/xattr.h>
25 static int au_xattr_ignore(int err
, char *name
, unsigned int ignore_flags
)
35 if ((ignore_flags
& AuBrAttr_ICEX
) == AuBrAttr_ICEX
) {
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) \
55 if (ignore_flags
& AuBrAttr_ICEX_OTH
)
62 static const int au_xattr_out_of_list
= AuBrAttr_ICEX_OTH
<< 1;
64 static int au_do_cpup_xattr(struct dentry
*h_dst
, struct dentry
*h_src
,
65 char *name
, char **buf
, unsigned int ignore_flags
,
72 ssz
= vfs_getxattr_alloc(h_src
, name
, buf
, 0, GFP_NOFS
);
74 if (unlikely(err
<= 0)) {
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
)
81 XATTR_NAME_POSIX_ACL_DEFAULT
))))
84 if (err
&& (verbose
|| au_debug_test()))
85 pr_err("%s, err %d\n", name
, err
);
89 /* unlock it temporary */
90 h_idst
= d_inode(h_dst
);
92 err
= vfsub_setxattr(h_dst
, name
, *buf
, ssz
, /*flags*/0);
93 inode_lock_nested(h_idst
, AuLsc_I_CHILD2
);
95 if (verbose
|| au_debug_test())
96 pr_err("%s, err %d\n", name
, err
);
97 err
= au_xattr_ignore(err
, name
, ignore_flags
);
104 int au_cpup_xattr(struct dentry
*h_dst
, struct dentry
*h_src
, int ignore_flags
,
105 unsigned int verbose
)
107 int err
, unlocked
, acl_access
, acl_default
;
109 struct inode
*h_isrc
, *h_idst
;
110 char *value
, *p
, *o
, *e
;
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
);
121 /* some filesystems don't list POSIX ACL, for example tmpfs */
122 ssz
= vfs_listxattr(h_src
, NULL
, 0);
124 if (unlikely(err
< 0)) {
127 || err
== -EOPNOTSUPP
)
128 err
= 0; /* ignore */
137 p
= kmalloc(ssz
, GFP_NOFS
);
141 err
= vfs_listxattr(h_src
, p
, ssz
);
143 inode_unlock(h_isrc
);
145 AuDbg("err %d, ssz %zd\n", err
, ssz
);
146 if (unlikely(err
< 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
)
160 err
= au_do_cpup_xattr(h_dst
, h_src
, p
, &value
, ignore_flags
,
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
);
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
);
180 au_delayed_kfree(value
);
187 inode_unlock(h_isrc
);
192 /* ---------------------------------------------------------------------- */
214 static ssize_t
au_lgxattr(struct dentry
*dentry
, struct au_lgxattr
*arg
)
218 struct super_block
*sb
;
221 err
= si_read_lock(sb
, AuLock_FLUSH
| AuLock_NOPLM
);
224 err
= au_h_path_getattr(dentry
, /*force*/1, &h_path
);
227 if (unlikely(!h_path
.dentry
))
228 /* illegally overlapped or something */
229 goto out_di
; /* pretending success */
231 /* always topmost entry only */
234 err
= vfs_listxattr(h_path
.dentry
,
235 arg
->u
.list
.list
, arg
->u
.list
.size
);
238 AuDebugOn(d_is_negative(h_path
.dentry
));
239 err
= vfs_getxattr(h_path
.dentry
,
240 arg
->u
.get
.name
, arg
->u
.get
.value
,
246 di_read_unlock(dentry
, AuLock_IR
);
254 ssize_t
aufs_listxattr(struct dentry
*dentry
, char *list
, size_t size
)
256 struct au_lgxattr arg
= {
257 .type
= AU_XATTR_LIST
,
264 return au_lgxattr(dentry
, &arg
);
267 ssize_t
aufs_getxattr(struct dentry
*dentry
, struct inode
*inode __maybe_unused
,
268 const char *name
, void *value
, size_t size
)
270 struct au_lgxattr arg
= {
271 .type
= AU_XATTR_GET
,
279 return au_lgxattr(dentry
, &arg
);
282 int aufs_setxattr(struct dentry
*dentry
, struct inode
*inode
, const char *name
,
283 const void *value
, size_t size
, int flags
)
285 struct au_srxattr arg
= {
286 .type
= AU_XATTR_SET
,
295 return au_srxattr(dentry
, inode
, &arg
);
298 int aufs_removexattr(struct dentry
*dentry
, const char *name
)
300 struct au_srxattr arg
= {
301 .type
= AU_XATTR_REMOVE
,
307 return au_srxattr(dentry
, d_inode(dentry
), &arg
);
310 /* ---------------------------------------------------------------------- */
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
)
316 return aufs_listxattr(dentry
, list
, list_size
);
319 static int au_xattr_get(struct dentry
*dentry
, const char *name
, void *buffer
,
320 size_t size
, int type
)
322 return aufs_getxattr(dentry
, name
, buffer
, size
);
325 static int au_xattr_set(struct dentry
*dentry
, const char *name
,
326 const void *value
, size_t size
, int flags
, int type
)
328 return aufs_setxattr(dentry
, name
, value
, size
, flags
);
331 static const struct xattr_handler au_xattr_handler
= {
332 /* no prefix, no flags */
333 .list
= au_xattr_list
,
339 static const struct xattr_handler
*au_xattr_handlers
[] = {
343 void au_xattr_init(struct super_block
*sb
)
345 /* sb->s_xattr = au_xattr_handlers; */