Merge tag 'linux-kselftest-5.4-rc1.1' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-block.git] / fs / gfs2 / acl.c
CommitLineData
7336d0e6 1// SPDX-License-Identifier: GPL-2.0-only
b3b94faa
DT
2/*
3 * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
3a8a9a10 4 * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved.
b3b94faa
DT
5 */
6
7#include <linux/sched.h>
8#include <linux/slab.h>
9#include <linux/spinlock.h>
10#include <linux/completion.h>
11#include <linux/buffer_head.h>
2646a1f6 12#include <linux/xattr.h>
b3b94faa
DT
13#include <linux/posix_acl.h>
14#include <linux/posix_acl_xattr.h>
5c676f6d 15#include <linux/gfs2_ondisk.h>
b3b94faa
DT
16
17#include "gfs2.h"
5c676f6d 18#include "incore.h"
b3b94faa 19#include "acl.h"
307cf6e6 20#include "xattr.h"
b3b94faa
DT
21#include "glock.h"
22#include "inode.h"
23#include "meta_io.h"
1a39ba99 24#include "rgrp.h"
b3b94faa 25#include "trans.h"
5c676f6d 26#include "util.h"
b3b94faa 27
479c427d 28static const char *gfs2_acl_name(int type)
b3b94faa 29{
479c427d
SW
30 switch (type) {
31 case ACL_TYPE_ACCESS:
97d79299 32 return XATTR_POSIX_ACL_ACCESS;
479c427d 33 case ACL_TYPE_DEFAULT:
97d79299 34 return XATTR_POSIX_ACL_DEFAULT;
479c427d
SW
35 }
36 return NULL;
37}
b3b94faa 38
1a39ba99 39static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type)
479c427d 40{
018a01cd 41 struct gfs2_inode *ip = GFS2_I(inode);
479c427d
SW
42 struct posix_acl *acl;
43 const char *name;
44 char *data;
45 int len;
40b78a32 46
3767ac21 47 if (!ip->i_eattr)
479c427d 48 return NULL;
b3b94faa 49
479c427d 50 name = gfs2_acl_name(type);
479c427d 51 len = gfs2_xattr_acl_get(ip, name, &data);
1a39ba99 52 if (len <= 0)
479c427d 53 return ERR_PTR(len);
5f3a4a28 54 acl = posix_acl_from_xattr(&init_user_ns, data, len);
479c427d
SW
55 kfree(data);
56 return acl;
b3b94faa
DT
57}
58
1a39ba99
AV
59struct posix_acl *gfs2_get_acl(struct inode *inode, int type)
60{
61 struct gfs2_inode *ip = GFS2_I(inode);
62 struct gfs2_holder gh;
63 bool need_unlock = false;
64 struct posix_acl *acl;
65
66 if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
67 int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
68 LM_FLAG_ANY, &gh);
69 if (ret)
70 return ERR_PTR(ret);
71 need_unlock = true;
72 }
73 acl = __gfs2_get_acl(inode, type);
74 if (need_unlock)
75 gfs2_glock_dq_uninit(&gh);
76 return acl;
77}
78
79int __gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
b3b94faa 80{
b3b94faa 81 int error;
910f3d58 82 size_t len;
479c427d
SW
83 char *data;
84 const char *name = gfs2_acl_name(type);
85
e01580bf 86 if (acl) {
910f3d58 87 len = posix_acl_xattr_size(acl->a_count);
e01580bf
CH
88 data = kmalloc(len, GFP_NOFS);
89 if (data == NULL)
90 return -ENOMEM;
91 error = posix_acl_to_xattr(&init_user_ns, acl, data, len);
92 if (error < 0)
93 goto out;
94 } else {
95 data = NULL;
96 len = 0;
106381bf 97 }
e01580bf
CH
98
99 error = __gfs2_xattr_set(inode, name, data, len, 0, GFS2_EATYPE_SYS);
100 if (error)
101 goto out;
932e468a 102 set_cached_acl(inode, type, acl);
2646a1f6 103out:
e01580bf 104 kfree(data);
2646a1f6
SW
105 return error;
106}
1a39ba99
AV
107
108int gfs2_set_acl(struct inode *inode, struct posix_acl *acl, int type)
109{
110 struct gfs2_inode *ip = GFS2_I(inode);
111 struct gfs2_holder gh;
112 bool need_unlock = false;
113 int ret;
309e8cda 114 umode_t mode;
1a39ba99 115
914cea93
JK
116 if (acl && acl->a_count > GFS2_ACL_MAX_ENTRIES(GFS2_SB(inode)))
117 return -E2BIG;
118
1a39ba99
AV
119 ret = gfs2_rsqa_alloc(ip);
120 if (ret)
121 return ret;
122
123 if (!gfs2_glock_is_locked_by_me(ip->i_gl)) {
124 ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
125 if (ret)
126 return ret;
127 need_unlock = true;
128 }
914cea93 129
309e8cda
EF
130 mode = inode->i_mode;
131 if (type == ACL_TYPE_ACCESS && acl) {
132 ret = posix_acl_update_mode(inode, &mode, &acl);
914cea93
JK
133 if (ret)
134 goto unlock;
914cea93
JK
135 }
136
1a39ba99 137 ret = __gfs2_set_acl(inode, acl, type);
309e8cda 138 if (!ret && mode != inode->i_mode) {
c2c4be28 139 inode->i_ctime = current_time(inode);
309e8cda
EF
140 inode->i_mode = mode;
141 mark_inode_dirty(inode);
142 }
914cea93 143unlock:
1a39ba99
AV
144 if (need_unlock)
145 gfs2_glock_dq_uninit(&gh);
146 return ret;
147}