1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2007 Red Hat. All rights reserved.
7 #include <linux/string.h>
8 #include <linux/xattr.h>
9 #include <linux/posix_acl_xattr.h>
10 #include <linux/posix_acl.h>
11 #include <linux/sched.h>
12 #include <linux/slab.h>
15 #include "btrfs_inode.h"
18 struct posix_acl
*btrfs_get_acl(struct inode
*inode
, int type
)
23 struct posix_acl
*acl
;
27 name
= XATTR_NAME_POSIX_ACL_ACCESS
;
29 case ACL_TYPE_DEFAULT
:
30 name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
36 size
= btrfs_getxattr(inode
, name
, "", 0);
38 value
= kzalloc(size
, GFP_KERNEL
);
40 return ERR_PTR(-ENOMEM
);
41 size
= btrfs_getxattr(inode
, name
, value
, size
);
44 acl
= posix_acl_from_xattr(&init_user_ns
, value
, size
);
45 } else if (size
== -ERANGE
|| size
== -ENODATA
|| size
== 0) {
55 static int __btrfs_set_acl(struct btrfs_trans_handle
*trans
,
56 struct inode
*inode
, struct posix_acl
*acl
, int type
)
64 name
= XATTR_NAME_POSIX_ACL_ACCESS
;
66 case ACL_TYPE_DEFAULT
:
67 if (!S_ISDIR(inode
->i_mode
))
68 return acl
? -EINVAL
: 0;
69 name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
76 size
= posix_acl_xattr_size(acl
->a_count
);
77 value
= kmalloc(size
, GFP_KERNEL
);
83 ret
= posix_acl_to_xattr(&init_user_ns
, acl
, value
, size
);
88 ret
= btrfs_setxattr(trans
, inode
, name
, value
, size
, 0);
93 set_cached_acl(inode
, type
, acl
);
98 int btrfs_set_acl(struct inode
*inode
, struct posix_acl
*acl
, int type
)
101 umode_t old_mode
= inode
->i_mode
;
103 if (type
== ACL_TYPE_ACCESS
&& acl
) {
104 ret
= posix_acl_update_mode(inode
, &inode
->i_mode
, &acl
);
108 ret
= __btrfs_set_acl(NULL
, inode
, acl
, type
);
110 inode
->i_mode
= old_mode
;
114 int btrfs_init_acl(struct btrfs_trans_handle
*trans
,
115 struct inode
*inode
, struct inode
*dir
)
117 struct posix_acl
*default_acl
, *acl
;
120 /* this happens with subvols */
124 ret
= posix_acl_create(dir
, &inode
->i_mode
, &default_acl
, &acl
);
129 ret
= __btrfs_set_acl(trans
, inode
, default_acl
,
131 posix_acl_release(default_acl
);
136 ret
= __btrfs_set_acl(trans
, inode
, acl
,
138 posix_acl_release(acl
);
141 if (!default_acl
&& !acl
)