1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (c) 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"
52 /****************************************
53 * handle remote getfacl/setfacl upcall *
54 ****************************************/
56 #define RMTACL_UPCALL_HASHSIZE (1)
57 static struct upcall_cache _rmtacl_upcall_cache;
58 static struct list_head _rmtacl_upcall_hashtable[RMTACL_UPCALL_HASHSIZE];
60 #define RMTACL_UPCALL_PATH "/usr/bin/lacl_upcall"
61 #define RMTACL_ACQUIRE_EXPIRE (15)
62 #define RMTACL_ENTRY_EXPIRE (0)
63 #define RMTACL_ERR_ENTRY_EXPIRE (0)
65 struct upcall_cache *__mds_get_global_rmtacl_upcall_cache()
67 return &_rmtacl_upcall_cache;
70 static unsigned int rmtacl_hash(struct upcall_cache *cache, __u64 key)
72 LASSERT(cache == &_rmtacl_upcall_cache);
76 static struct upcall_cache_entry *
77 rmtacl_alloc_entry(struct upcall_cache *cache, __u64 key)
79 struct rmtacl_upcall_entry *entry;
81 OBD_ALLOC(entry, sizeof(*entry));
85 upcall_cache_init_entry(cache, &entry->base, key);
86 entry->desc = (struct rmtacl_upcall_desc *) ((unsigned long) key);
91 static void rmtacl_free_entry(struct upcall_cache *cache,
92 struct upcall_cache_entry *entry)
94 struct rmtacl_upcall_entry *rentry;
96 rentry = container_of(entry, struct rmtacl_upcall_entry, base);
97 OBD_FREE(rentry, sizeof(*rentry));
100 static int rmtacl_make_upcall(struct upcall_cache *cache,
101 struct upcall_cache_entry *entry)
103 struct rmtacl_upcall_entry *rentry;
104 struct rmtacl_upcall_desc *desc;
111 rentry = container_of(entry, struct rmtacl_upcall_entry, base);
114 snprintf(keystr, 20, LPX64, entry->ue_key);
115 snprintf(uidstr, 16, "%u", desc->uid);
117 argv[0] = cache->uc_upcall;
120 argv[3] = desc->root;
121 argv[4] = desc->get ? "get" : "set";
126 envp[1] = "PATH=/bin:/usr/bin:/usr/local/bin";
129 rc = USERMODEHELPER(argv[0], argv, envp);
131 CERROR("Error invoking upcall %s: %d; check "
132 "/proc/fs/lustre/mds/lacl_upcall\n",
135 CDEBUG(D_SEC, "Invoked upcall %s %s %s %s\n",
136 argv[0], argv[1], argv[2], argv[3]);
141 static int rmtacl_parse_downcall(struct upcall_cache *cache,
142 struct upcall_cache_entry *entry,
145 struct rmtacl_upcall_entry *rentry;
146 struct rmtacl_upcall_desc *desc;
147 struct rmtacl_downcall_args *rargs;
151 rentry = container_of(entry, struct rmtacl_upcall_entry, base);
153 rargs = (struct rmtacl_downcall_args *) args;
155 desc->status = rargs->status;
157 if (desc->reslen < rargs->reslen) {
158 CERROR("bufsize %u, while %u passed down\n",
159 desc->reslen, rargs->reslen);
160 desc->upcall_status = -ENOMEM;
164 desc->reslen = rargs->reslen;
168 if (copy_from_user(desc->res, rargs->res, rargs->reslen)) {
169 desc->upcall_status = -EFAULT;
177 static void mds_rmtacl_upcall(struct rmtacl_upcall_desc *desc)
179 struct upcall_cache *cache = &_rmtacl_upcall_cache;
180 struct upcall_cache_entry *entry;
182 desc->upcall_status = 0;
184 entry = upcall_cache_get_entry(cache, (__u64) ((unsigned long) desc));
186 desc->upcall_status = -EINVAL;
190 UC_CACHE_SET_EXPIRED(entry);
191 upcall_cache_put_entry(entry);
194 int mds_init_rmtacl_upcall_cache()
196 struct upcall_cache *cache = &_rmtacl_upcall_cache;
200 cache->uc_hashtable = _rmtacl_upcall_hashtable;
201 cache->uc_hashsize = RMTACL_UPCALL_HASHSIZE;
202 cache->uc_hashlock = RW_LOCK_UNLOCKED;
203 for (i = 0; i < cache->uc_hashsize; i++)
204 INIT_LIST_HEAD(&cache->uc_hashtable[i]);
205 cache->uc_name = "RMTACL_UPCALL";
207 /* set default value, proc tunable */
208 sprintf(cache->uc_upcall, RMTACL_UPCALL_PATH);
209 cache->uc_acquire_expire = RMTACL_ACQUIRE_EXPIRE;
210 cache->uc_entry_expire = RMTACL_ENTRY_EXPIRE;
211 cache->uc_err_entry_expire = RMTACL_ERR_ENTRY_EXPIRE;
213 cache->hash = rmtacl_hash;
214 cache->alloc_entry = rmtacl_alloc_entry;
215 cache->free_entry = rmtacl_free_entry;
216 cache->make_upcall = rmtacl_make_upcall;
217 cache->parse_downcall = rmtacl_parse_downcall;
222 void mds_cleanup_rmtacl_upcall_cache()
224 struct upcall_cache *cache = &_rmtacl_upcall_cache;
226 LASSERT(list_empty(&cache->uc_hashtable[0]));
229 /****************************************
230 * exported helper functions *
231 ****************************************/
234 * traverse through the mountpoint to find lustre mountpoint
236 static struct vfsmount *mds_get_lustre_mnt(void)
238 struct vfsmount *mnt, *lmnt = NULL;
240 LASSERT(current->fs);
241 read_lock(¤t->fs->lock);
242 mnt = mntget(current->fs->rootmnt);
243 read_unlock(¤t->fs->lock);
246 spin_lock(&vfsmount_lock);
248 if (!strcmp(mnt->mnt_sb->s_type->name, "lustre") ||
249 !strcmp(mnt->mnt_sb->s_type->name, "llite")) {
254 if (!list_empty(&mnt->mnt_mounts)) {
255 mnt = list_entry(mnt->mnt_mounts.next,
256 struct vfsmount, mnt_child);
262 if (list_empty(&mnt->mnt_child) ||
263 mnt->mnt_child.next == &mnt->mnt_parent->mnt_mounts) {
264 /* we are the last child */
265 LASSERT(mnt->mnt_parent != NULL);
266 if (list_empty(&mnt->mnt_child) ||
267 mnt->mnt_parent == NULL)
269 mnt = mnt->mnt_parent;
270 goto follow_siblings;
273 mnt = list_entry(mnt->mnt_child.next, struct vfsmount, mnt_child);
277 spin_unlock(&vfsmount_lock);
282 void mds_do_remote_acl_upcall(struct rmtacl_upcall_desc *desc)
284 struct fs_struct *fs = current->fs;
285 struct vfsmount *lmnt;
286 char *buf = NULL, *mntpnt;
288 lmnt = mds_get_lustre_mnt();
290 desc->upcall_status = -EOPNOTSUPP;
294 OBD_ALLOC(buf, PAGE_SIZE);
296 desc->upcall_status = -ENOMEM;
300 mntpnt = __d_path(lmnt->mnt_root, lmnt, fs->root, fs->rootmnt,
302 if (IS_ERR(mntpnt)) {
303 desc->upcall_status = PTR_ERR(mntpnt);
308 desc->uid = current->uid;
310 mds_rmtacl_upcall(desc);
314 OBD_FREE(buf, PAGE_SIZE);