1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 2004-2005 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #define DEBUG_SUBSYSTEM S_MDS
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/kernel.h>
28 #include <linux/kmod.h>
29 #include <linux/string.h>
30 #include <linux/stat.h>
31 #include <linux/errno.h>
32 #include <linux/version.h>
33 #include <linux/unistd.h>
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
39 #include <linux/stat.h>
40 #include <asm/uaccess.h>
41 #include <linux/slab.h>
42 #include <asm/segment.h>
44 #include <libcfs/list.h>
45 #include <linux/obd_support.h>
46 #include <linux/lustre_lib.h>
47 #include <linux/lustre_mds.h>
48 #include <linux/lustre_ucache.h>
50 #include "mds_internal.h"
53 * We need share hash table among the groups of MDSs (which server as the same
54 * lustre file system), maybe MDT? but there's lprocfs problems of putting this
55 * in MDT. so we make it global to the module. which brings the limitation that
56 * one node couldn't running multiple MDS which server as different Lustre FS.
57 * but which maybe not meaningful.
61 #define MDS_LSD_HASHSIZE (256)
62 static struct upcall_cache _lsd_cache;
63 static struct list_head _lsd_hashtable[MDS_LSD_HASHSIZE];
65 #define MDS_LSD_UPCALL_PATH "/usr/sbin/lsd_upcall"
66 #define MDS_LSD_ACQUIRE_EXPIRE (5)
67 #define MDS_LSD_ENTRY_EXPIRE (5 * 60)
68 #define MDS_LSD_ERR_ENTRY_EXPIRE (30)
70 struct upcall_cache *__mds_get_global_lsd_cache()
75 static unsigned int lsd_hash(struct upcall_cache *cache, __u64 key)
77 LASSERT(cache == &_lsd_cache);
78 return ((__u32) key) & (MDS_LSD_HASHSIZE - 1);
81 static struct upcall_cache_entry *
82 lsd_alloc_entry(struct upcall_cache *cache, __u64 key)
84 struct lsd_cache_entry *entry;
87 OBD_ALLOC(entry, sizeof(*entry));
89 CERROR("failed to alloc entry\n");
92 upcall_cache_init_entry(cache, &entry->base, key);
97 static void lsd_free_entry(struct upcall_cache *cache,
98 struct upcall_cache_entry *entry)
100 struct lsd_cache_entry *lentry;
102 lentry = container_of(entry, struct lsd_cache_entry, base);
103 if (lentry->lsd.lsd_ginfo)
104 put_group_info(lentry->lsd.lsd_ginfo);
105 if (lentry->lsd.lsd_perms) {
106 LASSERT(lentry->lsd.lsd_nperms);
107 OBD_FREE(lentry->lsd.lsd_perms, lentry->lsd.lsd_nperms *
108 sizeof(struct lsd_permission));
110 OBD_FREE(lentry, sizeof(*lentry));
114 static int lsd_make_upcall(struct upcall_cache *cache,
115 struct upcall_cache_entry *entry)
123 snprintf(uidstr, 16, "%u", (__u32) entry->ue_key);
125 argv[0] = cache->uc_upcall;
130 envp[1] = "PATH=/sbin:/usr/sbin";
133 rc = USERMODEHELPER(argv[0], argv, envp);
135 CERROR("Error invoking lsd upcall %s %s: %d; check "
136 "/proc/fs/lustre/mds/lsd_upcall\n",
137 argv[0], argv[1], rc);
139 CWARN("Invoked upcall %s %s\n",
145 static int lsd_parse_downcall(struct upcall_cache *cache,
146 struct upcall_cache_entry *entry,
149 struct lustre_sec_desc *lsd;
150 struct lsd_cache_entry *lentry;
151 struct lsd_downcall_args *lsd_args;
152 struct group_info *ginfo;
158 lentry = container_of(entry, struct lsd_cache_entry, base);
160 lsd_args = (struct lsd_downcall_args *) args;
161 LASSERT(lsd_args->ngroups <= NGROUPS_MAX);
164 GOTO(err_ret, lsd_args->err);
166 ginfo = groups_alloc(lsd_args->ngroups);
168 CERROR("failed to alloc %d groups\n", lsd_args->ngroups);
169 GOTO(err_ret, -ENOMEM);
171 groups_from_buffer(ginfo, lsd_args->groups);
174 if (lsd_args->nperms) {
175 size = lsd_args->nperms * sizeof(struct lsd_permission);
176 OBD_ALLOC(lsd->lsd_perms, size);
177 if (!lsd->lsd_perms) {
178 CERROR("failed to alloc %d\n", size);
179 GOTO(err_group, -ENOMEM);
181 if (copy_from_user(lsd->lsd_perms, lsd_args->perms, size)) {
182 CERROR("error copy from user space\n");
183 GOTO(err_free, -EFAULT);
187 lsd->lsd_invalid = 0;
188 lsd->lsd_uid = lsd_args->uid;
189 lsd->lsd_gid = lsd_args->gid;
190 lsd->lsd_ginfo = ginfo;
191 lsd->lsd_nperms = lsd_args->nperms;
193 CWARN("LSD: %d:%d, ngrps %u, nperms %u\n", lsd->lsd_uid, lsd->lsd_gid,
194 lsd->lsd_ginfo ? lsd->lsd_ginfo->ngroups : 0, lsd->lsd_nperms);
198 OBD_FREE(lsd->lsd_perms, size);
199 lsd->lsd_perms = NULL;
201 put_group_info(ginfo);
203 CERROR("LSD downcall error, disable this user for %lus\n",
204 cache->uc_err_entry_expire);
205 lsd->lsd_invalid = 1;
209 struct lustre_sec_desc * mds_get_lsd(__u32 uid)
211 struct upcall_cache *cache = &_lsd_cache;
212 struct upcall_cache_entry *entry;
213 struct lsd_cache_entry *lentry;
215 entry = upcall_cache_get_entry(cache, (__u64) uid);
219 lentry = container_of(entry, struct lsd_cache_entry, base);
220 if (lentry->lsd.lsd_invalid) {
221 upcall_cache_put_entry(&lentry->base);
228 void mds_put_lsd(struct lustre_sec_desc *lsd)
230 struct lsd_cache_entry *lentry;
234 lentry = container_of(lsd, struct lsd_cache_entry, lsd);
235 upcall_cache_put_entry(&lentry->base);
238 int mds_init_lsd_cache()
240 struct upcall_cache *cache = &_lsd_cache;
244 cache->uc_hashtable = _lsd_hashtable;
245 cache->uc_hashsize = MDS_LSD_HASHSIZE;
246 cache->uc_hashlock = RW_LOCK_UNLOCKED;
247 for (i = 0; i < cache->uc_hashsize; i++)
248 INIT_LIST_HEAD(&cache->uc_hashtable[i]);
249 cache->uc_name = "LSD_CACHE";
251 /* set default value, proc tunable */
252 sprintf(cache->uc_upcall, MDS_LSD_UPCALL_PATH);
253 cache->uc_acquire_expire = MDS_LSD_ACQUIRE_EXPIRE;
254 cache->uc_entry_expire = MDS_LSD_ENTRY_EXPIRE;
255 cache->uc_err_entry_expire = MDS_LSD_ERR_ENTRY_EXPIRE;
257 cache->hash = lsd_hash;
258 cache->alloc_entry = lsd_alloc_entry;
259 cache->free_entry = lsd_free_entry;
260 cache->make_upcall = lsd_make_upcall;
261 cache->parse_downcall = lsd_parse_downcall;
266 void mds_flush_lsd(__u32 id)
268 struct upcall_cache *cache = &_lsd_cache;
271 upcall_cache_flush_idle(cache);
273 upcall_cache_flush_one(cache, (__u64) id);
276 void mds_cleanup_lsd_cache()
278 upcall_cache_flush_all(&_lsd_cache);
281 __u32 mds_lsd_get_perms(struct lustre_sec_desc *lsd, __u32 is_remote,
282 ptl_netid_t netid, ptl_nid_t nid)
284 struct lsd_permission *perm = lsd->lsd_perms;
287 for (i = 0; i < lsd->lsd_nperms; i++) {
288 if (perm->netid != PTL_NETID_ANY && perm->netid != netid)
290 if (perm->nid != PTL_NID_ANY && perm->nid != nid)
299 return LSD_PERM_SETGRP;