Whamcloud - gitweb
fbc3de38f6cd424b3e789133991fc5e555a2ebb2
[fs/lustre-release.git] / lustre / mds / mds_lsd.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  Copyright (c) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
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.
11  *
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.
16  *
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.
20  */
21
22 #define DEBUG_SUBSYSTEM S_MDS
23
24 #include <linux/config.h>
25 #include <linux/module.h>
26 #include <linux/kernel.h>
27 #include <linux/mm.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>
34
35 #include <asm/system.h>
36 #include <asm/uaccess.h>
37
38 #include <linux/fs.h>
39 #include <linux/stat.h>
40 #include <asm/uaccess.h>
41 #include <linux/slab.h>
42 #include <asm/segment.h>
43
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>
49
50 #include "mds_internal.h"
51
52 /* 
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.
58  */
59
60
61 #define MDS_LSD_HASHSIZE        (256)
62 static struct upcall_cache _lsd_cache;
63 static struct list_head _lsd_hashtable[MDS_LSD_HASHSIZE];
64
65 struct upcall_cache *__mds_get_global_lsd_cache()
66 {
67         return &_lsd_cache;
68 }
69
70 static unsigned int lsd_hash(struct upcall_cache *cache, __u64 key)
71 {
72         LASSERT(cache == &_lsd_cache);
73         return ((__u32) key) & (MDS_LSD_HASHSIZE - 1);
74 }
75
76 static struct upcall_cache_entry *
77 lsd_alloc_entry(struct upcall_cache *cache, __u64 key)
78 {
79         struct lsd_cache_entry *entry;
80         ENTRY;
81
82         OBD_ALLOC(entry, sizeof(*entry));
83         if (!entry) {
84                 CERROR("failed to alloc entry\n");
85                 RETURN(NULL);
86         }
87         upcall_cache_init_entry(cache, &entry->base, key);
88
89         RETURN(&entry->base);
90 }
91
92 static void lsd_free_entry(struct upcall_cache *cache,
93                            struct upcall_cache_entry *entry)
94 {
95         struct lsd_cache_entry *lentry;
96
97         lentry = container_of(entry, struct lsd_cache_entry, base);
98         if (lentry->lsd.lsd_ginfo)
99                 put_group_info(lentry->lsd.lsd_ginfo);
100         OBD_FREE(lentry, sizeof(*lentry));
101 }
102
103
104 static int lsd_make_upcall(struct upcall_cache *cache,
105                            struct upcall_cache_entry *entry)
106 {
107         char *argv[4];
108         char *envp[3];
109         char uidstr[16];
110         int rc;
111         ENTRY;
112
113         snprintf(uidstr, 16, "%u", (__u32) entry->ue_key);
114
115         argv[0] = cache->uc_upcall;
116         argv[1] = uidstr;
117         argv[2] = NULL;
118                                                                                                                         
119         envp[0] = "HOME=/";
120         envp[1] = "PATH=/sbin:/usr/sbin";
121         envp[2] = NULL;
122
123         rc = USERMODEHELPER(argv[0], argv, envp);
124         if (rc < 0) {
125                 CERROR("Error invoking lsd upcall %s %s: %d; check "
126                        "/proc/fs/lustre/mds/lsd_upcall\n",
127                        argv[0], argv[1], rc);
128         } else {
129                 CWARN("Invoked upcall %s %s\n",
130                         argv[0], argv[1]);
131         }
132         RETURN(rc);
133 }
134
135 static int lsd_parse_downcall(struct upcall_cache *cache,
136                               struct upcall_cache_entry *entry,
137                               void *args)
138 {
139         struct lustre_sec_desc *lsd;
140         struct lsd_cache_entry *lentry;
141         struct lsd_downcall_args *lsd_args;
142         struct group_info *ginfo;
143         ENTRY;
144
145         LASSERT(args);
146
147         lentry = container_of(entry, struct lsd_cache_entry, base);
148         lsd = &lentry->lsd;
149         lsd_args = (struct lsd_downcall_args *) args;
150         LASSERT(lsd_args->err == 0);
151         LASSERT(lsd_args->ngroups <= NGROUPS_MAX);
152
153         ginfo = groups_alloc(lsd_args->ngroups);
154         if (!ginfo) {
155                 CERROR("can't alloc group_info for %d groups\n",
156                         lsd_args->ngroups);
157                 RETURN(-ENOMEM);
158         }
159         groups_from_buffer(ginfo, lsd_args->groups);
160         groups_sort(ginfo);
161
162         lsd->lsd_uid = lsd_args->uid;
163         lsd->lsd_gid = lsd_args->gid;
164         lsd->lsd_ginfo = ginfo;
165         lsd->lsd_allow_setuid = lsd_args->allow_setuid;
166         lsd->lsd_allow_setgid = lsd_args->allow_setgid;
167         lsd->lsd_allow_setgrp = lsd_args->allow_setgrp;
168
169         CWARN("LSD: uid %u gid %u ngroups %u, perm (%d/%d/%d)\n",
170               lsd->lsd_uid, lsd->lsd_gid, ginfo->ngroups,
171               lsd->lsd_allow_setuid, lsd->lsd_allow_setgid,
172               lsd->lsd_allow_setgrp);
173         RETURN(0);
174 }
175
176 struct lustre_sec_desc * mds_get_lsd(__u32 uid)
177 {
178         struct upcall_cache *cache = &_lsd_cache;
179         struct upcall_cache_entry *entry;
180         struct lsd_cache_entry *lentry;
181
182         entry = upcall_cache_get_entry(cache, (__u64) uid);
183         if (!entry)
184                 return NULL;
185
186         lentry = container_of(entry, struct lsd_cache_entry, base);
187         return &lentry->lsd;
188 }
189
190 void mds_put_lsd(struct lustre_sec_desc *lsd)
191 {
192         struct lsd_cache_entry *lentry;
193
194         LASSERT(lsd);
195
196         lentry = container_of(lsd, struct lsd_cache_entry, lsd);
197         upcall_cache_put_entry(&lentry->base);
198 }
199
200 int mds_init_lsd_cache()
201 {
202         struct upcall_cache *cache = &_lsd_cache;
203         int i;
204         ENTRY;
205
206         cache->uc_hashtable = _lsd_hashtable;
207         cache->uc_hashsize = MDS_LSD_HASHSIZE;
208         cache->uc_hashlock = RW_LOCK_UNLOCKED;
209         for (i = 0; i < cache->uc_hashsize; i++)
210                 INIT_LIST_HEAD(&cache->uc_hashtable[i]);
211         cache->uc_name = "LSD_CACHE";
212
213         /* set default value, proc tunable */
214         sprintf(cache->uc_upcall, "%s", "/sbin/lsd_upcall");
215         cache->uc_entry_expire = 5 * 60;
216         cache->uc_acquire_expire = 5;
217
218         cache->hash = lsd_hash;
219         cache->alloc_entry = lsd_alloc_entry;
220         cache->free_entry = lsd_free_entry;
221         cache->make_upcall = lsd_make_upcall;
222         cache->parse_downcall = lsd_parse_downcall;
223
224         RETURN(0);
225 }
226
227 void mds_flush_lsd(__u32 id)
228 {
229         struct upcall_cache *cache = &_lsd_cache;
230
231         if (id == -1)
232                 upcall_cache_flush_idle(cache);
233         else
234                 upcall_cache_flush_one(cache, (__u64) id);
235 }
236
237 void mds_cleanup_lsd_cache()
238 {
239         upcall_cache_flush_all(&_lsd_cache);
240 }