This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / intermezzo / upcall.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2001, 2002 Cluster File Systems, Inc. <braam@clusterfs.com>
5  * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
6  *
7  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
8  *
9  *   InterMezzo is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   InterMezzo is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with InterMezzo; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  *
22  * Mostly platform independent upcall operations to a cache manager:
23  *  -- upcalls
24  *  -- upcall routines
25  *
26  */
27
28 #include <asm/system.h>
29 #include <asm/segment.h>
30 #include <asm/signal.h>
31 #include <linux/signal.h>
32
33 #include <linux/types.h>
34 #include <linux/kernel.h>
35 #include <linux/mm.h>
36 #include <linux/vmalloc.h>
37 #include <linux/slab.h>
38 #include <linux/sched.h>
39 #include <linux/fs.h>
40 #include <linux/stat.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <asm/uaccess.h>
44
45 #include "intermezzo_lib.h"
46 #include "intermezzo_fs.h"
47 #include "intermezzo_psdev.h"
48
49 #include "intermezzo_idl.h"
50
51 /*
52   At present:
53   -- Asynchronous calls:
54    - kml:            give a "more" kml indication to userland
55    - kml_truncate:   initiate KML truncation
56    - release_permit: kernel is done with permit
57   -- Synchronous
58    - open:           fetch file
59    - permit:         get a permit
60
61   Errors returned by user level code are positive
62
63  */
64
65 static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
66                                        char *fsetname, int reclen, char *rec,
67                                        int *size)
68 {
69         struct izo_upcall_hdr *hdr;
70         char *ptr;
71         ENTRY;
72
73         *size = sizeof(struct izo_upcall_hdr);
74         if ( fsetname ) {
75                 *size += round_strlen(fsetname);
76         }
77         if ( path ) { 
78                 *size += round_strlen(path);
79         }
80         if ( rec ) { 
81                 *size += size_round(reclen);
82         }
83         PRESTO_ALLOC(hdr, *size);
84         if (!hdr) { 
85                 CERROR("intermezzo upcall: out of memory (opc %d)\n", opcode);
86                 EXIT;
87                 return NULL;
88         }
89         memset(hdr, 0, *size);
90
91         ptr = (char *)hdr + sizeof(*hdr);
92
93         /* XXX do we need fsuid ? */
94         hdr->u_len = *size;
95         hdr->u_version = IZO_UPC_VERSION;
96         hdr->u_opc = opcode;
97         hdr->u_pid = current->pid;
98         hdr->u_uid = current->fsuid;
99
100         if (path) { 
101                 /*XXX Robert: please review what len to pass in for 
102                   NUL terminated strings */
103                 hdr->u_pathlen = strlen(path);
104                 LOGL0(path, hdr->u_pathlen, ptr);
105         }
106         if (fsetname) { 
107                 hdr->u_fsetlen = strlen(fsetname);
108                 LOGL0(fsetname, strlen(fsetname), ptr);
109         }
110         if (rec) { 
111                 hdr->u_reclen = reclen;
112                 LOGL(rec, reclen, ptr);
113         }
114         
115         EXIT;
116         return hdr;
117 }
118
119 /* the upcalls */
120 int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length, __u32 last_recno, char *fsetname)
121 {
122         int size;
123         int error;
124         struct izo_upcall_hdr *hdr;
125
126         ENTRY;
127         if (!presto_lento_up(minor)) {
128                 EXIT;
129                 return 0;
130         }
131
132         hdr = upc_pack(IZO_UPC_KML, 0, NULL, fsetname, 0, NULL, &size);
133         if (!hdr || IS_ERR(hdr)) {
134                 EXIT;
135                 return -PTR_ERR(hdr);
136         }
137
138         hdr->u_offset = offset;
139         hdr->u_first_recno = first_recno;
140         hdr->u_length = length;
141         hdr->u_last_recno = last_recno;
142
143         CDEBUG(D_UPCALL, "KML: fileset %s, offset %Lu, length %Lu, "
144                "first %u, last %d; minor %d\n",
145                fsetname,
146                (unsigned long long) hdr->u_offset,
147                (unsigned long long) hdr->u_length,
148                hdr->u_first_recno,
149                hdr->u_last_recno, minor);
150
151         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
152
153         EXIT;
154         return -error;
155 }
156
157 int izo_upc_kml_truncate(int minor, __u64 length, __u32 last_recno, char *fsetname)
158 {
159         int size;
160         int error;
161         struct izo_upcall_hdr *hdr;
162
163         ENTRY;
164         if (!presto_lento_up(minor)) {
165                 EXIT;
166                 return 0;
167         }
168
169         hdr = upc_pack(IZO_UPC_KML_TRUNC, 0, NULL, fsetname, 0, NULL, &size);
170         if (!hdr || IS_ERR(hdr)) {
171                 EXIT;
172                 return -PTR_ERR(hdr);
173         }
174
175         hdr->u_length = length;
176         hdr->u_last_recno = last_recno;
177
178         CDEBUG(D_UPCALL, "KML TRUNCATE: fileset %s, length %Lu, "
179                "last recno %d, minor %d\n",
180                fsetname,
181                (unsigned long long) hdr->u_length,
182                hdr->u_last_recno, minor);
183
184         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
185
186         EXIT;
187         return error;
188 }
189
190 int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname, struct lento_vfs_context *info)
191 {
192         int size;
193         int error;
194         struct izo_upcall_hdr *hdr;
195         ENTRY;
196
197         if (!presto_lento_up(minor)) {
198                 EXIT;
199                 return -EIO;
200         }
201
202         hdr = upc_pack(IZO_UPC_OPEN, pathlen, path, fsetname, 
203                        sizeof(*info), (char*)info, &size);
204         if (!hdr || IS_ERR(hdr)) {
205                 EXIT;
206                 return -PTR_ERR(hdr);
207         }
208
209         CDEBUG(D_UPCALL, "path %s\n", path);
210
211         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
212         if (error)
213                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
214
215         EXIT;
216         return -error;
217 }
218
219 int izo_upc_get_fileid(int minor, __u32 reclen, char *rec, 
220                        __u32 pathlen, char *path, char *fsetname)
221 {
222         int size;
223         int error;
224         struct izo_upcall_hdr *hdr;
225         ENTRY;
226
227         if (!presto_lento_up(minor)) {
228                 EXIT;
229                 return -EIO;
230         }
231
232         hdr = upc_pack(IZO_UPC_GET_FILEID, pathlen, path, fsetname, reclen, rec, &size);
233         if (!hdr || IS_ERR(hdr)) {
234                 EXIT;
235                 return -PTR_ERR(hdr);
236         }
237
238         CDEBUG(D_UPCALL, "path %s\n", path);
239
240         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
241         if (error)
242                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
243
244         EXIT;
245         return -error;
246 }
247
248 int izo_upc_backfetch(int minor, char *path, char *fsetname, struct lento_vfs_context *info)
249 {
250         int size;
251         int error;
252         struct izo_upcall_hdr *hdr;
253         ENTRY;
254
255         if (!presto_lento_up(minor)) {
256                 EXIT;
257                 return -EIO;
258         }
259
260         hdr = upc_pack(IZO_UPC_BACKFETCH, strlen(path), path, fsetname, 
261                        sizeof(*info), (char *)info, &size);
262         if (!hdr || IS_ERR(hdr)) {
263                 EXIT;
264                 return -PTR_ERR(hdr);
265         }
266
267         /* This is currently synchronous, kml_reint_record blocks */
268         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
269         if (error)
270                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
271
272         EXIT;
273         return -error;
274 }
275
276 int izo_upc_permit(int minor, struct dentry *dentry, __u32 pathlen, char *path,
277                    char *fsetname)
278 {
279         int size;
280         int error;
281         struct izo_upcall_hdr *hdr;
282
283         ENTRY;
284
285         hdr = upc_pack(IZO_UPC_PERMIT, pathlen, path, fsetname, 0, NULL, &size);
286         if (!hdr || IS_ERR(hdr)) {
287                 EXIT;
288                 return -PTR_ERR(hdr);
289         }
290
291         CDEBUG(D_UPCALL, "Permit minor %d path %s\n", minor, path);
292
293         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
294
295         if (error == -EROFS) {
296                 int err;
297                 CERROR("InterMezzo: ERROR - requested permit for read-only "
298                        "fileset.\n   Setting \"%s\" read-only!\n", path);
299                 err = izo_mark_cache(dentry, 0xFFFFFFFF, CACHE_CLIENT_RO, NULL);
300                 if (err)
301                         CERROR("InterMezzo ERROR: mark_cache %d\n", err);
302         } else if (error) {
303                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
304         }
305
306         EXIT;
307         return error;
308 }
309
310 /* This is a ping-pong upcall handled on the server when a client (uuid)
311  * requests the permit for itself. */
312 int izo_upc_revoke_permit(int minor, char *fsetname, __u8 uuid[16])
313 {
314         int size;
315         int error;
316         struct izo_upcall_hdr *hdr;
317
318         ENTRY;
319
320         hdr = upc_pack(IZO_UPC_REVOKE_PERMIT, 0, NULL, fsetname, 0, NULL, &size);
321         if (!hdr || IS_ERR(hdr)) {
322                 EXIT;
323                 return -PTR_ERR(hdr);
324         }
325
326         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
327
328         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
329
330         if (error)
331                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
332
333         EXIT;
334         return -error;
335 }
336
337 int izo_upc_go_fetch_kml(int minor, char *fsetname, __u8 uuid[16],
338                          __u64 kmlsize)
339 {
340         int size;
341         int error;
342         struct izo_upcall_hdr *hdr;
343         ENTRY;
344
345         if (!presto_lento_up(minor)) {
346                 EXIT;
347                 return -EIO;
348         }
349
350         hdr = upc_pack(IZO_UPC_GO_FETCH_KML, 0, NULL, fsetname, 0, NULL, &size);
351         if (!hdr || IS_ERR(hdr)) {
352                 EXIT;
353                 return -PTR_ERR(hdr);
354         }
355
356         hdr->u_offset = kmlsize;
357         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
358
359         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
360         if (error)
361                 CERROR("%s: error %d\n", __FUNCTION__, error);
362
363         EXIT;
364         return -error;
365 }
366
367 int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
368                     int client_flag)
369 {
370         int size;
371         int error;
372         struct izo_upcall_hdr *hdr;
373         ENTRY;
374
375         if (!presto_lento_up(minor)) {
376                 EXIT;
377                 return -EIO;
378         }
379
380         hdr = upc_pack(IZO_UPC_CONNECT, 0, NULL, NULL, 0, NULL, &size);
381         if (!hdr || IS_ERR(hdr)) {
382                 EXIT;
383                 return -PTR_ERR(hdr);
384         }
385
386         hdr->u_offset = ip_address;
387         hdr->u_length = port;
388         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
389         hdr->u_first_recno = client_flag;
390
391         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
392         if (error) {
393                 CERROR("%s: error %d\n", __FUNCTION__, error);
394         }
395
396         EXIT;
397         return -error;
398 }
399
400 int izo_upc_set_kmlsize(int minor, char *fsetname, __u8 uuid[16], __u64 kmlsize)
401 {
402         int size;
403         int error;
404         struct izo_upcall_hdr *hdr;
405         ENTRY;
406
407         if (!presto_lento_up(minor)) {
408                 EXIT;
409                 return -EIO;
410         }
411
412         hdr = upc_pack(IZO_UPC_SET_KMLSIZE, 0, NULL, fsetname, 0, NULL, &size);
413         if (!hdr || IS_ERR(hdr)) {
414                 EXIT;
415                 return -PTR_ERR(hdr);
416         }
417
418         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
419         hdr->u_length = kmlsize;
420
421         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
422         if (error)
423                 CERROR("%s: error %d\n", __FUNCTION__, error);
424
425         EXIT;
426         return -error;
427 }
428
429 int izo_upc_repstatus(int minor,  char * fsetname, struct izo_rcvd_rec *lr_server)
430 {
431         int size;
432         int error;
433         struct izo_upcall_hdr *hdr;
434         ENTRY;
435
436         if (!presto_lento_up(minor)) {
437                 EXIT;
438                 return -EIO;
439         }
440
441         hdr = upc_pack(IZO_UPC_REPSTATUS, 0, NULL, fsetname, 
442                        sizeof(*lr_server), (char*)lr_server, 
443                        &size);
444         if (!hdr || IS_ERR(hdr)) {
445                 EXIT;
446                 return -PTR_ERR(hdr);
447         }
448
449         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
450         if (error)
451                 CERROR("%s: error %d\n", __FUNCTION__, error);
452
453         EXIT;
454         return -error;
455 }
456
457
458 #if 0
459 int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
460                                char *branchname)
461 {
462         int size, error;
463         struct izo_upcall_hdr *hdr;
464         int pathlen;
465         char *path;
466         ENTRY;
467
468         hdr = upc_pack(IZO_UPC_CLIENT_MAKE_BRANCH, strlen(tagname), tagname,
469                        fsetname, strlen(branchname) + 1, branchname, &size);
470         if (!hdr || IS_ERR(hdr)) {
471                 error = -PTR_ERR(hdr);
472                 goto error;
473         }
474
475         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
476         if (error)
477                 CERROR("InterMezzo: error %d\n", error);
478
479  error:
480         PRESTO_FREE(path, pathlen);
481         EXIT;
482         return error;
483 }
484 #endif
485
486 int izo_upc_server_make_branch(int minor, char *fsetname)
487 {
488         int size, error;
489         struct izo_upcall_hdr *hdr;
490         ENTRY;
491
492         hdr = upc_pack(IZO_UPC_SERVER_MAKE_BRANCH, 0, NULL, fsetname, 0, NULL, &size);
493         if (!hdr || IS_ERR(hdr)) {
494                 error = -PTR_ERR(hdr);
495                 goto error;
496         }
497
498         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
499         if (error)
500                 CERROR("InterMezzo: error %d\n", error);
501
502  error:
503         EXIT;
504         return -error;
505 }
506
507 int izo_upc_branch_undo(int minor, char *fsetname, char *branchname)
508 {
509         int size;
510         int error;
511         struct izo_upcall_hdr *hdr;
512         ENTRY;
513
514         if (!presto_lento_up(minor)) {
515                 EXIT;
516                 return -EIO;
517         }
518
519         hdr = upc_pack(IZO_UPC_BRANCH_UNDO, strlen(branchname), branchname,
520                        fsetname, 0, NULL, &size);
521         if (!hdr || IS_ERR(hdr)) {
522                 EXIT;
523                 return -PTR_ERR(hdr);
524         }
525
526         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
527         if (error)
528                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
529
530         EXIT;
531         return -error;
532 }
533
534 int izo_upc_branch_redo(int minor, char *fsetname, char *branchname)
535 {
536         int size;
537         int error;
538         struct izo_upcall_hdr *hdr;
539         ENTRY;
540
541         if (!presto_lento_up(minor)) {
542                 EXIT;
543                 return -EIO;
544         }
545
546         hdr = upc_pack(IZO_UPC_BRANCH_REDO, strlen(branchname) + 1, branchname,
547                        fsetname, 0, NULL, &size);
548         if (!hdr || IS_ERR(hdr)) {
549                 EXIT;
550                 return -PTR_ERR(hdr);
551         }
552
553         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
554         if (error)
555                 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
556
557         EXIT;
558         return -error;
559 }