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 (10)
67 #define MDS_LSD_ENTRY_EXPIRE (10 * 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("%lu: lsd %p Invoked upcall %s %s\n",
140 get_seconds(), entry, argv[0], argv[1]);
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 (%p): %d:%d, ngrps %u, nperms %u\n",
194 lentry, lsd->lsd_uid, lsd->lsd_gid,
195 lsd->lsd_ginfo ? lsd->lsd_ginfo->ngroups : 0, lsd->lsd_nperms);
199 OBD_FREE(lsd->lsd_perms, size);
200 lsd->lsd_perms = NULL;
202 put_group_info(ginfo);
204 CERROR("LSD downcall error, disable this user for %lus\n",
205 cache->uc_err_entry_expire);
206 lsd->lsd_invalid = 1;
210 struct lustre_sec_desc * mds_get_lsd(__u32 uid)
212 struct upcall_cache *cache = &_lsd_cache;
213 struct upcall_cache_entry *entry;
214 struct lsd_cache_entry *lentry;
216 entry = upcall_cache_get_entry(cache, (__u64) uid);
220 lentry = container_of(entry, struct lsd_cache_entry, base);
221 if (lentry->lsd.lsd_invalid) {
222 upcall_cache_put_entry(&lentry->base);
229 void mds_put_lsd(struct lustre_sec_desc *lsd)
231 struct lsd_cache_entry *lentry;
235 lentry = container_of(lsd, struct lsd_cache_entry, lsd);
236 upcall_cache_put_entry(&lentry->base);
239 int mds_init_lsd_cache()
241 struct upcall_cache *cache = &_lsd_cache;
245 cache->uc_hashtable = _lsd_hashtable;
246 cache->uc_hashsize = MDS_LSD_HASHSIZE;
247 cache->uc_hashlock = RW_LOCK_UNLOCKED;
248 for (i = 0; i < cache->uc_hashsize; i++)
249 INIT_LIST_HEAD(&cache->uc_hashtable[i]);
250 cache->uc_name = "LSD_CACHE";
252 /* set default value, proc tunable */
253 sprintf(cache->uc_upcall, MDS_LSD_UPCALL_PATH);
254 cache->uc_acquire_expire = MDS_LSD_ACQUIRE_EXPIRE;
255 cache->uc_entry_expire = MDS_LSD_ENTRY_EXPIRE;
256 cache->uc_err_entry_expire = MDS_LSD_ERR_ENTRY_EXPIRE;
258 cache->hash = lsd_hash;
259 cache->alloc_entry = lsd_alloc_entry;
260 cache->free_entry = lsd_free_entry;
261 cache->make_upcall = lsd_make_upcall;
262 cache->parse_downcall = lsd_parse_downcall;
267 void mds_flush_lsd(__u32 id)
269 struct upcall_cache *cache = &_lsd_cache;
272 upcall_cache_flush_idle(cache);
274 upcall_cache_flush_one(cache, (__u64) id);
277 void mds_cleanup_lsd_cache()
279 upcall_cache_flush_all(&_lsd_cache);
282 __u32 mds_lsd_get_perms(struct lustre_sec_desc *lsd, __u32 is_remote,
283 ptl_netid_t netid, ptl_nid_t nid)
285 struct lsd_permission *perm = lsd->lsd_perms;
288 for (i = 0; i < lsd->lsd_nperms; i++) {
289 if (perm->netid != PTL_NETID_ANY && perm->netid != netid)
291 if (perm->nid != PTL_NID_ANY && perm->nid != nid)
300 return LSD_PERM_SETGRP;