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/sbin/lacl_upcall"
61 #define RMTACL_ACQUIRE_EXPIRE (20)
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 %s %s\n",
136 argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
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 CERROR("can't copy from userspace\n");
170 desc->upcall_status = -EFAULT;
178 static void mds_rmtacl_upcall(struct rmtacl_upcall_desc *desc)
180 struct upcall_cache *cache = &_rmtacl_upcall_cache;
181 struct upcall_cache_entry *entry;
183 desc->upcall_status = 0;
185 entry = upcall_cache_get_entry(cache, (__u64) ((unsigned long) desc));
187 desc->upcall_status = -EINVAL;
191 UC_CACHE_SET_EXPIRED(entry);
192 upcall_cache_put_entry(entry);
195 int mds_init_rmtacl_upcall_cache()
197 struct upcall_cache *cache = &_rmtacl_upcall_cache;
201 cache->uc_hashtable = _rmtacl_upcall_hashtable;
202 cache->uc_hashsize = RMTACL_UPCALL_HASHSIZE;
203 cache->uc_hashlock = RW_LOCK_UNLOCKED;
204 for (i = 0; i < cache->uc_hashsize; i++)
205 INIT_LIST_HEAD(&cache->uc_hashtable[i]);
206 cache->uc_name = "RMTACL_UPCALL";
208 /* set default value, proc tunable */
209 sprintf(cache->uc_upcall, RMTACL_UPCALL_PATH);
210 cache->uc_acquire_expire = RMTACL_ACQUIRE_EXPIRE;
211 cache->uc_entry_expire = RMTACL_ENTRY_EXPIRE;
212 cache->uc_err_entry_expire = RMTACL_ERR_ENTRY_EXPIRE;
214 cache->hash = rmtacl_hash;
215 cache->alloc_entry = rmtacl_alloc_entry;
216 cache->free_entry = rmtacl_free_entry;
217 cache->make_upcall = rmtacl_make_upcall;
218 cache->parse_downcall = rmtacl_parse_downcall;
223 void mds_cleanup_rmtacl_upcall_cache()
225 struct upcall_cache *cache = &_rmtacl_upcall_cache;
227 LASSERT(list_empty(&cache->uc_hashtable[0]));
230 /****************************************
231 * exported helper functions *
232 ****************************************/
235 * traverse through the mountpoint to find lustre mountpoint
237 static struct vfsmount *mds_get_lustre_mnt(void)
239 struct vfsmount *mnt, *lmnt = NULL;
241 LASSERT(current->fs);
242 read_lock(¤t->fs->lock);
243 mnt = mntget(current->fs->rootmnt);
244 read_unlock(¤t->fs->lock);
247 spin_lock(&vfsmount_lock);
249 if (!strcmp(mnt->mnt_sb->s_type->name, "lustre") ||
250 !strcmp(mnt->mnt_sb->s_type->name, "llite")) {
255 if (!list_empty(&mnt->mnt_mounts)) {
256 mnt = list_entry(mnt->mnt_mounts.next,
257 struct vfsmount, mnt_child);
263 if (list_empty(&mnt->mnt_child) ||
264 mnt->mnt_child.next == &mnt->mnt_parent->mnt_mounts) {
265 /* we are the last child */
266 LASSERT(mnt->mnt_parent != NULL);
267 if (list_empty(&mnt->mnt_child) ||
268 mnt->mnt_parent == NULL)
270 mnt = mnt->mnt_parent;
271 goto follow_siblings;
274 mnt = list_entry(mnt->mnt_child.next, struct vfsmount, mnt_child);
278 spin_unlock(&vfsmount_lock);
283 void mds_do_remote_acl_upcall(struct rmtacl_upcall_desc *desc)
285 struct fs_struct *fs = current->fs;
286 struct vfsmount *lmnt;
287 char *buf = NULL, *mntpnt;
289 lmnt = mds_get_lustre_mnt();
291 desc->upcall_status = -EOPNOTSUPP;
295 OBD_ALLOC(buf, PAGE_SIZE);
297 desc->upcall_status = -ENOMEM;
301 mntpnt = __d_path(lmnt->mnt_root, lmnt, fs->root, fs->rootmnt,
303 if (IS_ERR(mntpnt)) {
304 desc->upcall_status = PTR_ERR(mntpnt);
309 desc->uid = current->uid;
311 mds_rmtacl_upcall(desc);
315 OBD_FREE(buf, PAGE_SIZE);