• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  *
30  * Copyright (c) 2012, Intel Corporation.
31  */
32 /*
33  * This file is part of Lustre, http://www.lustre.org/
34  * Lustre is a trademark of Sun Microsystems, Inc.
35  *
36  * lustre/llite/llite_rmtacl.c
37  *
38  * Lustre Remote User Access Control List.
39  *
40  * Author: Fan Yong <fanyong@clusterfs.com>
41  */
42 
43 #define DEBUG_SUBSYSTEM S_LLITE
44 
45 #ifdef CONFIG_FS_POSIX_ACL
46 
47 #include "../include/lustre_lite.h"
48 #include "../include/lustre_eacl.h"
49 #include "llite_internal.h"
50 
rce_hashfunc(uid_t id)51 static inline __u32 rce_hashfunc(uid_t id)
52 {
53 	return id & (RCE_HASHES - 1);
54 }
55 
ee_hashfunc(uid_t id)56 static inline __u32 ee_hashfunc(uid_t id)
57 {
58 	return id & (EE_HASHES - 1);
59 }
60 
rce_ops2valid(int ops)61 u64 rce_ops2valid(int ops)
62 {
63 	switch (ops) {
64 	case RMT_LSETFACL:
65 		return OBD_MD_FLRMTLSETFACL;
66 	case RMT_LGETFACL:
67 		return OBD_MD_FLRMTLGETFACL;
68 	case RMT_RSETFACL:
69 		return OBD_MD_FLRMTRSETFACL;
70 	case RMT_RGETFACL:
71 		return OBD_MD_FLRMTRGETFACL;
72 	default:
73 		return 0;
74 	}
75 }
76 
rce_alloc(pid_t key,int ops)77 static struct rmtacl_ctl_entry *rce_alloc(pid_t key, int ops)
78 {
79 	struct rmtacl_ctl_entry *rce;
80 
81 	rce = kzalloc(sizeof(*rce), GFP_NOFS);
82 	if (!rce)
83 		return NULL;
84 
85 	INIT_LIST_HEAD(&rce->rce_list);
86 	rce->rce_key = key;
87 	rce->rce_ops = ops;
88 
89 	return rce;
90 }
91 
rce_free(struct rmtacl_ctl_entry * rce)92 static void rce_free(struct rmtacl_ctl_entry *rce)
93 {
94 	if (!list_empty(&rce->rce_list))
95 		list_del(&rce->rce_list);
96 
97 	kfree(rce);
98 }
99 
__rct_search(struct rmtacl_ctl_table * rct,pid_t key)100 static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct,
101 					   pid_t key)
102 {
103 	struct rmtacl_ctl_entry *rce;
104 	struct list_head *head = &rct->rct_entries[rce_hashfunc(key)];
105 
106 	list_for_each_entry(rce, head, rce_list)
107 		if (rce->rce_key == key)
108 			return rce;
109 
110 	return NULL;
111 }
112 
rct_search(struct rmtacl_ctl_table * rct,pid_t key)113 struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key)
114 {
115 	struct rmtacl_ctl_entry *rce;
116 
117 	spin_lock(&rct->rct_lock);
118 	rce = __rct_search(rct, key);
119 	spin_unlock(&rct->rct_lock);
120 	return rce;
121 }
122 
rct_add(struct rmtacl_ctl_table * rct,pid_t key,int ops)123 int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops)
124 {
125 	struct rmtacl_ctl_entry *rce, *e;
126 
127 	rce = rce_alloc(key, ops);
128 	if (rce == NULL)
129 		return -ENOMEM;
130 
131 	spin_lock(&rct->rct_lock);
132 	e = __rct_search(rct, key);
133 	if (unlikely(e != NULL)) {
134 		CWARN("Unexpected stale rmtacl_entry found: [key: %d] [ops: %d]\n",
135 		      (int)key, ops);
136 		rce_free(e);
137 	}
138 	list_add_tail(&rce->rce_list, &rct->rct_entries[rce_hashfunc(key)]);
139 	spin_unlock(&rct->rct_lock);
140 
141 	return 0;
142 }
143 
rct_del(struct rmtacl_ctl_table * rct,pid_t key)144 int rct_del(struct rmtacl_ctl_table *rct, pid_t key)
145 {
146 	struct rmtacl_ctl_entry *rce;
147 
148 	spin_lock(&rct->rct_lock);
149 	rce = __rct_search(rct, key);
150 	if (rce)
151 		rce_free(rce);
152 	spin_unlock(&rct->rct_lock);
153 
154 	return rce ? 0 : -ENOENT;
155 }
156 
rct_init(struct rmtacl_ctl_table * rct)157 void rct_init(struct rmtacl_ctl_table *rct)
158 {
159 	int i;
160 
161 	spin_lock_init(&rct->rct_lock);
162 	for (i = 0; i < RCE_HASHES; i++)
163 		INIT_LIST_HEAD(&rct->rct_entries[i]);
164 }
165 
rct_fini(struct rmtacl_ctl_table * rct)166 void rct_fini(struct rmtacl_ctl_table *rct)
167 {
168 	struct rmtacl_ctl_entry *rce;
169 	int i;
170 
171 	spin_lock(&rct->rct_lock);
172 	for (i = 0; i < RCE_HASHES; i++)
173 		while (!list_empty(&rct->rct_entries[i])) {
174 			rce = list_entry(rct->rct_entries[i].next,
175 					     struct rmtacl_ctl_entry, rce_list);
176 			rce_free(rce);
177 		}
178 	spin_unlock(&rct->rct_lock);
179 }
180 
ee_alloc(pid_t key,struct lu_fid * fid,int type,ext_acl_xattr_header * header)181 static struct eacl_entry *ee_alloc(pid_t key, struct lu_fid *fid, int type,
182 				   ext_acl_xattr_header *header)
183 {
184 	struct eacl_entry *ee;
185 
186 	ee = kzalloc(sizeof(*ee), GFP_NOFS);
187 	if (!ee)
188 		return NULL;
189 
190 	INIT_LIST_HEAD(&ee->ee_list);
191 	ee->ee_key = key;
192 	ee->ee_fid = *fid;
193 	ee->ee_type = type;
194 	ee->ee_acl = header;
195 
196 	return ee;
197 }
198 
ee_free(struct eacl_entry * ee)199 void ee_free(struct eacl_entry *ee)
200 {
201 	if (!list_empty(&ee->ee_list))
202 		list_del(&ee->ee_list);
203 
204 	if (ee->ee_acl)
205 		lustre_ext_acl_xattr_free(ee->ee_acl);
206 
207 	kfree(ee);
208 }
209 
__et_search_del(struct eacl_table * et,pid_t key,struct lu_fid * fid,int type)210 static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key,
211 					struct lu_fid *fid, int type)
212 {
213 	struct eacl_entry *ee;
214 	struct list_head *head = &et->et_entries[ee_hashfunc(key)];
215 
216 	LASSERT(fid != NULL);
217 	list_for_each_entry(ee, head, ee_list)
218 		if (ee->ee_key == key) {
219 			if (lu_fid_eq(&ee->ee_fid, fid) &&
220 			    ee->ee_type == type) {
221 				list_del_init(&ee->ee_list);
222 				return ee;
223 			}
224 		}
225 
226 	return NULL;
227 }
228 
et_search_del(struct eacl_table * et,pid_t key,struct lu_fid * fid,int type)229 struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
230 				 struct lu_fid *fid, int type)
231 {
232 	struct eacl_entry *ee;
233 
234 	spin_lock(&et->et_lock);
235 	ee = __et_search_del(et, key, fid, type);
236 	spin_unlock(&et->et_lock);
237 	return ee;
238 }
239 
et_search_free(struct eacl_table * et,pid_t key)240 void et_search_free(struct eacl_table *et, pid_t key)
241 {
242 	struct eacl_entry *ee, *next;
243 	struct list_head *head = &et->et_entries[ee_hashfunc(key)];
244 
245 	spin_lock(&et->et_lock);
246 	list_for_each_entry_safe(ee, next, head, ee_list)
247 		if (ee->ee_key == key)
248 			ee_free(ee);
249 
250 	spin_unlock(&et->et_lock);
251 }
252 
ee_add(struct eacl_table * et,pid_t key,struct lu_fid * fid,int type,ext_acl_xattr_header * header)253 int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
254 	   ext_acl_xattr_header *header)
255 {
256 	struct eacl_entry *ee, *e;
257 
258 	ee = ee_alloc(key, fid, type, header);
259 	if (ee == NULL)
260 		return -ENOMEM;
261 
262 	spin_lock(&et->et_lock);
263 	e = __et_search_del(et, key, fid, type);
264 	if (unlikely(e != NULL)) {
265 		CWARN("Unexpected stale eacl_entry found: [key: %d] [fid: " DFID "] [type: %d]\n",
266 		      (int)key, PFID(fid), type);
267 		ee_free(e);
268 	}
269 	list_add_tail(&ee->ee_list, &et->et_entries[ee_hashfunc(key)]);
270 	spin_unlock(&et->et_lock);
271 
272 	return 0;
273 }
274 
et_init(struct eacl_table * et)275 void et_init(struct eacl_table *et)
276 {
277 	int i;
278 
279 	spin_lock_init(&et->et_lock);
280 	for (i = 0; i < EE_HASHES; i++)
281 		INIT_LIST_HEAD(&et->et_entries[i]);
282 }
283 
et_fini(struct eacl_table * et)284 void et_fini(struct eacl_table *et)
285 {
286 	struct eacl_entry *ee;
287 	int i;
288 
289 	spin_lock(&et->et_lock);
290 	for (i = 0; i < EE_HASHES; i++)
291 		while (!list_empty(&et->et_entries[i])) {
292 			ee = list_entry(et->et_entries[i].next,
293 					    struct eacl_entry, ee_list);
294 			ee_free(ee);
295 		}
296 	spin_unlock(&et->et_lock);
297 }
298 
299 #endif
300