Whamcloud - gitweb
- make HEAD from b_post_cmd3
[fs/lustre-release.git] / lustre / mdt / mdt_rmtacl.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2004-2006 Cluster File Systems, Inc.
5  *   Author: Lai Siyao <lsy@clusterfs.com>
6  *   Author: Fan Yong <fanyong@clusterfs.com>
7  *
8  *   This file is part of Lustre, http://www.lustre.org.
9  *
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.
13  *
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.
18  *
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.
22  */
23
24 #ifndef EXPORT_SYMTAB
25 #define EXPORT_SYMTAB
26 #endif
27 #define DEBUG_SUBSYSTEM S_MDS
28
29 #ifdef HAVE_KERNEL_CONFIG_H
30 #include <linux/config.h>
31 #endif
32 #include <linux/module.h>
33 #include <linux/kernel.h>
34 #include <linux/mm.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>
43 #include <linux/fs.h>
44 #include <linux/stat.h>
45 #include <asm/uaccess.h>
46 #include <linux/slab.h>
47 #include <asm/segment.h>
48
49 #include <libcfs/kp30.h>
50 #include <obd.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>
58
59 #include "mdt_internal.h"
60
61 #define MAX_CMD_LEN     256
62
63 static __u64 rmtacl_key = 0;
64 static spinlock_t rmtacl_key_lock = SPIN_LOCK_UNLOCKED;
65
66 /* 
67  * For remote acl operation, do NOT cache!
68  * Use different key for each remote acl operation.
69  */
70 static __u64 mdt_rmtacl_getkey(void)
71 {
72         __u64 key;
73
74         spin_lock(&rmtacl_key_lock);
75         key = ++rmtacl_key;
76         spin_unlock(&rmtacl_key_lock);
77
78         return key;
79 }
80
81 static void mdt_rmtacl_entry_init(struct upcall_cache_entry *entry, void *args)
82 {
83         struct rmtacl_upcall_data *data = args;
84         struct mdt_rmtacl *acl = &entry->u.acl;
85         char *cmd;
86
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);
92         if (!cmd)
93                 return; /* upcall will fail later! */
94
95         strcpy(cmd, data->aud_cmd);
96         acl->ra_cmd = cmd;
97 }
98
99 static void mdt_rmtacl_entry_free(struct upcall_cache *cache,
100                                   struct upcall_cache_entry *entry)
101 {
102         struct mdt_rmtacl *acl = &entry->u.acl;
103         int len;
104
105         if (acl->ra_cmd) {
106                 len = strlen(acl->ra_cmd) + 1;
107                 OBD_FREE(acl->ra_cmd, len);
108         }
109
110         if (acl->ra_buf) {
111                 len = strlen(acl->ra_buf) + 1;
112                 OBD_FREE(acl->ra_buf, len);
113         }
114 }
115
116 static int mdt_rmtacl_upcall_compare(struct upcall_cache *cache,
117                                      struct upcall_cache_entry *entry,
118                                      __u64 key, void *args)
119 {
120         struct rmtacl_upcall_data *data = args;
121
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);
125 }
126
127 static int mdt_rmtacl_downcall_compare(struct upcall_cache *cache,
128                                        struct upcall_cache_entry *entry,
129                                        __u64 key, void *args)
130 {
131         struct rmtacl_downcall_data *data = args;
132
133         return entry->u.acl.ra_handle - data->add_handle;
134 }
135
136 static int mdt_rmtacl_do_upcall(struct upcall_cache *cache,
137                                 struct upcall_cache_entry *entry)
138 {
139         struct mdt_rmtacl *acl = &entry->u.acl;
140         char uidstr[8] = "";
141         char gidstr[8] = "";
142         char handle[20] = "";
143         char keystr[20] = "";
144         char *argv[] = {
145                   [0] = cache->uc_upcall,
146                   [1] = uidstr,
147                   [2] = gidstr,
148                   [3] = cache->uc_name,
149                   [4] = keystr,
150                   [5] = handle,
151                   [6] = acl->ra_cmd,
152                   [7] = NULL
153         };
154         char *envp[] = {
155                   [0] = "HOME=/",
156                   [1] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
157                   [2] = NULL
158         };
159         int rc;
160         ENTRY;
161
162         if (!acl->ra_cmd)
163                 RETURN(-ENOMEM);
164
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);
169
170         LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
171
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],
174                argv[5], argv[6]);
175
176         rc = USERMODEHELPER(argv[0], argv, envp);
177         if (rc < 0) {
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);
182         } else {
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]);
186                 rc = 0;
187         }
188         RETURN(rc);
189 }
190
191 static int mdt_rmtacl_parse_downcall(struct upcall_cache *cache,
192                                      struct upcall_cache_entry *entry,
193                                      void *args)
194 {
195         struct mdt_rmtacl *acl = &entry->u.acl;
196         struct rmtacl_downcall_data *data;
197         char *buf;
198         int len;
199         ENTRY;
200
201         data = (struct rmtacl_downcall_data *)args;
202         LASSERT(data);
203
204         len = strlen(data->add_buf) + 1;
205         OBD_ALLOC(buf, len);
206         if (!buf)
207                 RETURN(-ENOMEM);
208
209         memcpy(buf, data->add_buf, len);
210         acl->ra_buf = buf;
211
212         CDEBUG(D_OTHER, "parse mdt acl@%p: %s %s\n",
213                acl, acl->ra_cmd, acl->ra_buf);
214
215         RETURN(0);
216 }
217
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,
225 };
226
227 int mdt_rmtacl_upcall(struct mdt_thread_info *info, char *cmd,
228                       struct lu_buf *buf)
229 {
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;
234         __u64                           key;
235         int                             rc  = 0;
236         ENTRY;
237
238         data.aud_uid = uc->mu_fsuid;
239         data.aud_gid = uc->mu_fsgid;
240         data.aud_cmd = cmd;
241
242         key = mdt_rmtacl_getkey();
243
244         entry = upcall_cache_get_entry(mdt->mdt_rmtacl_cache, key, &data);
245         if (IS_ERR(entry))
246                 GOTO(out, rc = PTR_ERR(entry));
247
248         if (buf->lb_len <= strlen(entry->u.acl.ra_buf))
249                 GOTO(out, rc = -EFAULT);
250
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);
255
256 out:
257         if (rc)
258                 sprintf(buf->lb_buf, "server processing error: %d\n", rc);
259         RETURN(0);
260 }