Whamcloud - gitweb
- fixed really nasty bug with recovery. Sometimes server sent _two_ replies for one...
[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 #include <linux/config.h>
30 #include <linux/module.h>
31 #include <linux/kernel.h>
32 #include <linux/mm.h>
33 #include <linux/kmod.h>
34 #include <linux/string.h>
35 #include <linux/stat.h>
36 #include <linux/errno.h>
37 #include <linux/version.h>
38 #include <linux/unistd.h>
39 #include <asm/system.h>
40 #include <asm/uaccess.h>
41 #include <linux/fs.h>
42 #include <linux/stat.h>
43 #include <asm/uaccess.h>
44 #include <linux/slab.h>
45 #include <asm/segment.h>
46
47 #include <libcfs/kp30.h>
48 #include <obd.h>
49 #include <obd_class.h>
50 #include <obd_support.h>
51 #include <lustre_net.h>
52 #include <lustre_import.h>
53 #include <lustre_dlm.h>
54 #include <lustre_lib.h>
55 #include <lustre_ucache.h>
56
57 #include "mdt_internal.h"
58
59 #define MAX_CMD_LEN     256
60
61 static void mdt_rmtacl_entry_init(struct upcall_cache_entry *entry, void *args)
62 {
63         struct rmtacl_upcall_data *data = args;
64         struct mdt_rmtacl *acl = &entry->u.acl;
65         char *cmd;
66
67         /* we use address of this cache entry as handle */
68         acl->ra_handle = (__u32)entry;
69         OBD_ALLOC(cmd, strlen(data->aud_cmd) + 1);
70         if (!cmd)
71                 return; /* upcall will fail later! */
72
73         strcpy(cmd, data->aud_cmd);
74         entry->u.acl.ra_cmd = cmd;
75 }
76
77 static void mdt_rmtacl_entry_free(struct upcall_cache *cache,
78                                   struct upcall_cache_entry *entry)
79 {
80         struct mdt_rmtacl *acl = &entry->u.acl;
81         int len;
82
83         if (acl->ra_cmd) {
84                 len = strlen(acl->ra_cmd) + 1;
85                 OBD_FREE(acl->ra_cmd, len);
86         }
87
88         if (acl->ra_buf) {
89                 len = strlen(acl->ra_buf) + 1;
90                 OBD_FREE(acl->ra_buf, len);
91         }
92 }
93
94 static int mdt_rmtacl_upcall_compare(struct upcall_cache *cache,
95                                      struct upcall_cache_entry *entry,
96                                      __u64 key, void *args)
97 {
98         struct rmtacl_upcall_data *data = args;
99
100         LASSERT(entry && data);
101         LASSERT(entry->u.acl.ra_cmd && data->aud_cmd);
102         return strncmp(entry->u.acl.ra_cmd, data->aud_cmd, MAX_CMD_LEN);
103 }
104
105 static int mdt_rmtacl_downcall_compare(struct upcall_cache *cache,
106                                        struct upcall_cache_entry *entry,
107                                        __u64 key, void *args)
108 {
109         struct rmtacl_downcall_data *data = args;
110
111         return entry->u.acl.ra_handle - data->add_handle;
112 }
113
114 static int mdt_rmtacl_do_upcall(struct upcall_cache *cache,
115                                 struct upcall_cache_entry *entry)
116 {
117         struct mdt_rmtacl *acl = &entry->u.acl;
118         char handle[20] = "";
119         char keystr[20] = "";
120         char *argv[] = {
121                   [0] = cache->uc_upcall,
122                   [1] = cache->uc_name,
123                   [2] = keystr,
124                   [3] = handle,
125                   [4] = acl->ra_cmd,
126                   [5] = NULL
127         };
128         char *envp[] = {
129                   [0] = "HOME=/",
130                   [1] = "PATH=/bin:/usr/bin:/sbin:/usr/sbin",
131                   [2] = NULL
132         };
133         int rc;
134         ENTRY;
135
136         if (!acl->ra_cmd)
137                 RETURN(-ENOMEM);
138
139         snprintf(keystr, sizeof(keystr), LPU64, entry->ue_key);
140         snprintf(handle, sizeof(handle), "%u", acl->ra_handle);
141
142         LASSERTF(strcmp(cache->uc_upcall, "NONE"), "no upcall set!");
143
144         CDEBUG(D_INFO, "%s: remote acl upcall %s %s %s %s %s\n",
145                cache->uc_name, argv[0], argv[1], argv[2], argv[3], argv[4]);
146
147         rc = USERMODEHELPER(argv[0], argv, envp);
148         if (rc < 0) {
149                 CERROR("%s: error invoking upcall %s %s %s %s %s: rc %d; "
150                        "check /proc/fs/lustre/mdt/%s/rmtacl_upcall\n",
151                        cache->uc_name, argv[0], argv[1], argv[2], argv[3],
152                        argv[4], rc, cache->uc_name);
153         } else {
154                 CDEBUG(D_HA, "%s: invoked upcall %s %s %s %s %s\n",
155                        cache->uc_name, argv[0], argv[1], argv[2], argv[3],
156                        argv[4]);
157                 rc = 0;
158         }
159         RETURN(rc);
160 }
161
162 static int mdt_rmtacl_parse_downcall(struct upcall_cache *cache,
163                                      struct upcall_cache_entry *entry,
164                                      void *args)
165 {
166         struct mdt_rmtacl *acl = &entry->u.acl;
167         struct rmtacl_downcall_data *data;
168         char *buf;
169         int len;
170         ENTRY;
171
172         data = (struct rmtacl_downcall_data *)args;
173         LASSERT(data);
174
175         len = strlen(data->add_buf) + 1;
176         OBD_ALLOC(buf, len);
177         if (!buf)
178                 RETURN(-ENOMEM);
179
180         memcpy(buf, data->add_buf, len);
181         acl->ra_buf = buf;
182
183         CDEBUG(D_OTHER, "parse mdt acl@%p: %s %s\n",
184                acl, acl->ra_cmd, acl->ra_buf);
185
186         RETURN(0);
187 }
188
189 struct upcall_cache_ops mdt_rmtacl_upcall_cache_ops = {
190         .init_entry       = mdt_rmtacl_entry_init,
191         .free_entry       = mdt_rmtacl_entry_free,
192         .upcall_compare   = mdt_rmtacl_upcall_compare,
193         .downcall_compare = mdt_rmtacl_downcall_compare,
194         .do_upcall        = mdt_rmtacl_do_upcall,
195         .parse_downcall   = mdt_rmtacl_parse_downcall,
196 };
197
198 int mdt_rmtacl_upcall(struct mdt_thread_info *info, unsigned long key,
199                       char *cmd, char *buf, int buflen)
200 {
201         struct ptlrpc_request           *req = mdt_info_req(info);
202         struct obd_device               *obd = req->rq_export->exp_obd;
203         struct mdt_device               *mdt = info->mti_mdt;
204         struct lvfs_ucred               uc;
205         struct lvfs_run_ctxt            saved;
206         struct rmtacl_upcall_data       data;
207         struct upcall_cache_entry       *entry;
208         char                            *tmp = NULL;
209         int                             rc = 0;
210         ENTRY;
211
212         OBD_ALLOC(tmp, PAGE_SIZE);
213         if (!tmp)
214                 RETURN(-ENOMEM);
215
216         data.aud_cmd = cmd;
217
218         uc.luc_uid      = info->mti_uc.mu_uid;
219         uc.luc_gid      = info->mti_uc.mu_gid;
220         uc.luc_fsuid    = info->mti_uc.mu_fsuid;
221         uc.luc_fsgid    = info->mti_uc.mu_fsgid;
222         uc.luc_cap      = info->mti_uc.mu_cap;
223         uc.luc_umask    = info->mti_uc.mu_umask;
224         uc.luc_ginfo    = info->mti_uc.mu_ginfo;
225         uc.luc_identity = info->mti_uc.mu_identity;
226
227         push_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
228         entry = upcall_cache_get_entry(mdt->mdt_rmtacl_cache, (__u64)key,
229                                        &data);
230         pop_ctxt(&saved, &obd->obd_lvfs_ctxt, &uc);
231
232         if (IS_ERR(entry))
233                 GOTO(out, rc = PTR_ERR(entry));
234
235         if (buflen <= strlen(entry->u.acl.ra_buf))
236                 GOTO(out, rc = -EFAULT);
237
238         memcpy(buf, entry->u.acl.ra_buf, strlen(entry->u.acl.ra_buf));
239         /* remote acl operation expire at once! */
240         UC_CACHE_SET_EXPIRED(entry);
241         upcall_cache_put_entry(mdt->mdt_rmtacl_cache, entry);
242
243 out:
244         if (rc)
245                 sprintf(buf, "server processing error: %d\n", rc);
246         OBD_FREE(tmp, PAGE_SIZE);
247         RETURN(0);
248 }