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
;
33 return ERR_PTR(-EINVAL
);
36 size
= btrfs_getxattr(inode
, name
, NULL
, 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
== -ENODATA
|| size
== 0)
54 static int __btrfs_set_acl(struct btrfs_trans_handle
*trans
,
55 struct inode
*inode
, struct posix_acl
*acl
, int type
)
63 name
= XATTR_NAME_POSIX_ACL_ACCESS
;
65 case ACL_TYPE_DEFAULT
:
66 if (!S_ISDIR(inode
->i_mode
))
67 return acl
? -EINVAL
: 0;
68 name
= XATTR_NAME_POSIX_ACL_DEFAULT
;
75 size
= posix_acl_xattr_size(acl
->a_count
);
76 value
= kmalloc(size
, GFP_KERNEL
);
82 ret
= posix_acl_to_xattr(&init_user_ns
, acl
, value
, size
);
87 ret
= btrfs_setxattr(trans
, inode
, name
, value
, size
, 0);
92 set_cached_acl(inode
, type
, acl
);
97 int btrfs_set_acl(struct inode
*inode
, struct posix_acl
*acl
, int type
)
100 umode_t old_mode
= inode
->i_mode
;
102 if (type
== ACL_TYPE_ACCESS
&& acl
) {
103 ret
= posix_acl_update_mode(inode
, &inode
->i_mode
, &acl
);
107 ret
= __btrfs_set_acl(NULL
, inode
, acl
, type
);
109 inode
->i_mode
= old_mode
;
113 int btrfs_init_acl(struct btrfs_trans_handle
*trans
,
114 struct inode
*inode
, struct inode
*dir
)
116 struct posix_acl
*default_acl
, *acl
;
119 /* this happens with subvols */
123 ret
= posix_acl_create(dir
, &inode
->i_mode
, &default_acl
, &acl
);
128 ret
= __btrfs_set_acl(trans
, inode
, default_acl
,
130 posix_acl_release(default_acl
);
135 ret
= __btrfs_set_acl(trans
, inode
, acl
,
137 posix_acl_release(acl
);
140 if (!default_acl
&& !acl
)