1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
6 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 only,
10 * as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License version 2 for more details (a copy is included
16 * in the LICENSE file that accompanied this code).
18 * You should have received a copy of the GNU General Public License
19 * version 2 along with this program; If not, see
20 * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
22 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
23 * CA 95054 USA or visit www.sun.com if you need additional information or
29 * Copyright 2008 Sun Microsystems, Inc. All rights reserved
30 * Use is subject to license terms.
33 * This file is part of Lustre, http://www.lustre.org/
34 * Lustre is a trademark of Sun Microsystems, Inc.
36 * lustre/obdclass/idmap.c
38 * Lustre user identity mapping.
40 * Author: Fan Yong <fanyong@clusterfs.com>
44 # define EXPORT_SYMTAB
47 #define DEBUG_SUBSYSTEM S_SEC
49 #include <lustre_idmap.h>
50 #include <obd_support.h>
52 #define lustre_get_group_info(group_info) do { \
53 cfs_atomic_inc(&(group_info)->usage); \
56 #define lustre_put_group_info(group_info) do { \
57 if (cfs_atomic_dec_and_test(&(group_info)->usage)) \
58 cfs_groups_free(group_info); \
62 * groups_search() is copied from linux kernel!
65 static int lustre_groups_search(cfs_group_info_t *group_info,
74 right = group_info->ngroups;
75 while (left < right) {
76 int mid = (left + right) / 2;
77 int cmp = grp - CFS_GROUP_AT(group_info, mid);
89 void lustre_groups_from_list(cfs_group_info_t *ginfo, gid_t *glist)
92 int count = ginfo->ngroups;
94 /* fill group_info from gid array */
95 for (i = 0; i < ginfo->nblocks && count > 0; i++) {
96 int cp_count = min(CFS_NGROUPS_PER_BLOCK, count);
97 int off = i * CFS_NGROUPS_PER_BLOCK;
98 int len = cp_count * sizeof(*glist);
100 memcpy(ginfo->blocks[i], glist + off, len);
104 EXPORT_SYMBOL(lustre_groups_from_list);
106 /* groups_sort() is copied from linux kernel! */
107 /* a simple shell-metzner sort */
108 void lustre_groups_sort(cfs_group_info_t *group_info)
110 int base, max, stride;
111 int gidsetsize = group_info->ngroups;
113 for (stride = 1; stride < gidsetsize; stride = 3 * stride + 1)
118 max = gidsetsize - stride;
119 for (base = 0; base < max; base++) {
121 int right = left + stride;
122 gid_t tmp = CFS_GROUP_AT(group_info, right);
125 CFS_GROUP_AT(group_info, left) > tmp) {
126 CFS_GROUP_AT(group_info, right) =
127 CFS_GROUP_AT(group_info, left);
131 CFS_GROUP_AT(group_info, right) = tmp;
136 EXPORT_SYMBOL(lustre_groups_sort);
138 int lustre_in_group_p(struct md_ucred *mu, gid_t grp)
142 if (grp != mu->mu_fsgid) {
143 cfs_group_info_t *group_info = NULL;
145 if (mu->mu_ginfo || !mu->mu_identity ||
146 mu->mu_valid == UCRED_OLD)
147 if (grp == mu->mu_suppgids[0] ||
148 grp == mu->mu_suppgids[1])
152 group_info = mu->mu_ginfo;
153 else if (mu->mu_identity)
154 group_info = mu->mu_identity->mi_ginfo;
159 lustre_get_group_info(group_info);
160 rc = lustre_groups_search(group_info, grp);
161 lustre_put_group_info(group_info);
165 EXPORT_SYMBOL(lustre_in_group_p);
167 struct lustre_idmap_entry {
168 cfs_list_t lie_rmt_uid_hash; /* hashed as lie_rmt_uid; */
169 cfs_list_t lie_lcl_uid_hash; /* hashed as lie_lcl_uid; */
170 cfs_list_t lie_rmt_gid_hash; /* hashed as lie_rmt_gid; */
171 cfs_list_t lie_lcl_gid_hash; /* hashed as lie_lcl_gid; */
172 uid_t lie_rmt_uid; /* remote uid */
173 uid_t lie_lcl_uid; /* local uid */
174 gid_t lie_rmt_gid; /* remote gid */
175 gid_t lie_lcl_gid; /* local gid */
178 static inline __u32 lustre_idmap_hashfunc(__u32 id)
180 return id & (CFS_IDMAP_HASHSIZE - 1);
184 struct lustre_idmap_entry *idmap_entry_alloc(uid_t rmt_uid, uid_t lcl_uid,
185 gid_t rmt_gid, gid_t lcl_gid)
187 struct lustre_idmap_entry *e;
193 CFS_INIT_LIST_HEAD(&e->lie_rmt_uid_hash);
194 CFS_INIT_LIST_HEAD(&e->lie_lcl_uid_hash);
195 CFS_INIT_LIST_HEAD(&e->lie_rmt_gid_hash);
196 CFS_INIT_LIST_HEAD(&e->lie_lcl_gid_hash);
197 e->lie_rmt_uid = rmt_uid;
198 e->lie_lcl_uid = lcl_uid;
199 e->lie_rmt_gid = rmt_gid;
200 e->lie_lcl_gid = lcl_gid;
205 static void idmap_entry_free(struct lustre_idmap_entry *e)
207 if (!cfs_list_empty(&e->lie_rmt_uid_hash))
208 cfs_list_del(&e->lie_rmt_uid_hash);
209 if (!cfs_list_empty(&e->lie_lcl_uid_hash))
210 cfs_list_del(&e->lie_lcl_uid_hash);
211 if (!cfs_list_empty(&e->lie_rmt_gid_hash))
212 cfs_list_del(&e->lie_rmt_gid_hash);
213 if (!cfs_list_empty(&e->lie_lcl_gid_hash))
214 cfs_list_del(&e->lie_lcl_gid_hash);
220 * NULL: not found entry
221 * ERR_PTR(-EACCES): found 1(remote):N(local) mapped entry
222 * others: found normal entry
225 struct lustre_idmap_entry *idmap_search_entry(struct lustre_idmap_table *t,
226 uid_t rmt_uid, uid_t lcl_uid,
227 gid_t rmt_gid, gid_t lcl_gid)
230 struct lustre_idmap_entry *e;
232 head = &t->lit_idmaps[RMT_UIDMAP_IDX][lustre_idmap_hashfunc(rmt_uid)];
233 cfs_list_for_each_entry(e, head, lie_rmt_uid_hash)
234 if (e->lie_rmt_uid == rmt_uid) {
235 if (e->lie_lcl_uid == lcl_uid) {
236 if (e->lie_rmt_gid == rmt_gid &&
237 e->lie_lcl_gid == lcl_gid)
238 /* must be quaternion match */
241 /* 1:N uid mapping */
242 CERROR("rmt uid %u already be mapped to %u"
243 " (new %u)\n", e->lie_rmt_uid,
244 e->lie_lcl_uid, lcl_uid);
245 return ERR_PTR(-EACCES);
249 head = &t->lit_idmaps[RMT_GIDMAP_IDX][lustre_idmap_hashfunc(rmt_gid)];
250 cfs_list_for_each_entry(e, head, lie_rmt_gid_hash)
251 if (e->lie_rmt_gid == rmt_gid) {
252 if (e->lie_lcl_gid == lcl_gid) {
253 if (unlikely(e->lie_rmt_uid == rmt_uid &&
254 e->lie_lcl_uid == lcl_uid))
255 /* after uid mapping search above,
256 * we should never come here */
259 /* 1:N gid mapping */
260 CERROR("rmt gid %u already be mapped to %u"
261 " (new %u)\n", e->lie_rmt_gid,
262 e->lie_lcl_gid, lcl_gid);
263 return ERR_PTR(-EACCES);
270 static __u32 idmap_lookup_uid(cfs_list_t *hash, int reverse,
273 cfs_list_t *head = &hash[lustre_idmap_hashfunc(uid)];
274 struct lustre_idmap_entry *e;
277 cfs_list_for_each_entry(e, head, lie_rmt_uid_hash)
278 if (e->lie_rmt_uid == uid)
279 return e->lie_lcl_uid;
281 cfs_list_for_each_entry(e, head, lie_lcl_uid_hash)
282 if (e->lie_lcl_uid == uid)
283 return e->lie_rmt_uid;
286 return CFS_IDMAP_NOTFOUND;
289 static __u32 idmap_lookup_gid(cfs_list_t *hash, int reverse, __u32 gid)
291 cfs_list_t *head = &hash[lustre_idmap_hashfunc(gid)];
292 struct lustre_idmap_entry *e;
295 cfs_list_for_each_entry(e, head, lie_rmt_gid_hash)
296 if (e->lie_rmt_gid == gid)
297 return e->lie_lcl_gid;
299 cfs_list_for_each_entry(e, head, lie_lcl_gid_hash)
300 if (e->lie_lcl_gid == gid)
301 return e->lie_rmt_gid;
304 return CFS_IDMAP_NOTFOUND;
307 int lustre_idmap_add(struct lustre_idmap_table *t,
308 uid_t ruid, uid_t luid,
309 gid_t rgid, gid_t lgid)
311 struct lustre_idmap_entry *e0, *e1;
315 cfs_spin_lock(&t->lit_lock);
316 e0 = idmap_search_entry(t, ruid, luid, rgid, lgid);
317 cfs_spin_unlock(&t->lit_lock);
319 e0 = idmap_entry_alloc(ruid, luid, rgid, lgid);
323 cfs_spin_lock(&t->lit_lock);
324 e1 = idmap_search_entry(t, ruid, luid, rgid, lgid);
326 cfs_list_add_tail(&e0->lie_rmt_uid_hash,
327 &t->lit_idmaps[RMT_UIDMAP_IDX]
328 [lustre_idmap_hashfunc(ruid)]);
329 cfs_list_add_tail(&e0->lie_lcl_uid_hash,
330 &t->lit_idmaps[LCL_UIDMAP_IDX]
331 [lustre_idmap_hashfunc(luid)]);
332 cfs_list_add_tail(&e0->lie_rmt_gid_hash,
333 &t->lit_idmaps[RMT_GIDMAP_IDX]
334 [lustre_idmap_hashfunc(rgid)]);
335 cfs_list_add_tail(&e0->lie_lcl_gid_hash,
336 &t->lit_idmaps[LCL_GIDMAP_IDX]
337 [lustre_idmap_hashfunc(lgid)]);
339 cfs_spin_unlock(&t->lit_lock);
341 idmap_entry_free(e0);
345 } else if (IS_ERR(e0)) {
351 EXPORT_SYMBOL(lustre_idmap_add);
353 int lustre_idmap_del(struct lustre_idmap_table *t,
354 uid_t ruid, uid_t luid,
355 gid_t rgid, gid_t lgid)
357 struct lustre_idmap_entry *e;
362 cfs_spin_lock(&t->lit_lock);
363 e = idmap_search_entry(t, ruid, luid, rgid, lgid);
368 cfs_spin_unlock(&t->lit_lock);
372 EXPORT_SYMBOL(lustre_idmap_del);
374 int lustre_idmap_lookup_uid(struct md_ucred *mu,
375 struct lustre_idmap_table *t,
376 int reverse, uid_t uid)
380 if (mu && (mu->mu_valid == UCRED_OLD || mu->mu_valid == UCRED_NEW)) {
382 if (uid == mu->mu_o_uid)
384 else if (uid == mu->mu_o_fsuid)
387 if (uid == mu->mu_uid)
389 else if (uid == mu->mu_fsuid)
390 return mu->mu_o_fsuid;
395 return CFS_IDMAP_NOTFOUND;
397 hash = t->lit_idmaps[reverse ? LCL_UIDMAP_IDX : RMT_UIDMAP_IDX];
399 cfs_spin_lock(&t->lit_lock);
400 uid = idmap_lookup_uid(hash, reverse, uid);
401 cfs_spin_unlock(&t->lit_lock);
405 EXPORT_SYMBOL(lustre_idmap_lookup_uid);
407 int lustre_idmap_lookup_gid(struct md_ucred *mu, struct lustre_idmap_table *t,
408 int reverse, gid_t gid)
412 if (mu && (mu->mu_valid == UCRED_OLD || mu->mu_valid == UCRED_NEW)) {
414 if (gid == mu->mu_o_gid)
416 else if (gid == mu->mu_o_fsgid)
419 if (gid == mu->mu_gid)
421 else if (gid == mu->mu_fsgid)
422 return mu->mu_o_fsgid;
427 return CFS_IDMAP_NOTFOUND;
429 hash = t->lit_idmaps[reverse ? LCL_GIDMAP_IDX : RMT_GIDMAP_IDX];
431 cfs_spin_lock(&t->lit_lock);
432 gid = idmap_lookup_gid(hash, reverse, gid);
433 cfs_spin_unlock(&t->lit_lock);
437 EXPORT_SYMBOL(lustre_idmap_lookup_gid);
439 struct lustre_idmap_table *lustre_idmap_init(void)
441 struct lustre_idmap_table *t;
445 if(unlikely(t == NULL))
446 return (ERR_PTR(-ENOMEM));
448 cfs_spin_lock_init(&t->lit_lock);
449 for (i = 0; i < ARRAY_SIZE(t->lit_idmaps); i++)
450 for (j = 0; j < ARRAY_SIZE(t->lit_idmaps[i]); j++)
451 CFS_INIT_LIST_HEAD(&t->lit_idmaps[i][j]);
455 EXPORT_SYMBOL(lustre_idmap_init);
457 void lustre_idmap_fini(struct lustre_idmap_table *t)
460 struct lustre_idmap_entry *e;
464 list = t->lit_idmaps[RMT_UIDMAP_IDX];
465 cfs_spin_lock(&t->lit_lock);
466 for (i = 0; i < CFS_IDMAP_HASHSIZE; i++)
467 while (!cfs_list_empty(&list[i])) {
468 e = cfs_list_entry(list[i].next,
469 struct lustre_idmap_entry,
473 cfs_spin_unlock(&t->lit_lock);
477 EXPORT_SYMBOL(lustre_idmap_fini);