Whamcloud - gitweb
LU-1346 libcfs: replace libcfs wrappers with kernel API
[fs/lustre-release.git] / lustre / llite / llite_rmtacl.c
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 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/llite/llite_rmtacl.c
35  *
36  * Lustre Remote User Access Control List.
37  *
38  * Author: Fan Yong <fanyong@clusterfs.com>
39  */
40
41 #define DEBUG_SUBSYSTEM S_LLITE
42
43 #ifdef CONFIG_FS_POSIX_ACL
44
45 #include <lustre_lite.h>
46 #include "llite_internal.h"
47
48 static inline __u32 rce_hashfunc(uid_t id)
49 {
50         return id & (RCE_HASHES - 1);
51 }
52
53 static inline __u32 ee_hashfunc(uid_t id)
54 {
55         return id & (EE_HASHES - 1);
56 }
57
58 obd_valid rce_ops2valid(int ops)
59 {
60         switch (ops) {
61         case RMT_LSETFACL:
62                 return OBD_MD_FLRMTLSETFACL;
63         case RMT_LGETFACL:
64                 return OBD_MD_FLRMTLGETFACL;
65         case RMT_RSETFACL:
66                 return OBD_MD_FLRMTRSETFACL;
67         case RMT_RGETFACL:
68                 return OBD_MD_FLRMTRGETFACL;
69         default:
70                 return 0;
71         }
72 }
73
74 static struct rmtacl_ctl_entry *rce_alloc(pid_t key, int ops)
75 {
76         struct rmtacl_ctl_entry *rce;
77
78         OBD_ALLOC_PTR(rce);
79         if (!rce)
80                 return NULL;
81
82         CFS_INIT_LIST_HEAD(&rce->rce_list);
83         rce->rce_key = key;
84         rce->rce_ops = ops;
85
86         return rce;
87 }
88
89 static void rce_free(struct rmtacl_ctl_entry *rce)
90 {
91         if (!cfs_list_empty(&rce->rce_list))
92                 cfs_list_del(&rce->rce_list);
93
94         OBD_FREE_PTR(rce);
95 }
96
97 static struct rmtacl_ctl_entry *__rct_search(struct rmtacl_ctl_table *rct,
98                                            pid_t key)
99 {
100         struct rmtacl_ctl_entry *rce;
101         cfs_list_t *head = &rct->rct_entries[rce_hashfunc(key)];
102
103         cfs_list_for_each_entry(rce, head, rce_list)
104                 if (rce->rce_key == key)
105                         return rce;
106
107         return NULL;
108 }
109
110 struct rmtacl_ctl_entry *rct_search(struct rmtacl_ctl_table *rct, pid_t key)
111 {
112         struct rmtacl_ctl_entry *rce;
113
114         spin_lock(&rct->rct_lock);
115         rce = __rct_search(rct, key);
116         spin_unlock(&rct->rct_lock);
117         return rce;
118 }
119
120 int rct_add(struct rmtacl_ctl_table *rct, pid_t key, int ops)
121 {
122         struct rmtacl_ctl_entry *rce, *e;
123
124         rce = rce_alloc(key, ops);
125         if (rce == NULL)
126                 return -ENOMEM;
127
128         spin_lock(&rct->rct_lock);
129         e = __rct_search(rct, key);
130         if (unlikely(e != NULL)) {
131                 CWARN("Unexpected stale rmtacl_entry found: "
132                       "[key: %d] [ops: %d]\n", (int)key, ops);
133                 rce_free(e);
134         }
135         cfs_list_add_tail(&rce->rce_list, &rct->rct_entries[rce_hashfunc(key)]);
136         spin_unlock(&rct->rct_lock);
137
138         return 0;
139 }
140
141 int rct_del(struct rmtacl_ctl_table *rct, pid_t key)
142 {
143         struct rmtacl_ctl_entry *rce;
144
145         spin_lock(&rct->rct_lock);
146         rce = __rct_search(rct, key);
147         if (rce)
148                 rce_free(rce);
149         spin_unlock(&rct->rct_lock);
150
151         return rce ? 0 : -ENOENT;
152 }
153
154 void rct_init(struct rmtacl_ctl_table *rct)
155 {
156         int i;
157
158         spin_lock_init(&rct->rct_lock);
159         for (i = 0; i < RCE_HASHES; i++)
160                 CFS_INIT_LIST_HEAD(&rct->rct_entries[i]);
161 }
162
163 void rct_fini(struct rmtacl_ctl_table *rct)
164 {
165         struct rmtacl_ctl_entry *rce;
166         int i;
167
168         spin_lock(&rct->rct_lock);
169         for (i = 0; i < RCE_HASHES; i++)
170                 while (!cfs_list_empty(&rct->rct_entries[i])) {
171                         rce = cfs_list_entry(rct->rct_entries[i].next,
172                                              struct rmtacl_ctl_entry, rce_list);
173                         rce_free(rce);
174                 }
175         spin_unlock(&rct->rct_lock);
176 }
177
178
179 static struct eacl_entry *ee_alloc(pid_t key, struct lu_fid *fid, int type,
180                                    ext_acl_xattr_header *header)
181 {
182         struct eacl_entry *ee;
183
184         OBD_ALLOC_PTR(ee);
185         if (!ee)
186                 return NULL;
187
188         CFS_INIT_LIST_HEAD(&ee->ee_list);
189         ee->ee_key = key;
190         ee->ee_fid = *fid;
191         ee->ee_type = type;
192         ee->ee_acl = header;
193
194         return ee;
195 }
196
197 void ee_free(struct eacl_entry *ee)
198 {
199         if (!cfs_list_empty(&ee->ee_list))
200                 cfs_list_del(&ee->ee_list);
201
202         if (ee->ee_acl)
203                 lustre_ext_acl_xattr_free(ee->ee_acl);
204
205         OBD_FREE_PTR(ee);
206 }
207
208 static struct eacl_entry *__et_search_del(struct eacl_table *et, pid_t key,
209                                         struct lu_fid *fid, int type)
210 {
211         struct eacl_entry *ee;
212         cfs_list_t *head = &et->et_entries[ee_hashfunc(key)];
213
214         LASSERT(fid != NULL);
215         cfs_list_for_each_entry(ee, head, ee_list)
216                 if (ee->ee_key == key) {
217                         if (lu_fid_eq(&ee->ee_fid, fid) &&
218                             ee->ee_type == type) {
219                                 cfs_list_del_init(&ee->ee_list);
220                                 return ee;
221                         }
222                 }
223
224         return NULL;
225 }
226
227 struct eacl_entry *et_search_del(struct eacl_table *et, pid_t key,
228                                  struct lu_fid *fid, int type)
229 {
230         struct eacl_entry *ee;
231
232         spin_lock(&et->et_lock);
233         ee = __et_search_del(et, key, fid, type);
234         spin_unlock(&et->et_lock);
235         return ee;
236 }
237
238 void et_search_free(struct eacl_table *et, pid_t key)
239 {
240         struct eacl_entry *ee, *next;
241         cfs_list_t *head = &et->et_entries[ee_hashfunc(key)];
242
243         spin_lock(&et->et_lock);
244         cfs_list_for_each_entry_safe(ee, next, head, ee_list)
245                 if (ee->ee_key == key)
246                         ee_free(ee);
247
248         spin_unlock(&et->et_lock);
249 }
250
251 int ee_add(struct eacl_table *et, pid_t key, struct lu_fid *fid, int type,
252            ext_acl_xattr_header *header)
253 {
254         struct eacl_entry *ee, *e;
255
256         ee = ee_alloc(key, fid, type, header);
257         if (ee == NULL)
258                 return -ENOMEM;
259
260         spin_lock(&et->et_lock);
261         e = __et_search_del(et, key, fid, type);
262         if (unlikely(e != NULL)) {
263                 CWARN("Unexpected stale eacl_entry found: "
264                       "[key: %d] [fid: "DFID"] [type: %d]\n",
265                       (int)key, PFID(fid), type);
266                 ee_free(e);
267         }
268         cfs_list_add_tail(&ee->ee_list, &et->et_entries[ee_hashfunc(key)]);
269         spin_unlock(&et->et_lock);
270
271         return 0;
272 }
273
274 void et_init(struct eacl_table *et)
275 {
276         int i;
277
278         spin_lock_init(&et->et_lock);
279         for (i = 0; i < EE_HASHES; i++)
280                 CFS_INIT_LIST_HEAD(&et->et_entries[i]);
281 }
282
283 void et_fini(struct eacl_table *et)
284 {
285         struct eacl_entry *ee;
286         int i;
287
288         spin_lock(&et->et_lock);
289         for (i = 0; i < EE_HASHES; i++)
290                 while (!cfs_list_empty(&et->et_entries[i])) {
291                         ee = cfs_list_entry(et->et_entries[i].next,
292                                             struct eacl_entry, ee_list);
293                         ee_free(ee);
294                 }
295         spin_unlock(&et->et_lock);
296 }
297
298 #endif