1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004-2006 Cluster File Systems, Inc.
5 * Author: Lai Siyao <lsy@clusterfs.com>
6 * Author: Fan Yong <fanyong@clusterfs.com>
8 * This file is part of Lustre, http://www.lustre.org.
10 * Lustre is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation.
14 * Lustre is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with Lustre; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 #define DEBUG_SUBSYSTEM S_MDS
29 #ifndef AUTOCONF_INCLUDED
30 #include <linux/config.h>
32 #include <linux/module.h>
33 #include <linux/kernel.h>
35 #include <linux/kmod.h>
36 #include <linux/string.h>
37 #include <linux/stat.h>
38 #include <linux/errno.h>
39 #include <linux/version.h>
40 #include <linux/unistd.h>
41 #include <asm/system.h>
42 #include <asm/uaccess.h>
44 #include <linux/stat.h>
45 #include <asm/uaccess.h>
46 #include <linux/slab.h>
47 #include <asm/segment.h>
49 #include <libcfs/kp30.h>
51 #include <obd_class.h>
52 #include <obd_support.h>
53 #include <lustre_net.h>
54 #include <lustre_import.h>
55 #include <lustre_dlm.h>
56 #include <lustre_lib.h>
57 #include <lustre_ucache.h>
59 #include "mdt_internal.h"
61 #define MAX_CMD_LEN 256
63 static __u64 rmtacl_key = 0;
64 static spinlock_t rmtacl_key_lock = SPIN_LOCK_UNLOCKED;
67 * For remote acl operation, do NOT cache!
68 * Use different key for each remote acl operation.
70 static __u64 mdt_rmtacl_getkey(void)
74 spin_lock(&rmtacl_key_lock);
76 spin_unlock(&rmtacl_key_lock);
81 static void mdt_rmtacl_entry_init(struct upcall_cache_entry *entry, void *args)
83 struct rmtacl_upcall_data *data = args;
84 struct mdt_rmtacl *acl = &entry->u.acl;
87 acl->ra_uid = data->aud_uid;
88 acl->ra_gid = data->aud_gid;
89 /* we use address of this cache entry as handle */
90 acl->ra_handle = (__u32)entry;
91 OBD_ALLOC(cmd, strlen(data->aud_cmd) + 1);
93 return; /* upcall will fail later! */
95 strcpy(cmd, data->aud_cmd);
99 static void mdt_rmtacl_entry_free(struct upcall_cache *cache,
100 struct upcall_cache_entry *entry)
102 struct mdt_rmtacl *acl = &entry->u.acl;
106 len = strlen(acl->ra_cmd) + 1;
107 OBD_FREE(acl->ra_cmd, len);
111 len = strlen(acl->ra_buf) + 1;
112 OBD_FREE(acl->ra_buf, len);
116 static int mdt_rmtacl_upcall_compare(struct upcall_cache *cache,
117 struct upcall_cache_entry *entry,
118 __u64 key, void *args)
120 struct rmtacl_upcall_data *data = args;
122 LASSERT(entry && data);
123 LASSERT(entry->u.acl.ra_cmd && data->aud_cmd);
124 return strncmp(entry->u.acl.ra_cmd, data->aud_cmd, MAX_CMD_LEN);
127 static int mdt_rmtacl_downcall_compare(struct upcall_cache *cache,
128 struct upcall_cache_entry *entry,
129 __u64 key, void *args)
131 struct rmtacl_downcall_data *data = args;
133 return entry->u.acl.ra_handle - data->add_handle;
136 static int mdt_rmtacl_do_upcall(struct upcall_cache *cache,
137 struct upcall_cache_entry *entry)
139 struct mdt_rmtacl *acl = &entry->u.acl;
142 char handle[20] = "";
143 char keystr[20] = "";
145 [0] = cache->uc_upcall,
148 [3] = cache->uc_name,
156 [1] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
165 snprintf(uidstr, sizeof(uidstr), "%u", acl->ra_uid);
166 snprintf(gidstr, sizeof(gidstr), "%u", acl->ra_gid);
167 snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
168 snprintf(handle, sizeof(handle), "%u", acl->ra_handle);
170 LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
172 CDEBUG(D_INFO, "%s: remote acl upcall %s %s %s %s %s %s %s\n",
173 cache->uc_name, argv[0], argv[1], argv[2], argv[3], argv[4],
176 rc = USERMODEHELPER(argv[0], argv, envp);
178 CERROR("%s: error invoking upcall %s %s %s %s %s %s %s: rc %d; "
179 "check /proc/fs/lustre/mdt/%s/rmtacl_upcall\n",
180 cache->uc_name, argv[0], argv[1], argv[2], argv[3],
181 argv[4], argv[5], argv[6], rc, cache->uc_name);
183 CDEBUG(D_HA, "%s: invoked upcall %s %s %s %s %s %s %s\n",
184 cache->uc_name, argv[0], argv[1], argv[2], argv[3],
185 argv[4], argv[5], argv[6]);
191 static int mdt_rmtacl_parse_downcall(struct upcall_cache *cache,
192 struct upcall_cache_entry *entry,
195 struct mdt_rmtacl *acl = &entry->u.acl;
196 struct rmtacl_downcall_data *data;
201 data = (struct rmtacl_downcall_data *)args;
204 len = strlen(data->add_buf) + 1;
209 memcpy(buf, data->add_buf, len);
212 CDEBUG(D_OTHER, "parse mdt acl@%p: %s %s\n",
213 acl, acl->ra_cmd, acl->ra_buf);
218 struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops = {
219 .init_entry = mdt_rmtacl_entry_init,
220 .free_entry = mdt_rmtacl_entry_free,
221 .upcall_compare = mdt_rmtacl_upcall_compare,
222 .downcall_compare = mdt_rmtacl_downcall_compare,
223 .do_upcall = mdt_rmtacl_do_upcall,
224 .parse_downcall = mdt_rmtacl_parse_downcall,
227 int mdt_rmtacl_upcall(struct mdt_thread_info *info, char *cmd,
230 struct mdt_device *mdt = info->mti_mdt;
231 struct md_ucred *uc = mdt_ucred(info);
232 struct rmtacl_upcall_data data;
233 struct upcall_cache_entry *entry;
238 data.aud_uid = uc->mu_fsuid;
239 data.aud_gid = uc->mu_fsgid;
242 key = mdt_rmtacl_getkey();
244 entry = upcall_cache_get_entry(mdt->mdt_rmtacl_cache, key, &data);
246 GOTO(out, rc = PTR_ERR(entry));
248 if (buf->lb_len <= strlen(entry->u.acl.ra_buf))
249 GOTO(out, rc = -EFAULT);
251 memcpy(buf->lb_buf, entry->u.acl.ra_buf, strlen(entry->u.acl.ra_buf));
252 /* remote acl operation expire at once! */
253 UC_CACHE_SET_EXPIRED(entry);
254 upcall_cache_put_entry(mdt->mdt_rmtacl_cache, entry);
258 sprintf(buf->lb_buf, "server processing error: %d\n", rc);