1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2001, 2002 Cluster File Systems, Inc. <braam@clusterfs.com>
5 * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
7 * This file is part of InterMezzo, http://www.inter-mezzo.org.
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.
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.
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.
22 * Mostly platform independent upcall operations to a cache manager:
28 #include <asm/system.h>
29 #include <asm/segment.h>
30 #include <asm/signal.h>
31 #include <linux/signal.h>
33 #include <linux/types.h>
34 #include <linux/kernel.h>
36 #include <linux/vmalloc.h>
37 #include <linux/slab.h>
38 #include <linux/sched.h>
40 #include <linux/stat.h>
41 #include <linux/errno.h>
42 #include <linux/string.h>
43 #include <asm/uaccess.h>
45 #include "intermezzo_lib.h"
46 #include "intermezzo_fs.h"
47 #include "intermezzo_psdev.h"
49 #include "intermezzo_idl.h"
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
59 - permit: get a permit
61 Errors returned by user level code are positive
65 static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
66 char *fsetname, int reclen, char *rec,
69 struct izo_upcall_hdr *hdr;
73 *size = sizeof(struct izo_upcall_hdr);
75 *size += round_strlen(fsetname);
78 *size += round_strlen(path);
81 *size += size_round(reclen);
83 PRESTO_ALLOC(hdr, *size);
85 CERROR("intermezzo upcall: out of memory (opc %d)\n", opcode);
89 memset(hdr, 0, *size);
91 ptr = (char *)hdr + sizeof(*hdr);
93 /* XXX do we need fsuid ? */
95 hdr->u_version = IZO_UPC_VERSION;
97 hdr->u_pid = current->pid;
98 hdr->u_uid = current->fsuid;
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);
107 hdr->u_fsetlen = strlen(fsetname);
108 LOGL0(fsetname, strlen(fsetname), ptr);
111 hdr->u_reclen = reclen;
112 LOGL(rec, reclen, ptr);
120 int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length, __u32 last_recno, char *fsetname)
124 struct izo_upcall_hdr *hdr;
127 if (!presto_lento_up(minor)) {
132 hdr = upc_pack(IZO_UPC_KML, 0, NULL, fsetname, 0, NULL, &size);
133 if (!hdr || IS_ERR(hdr)) {
135 return -PTR_ERR(hdr);
138 hdr->u_offset = offset;
139 hdr->u_first_recno = first_recno;
140 hdr->u_length = length;
141 hdr->u_last_recno = last_recno;
143 CDEBUG(D_UPCALL, "KML: fileset %s, offset %Lu, length %Lu, "
144 "first %u, last %d; minor %d\n",
146 (unsigned long long) hdr->u_offset,
147 (unsigned long long) hdr->u_length,
149 hdr->u_last_recno, minor);
151 error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
157 int izo_upc_kml_truncate(int minor, __u64 length, __u32 last_recno, char *fsetname)
161 struct izo_upcall_hdr *hdr;
164 if (!presto_lento_up(minor)) {
169 hdr = upc_pack(IZO_UPC_KML_TRUNC, 0, NULL, fsetname, 0, NULL, &size);
170 if (!hdr || IS_ERR(hdr)) {
172 return -PTR_ERR(hdr);
175 hdr->u_length = length;
176 hdr->u_last_recno = last_recno;
178 CDEBUG(D_UPCALL, "KML TRUNCATE: fileset %s, length %Lu, "
179 "last recno %d, minor %d\n",
181 (unsigned long long) hdr->u_length,
182 hdr->u_last_recno, minor);
184 error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
190 int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname, struct lento_vfs_context *info)
194 struct izo_upcall_hdr *hdr;
197 if (!presto_lento_up(minor)) {
202 hdr = upc_pack(IZO_UPC_OPEN, pathlen, path, fsetname,
203 sizeof(*info), (char*)info, &size);
204 if (!hdr || IS_ERR(hdr)) {
206 return -PTR_ERR(hdr);
209 CDEBUG(D_UPCALL, "path %s\n", path);
211 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
213 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
219 int izo_upc_get_fileid(int minor, __u32 reclen, char *rec,
220 __u32 pathlen, char *path, char *fsetname)
224 struct izo_upcall_hdr *hdr;
227 if (!presto_lento_up(minor)) {
232 hdr = upc_pack(IZO_UPC_GET_FILEID, pathlen, path, fsetname, reclen, rec, &size);
233 if (!hdr || IS_ERR(hdr)) {
235 return -PTR_ERR(hdr);
238 CDEBUG(D_UPCALL, "path %s\n", path);
240 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
242 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
248 int izo_upc_backfetch(int minor, char *path, char *fsetname, struct lento_vfs_context *info)
252 struct izo_upcall_hdr *hdr;
255 if (!presto_lento_up(minor)) {
260 hdr = upc_pack(IZO_UPC_BACKFETCH, strlen(path), path, fsetname,
261 sizeof(*info), (char *)info, &size);
262 if (!hdr || IS_ERR(hdr)) {
264 return -PTR_ERR(hdr);
267 /* This is currently synchronous, kml_reint_record blocks */
268 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
270 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
276 int izo_upc_permit(int minor, struct dentry *dentry, __u32 pathlen, char *path,
281 struct izo_upcall_hdr *hdr;
285 hdr = upc_pack(IZO_UPC_PERMIT, pathlen, path, fsetname, 0, NULL, &size);
286 if (!hdr || IS_ERR(hdr)) {
288 return -PTR_ERR(hdr);
291 CDEBUG(D_UPCALL, "Permit minor %d path %s\n", minor, path);
293 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
295 if (error == -EROFS) {
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);
301 CERROR("InterMezzo ERROR: mark_cache %d\n", err);
303 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
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])
316 struct izo_upcall_hdr *hdr;
320 hdr = upc_pack(IZO_UPC_REVOKE_PERMIT, 0, NULL, fsetname, 0, NULL, &size);
321 if (!hdr || IS_ERR(hdr)) {
323 return -PTR_ERR(hdr);
326 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
328 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
331 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
337 int izo_upc_go_fetch_kml(int minor, char *fsetname, __u8 uuid[16],
342 struct izo_upcall_hdr *hdr;
345 if (!presto_lento_up(minor)) {
350 hdr = upc_pack(IZO_UPC_GO_FETCH_KML, 0, NULL, fsetname, 0, NULL, &size);
351 if (!hdr || IS_ERR(hdr)) {
353 return -PTR_ERR(hdr);
356 hdr->u_offset = kmlsize;
357 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
359 error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
361 CERROR("%s: error %d\n", __FUNCTION__, error);
367 int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
372 struct izo_upcall_hdr *hdr;
375 if (!presto_lento_up(minor)) {
380 hdr = upc_pack(IZO_UPC_CONNECT, 0, NULL, NULL, 0, NULL, &size);
381 if (!hdr || IS_ERR(hdr)) {
383 return -PTR_ERR(hdr);
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;
391 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
393 CERROR("%s: error %d\n", __FUNCTION__, error);
400 int izo_upc_set_kmlsize(int minor, char *fsetname, __u8 uuid[16], __u64 kmlsize)
404 struct izo_upcall_hdr *hdr;
407 if (!presto_lento_up(minor)) {
412 hdr = upc_pack(IZO_UPC_SET_KMLSIZE, 0, NULL, fsetname, 0, NULL, &size);
413 if (!hdr || IS_ERR(hdr)) {
415 return -PTR_ERR(hdr);
418 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
419 hdr->u_length = kmlsize;
421 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
423 CERROR("%s: error %d\n", __FUNCTION__, error);
429 int izo_upc_repstatus(int minor, char * fsetname, struct izo_rcvd_rec *lr_server)
433 struct izo_upcall_hdr *hdr;
436 if (!presto_lento_up(minor)) {
441 hdr = upc_pack(IZO_UPC_REPSTATUS, 0, NULL, fsetname,
442 sizeof(*lr_server), (char*)lr_server,
444 if (!hdr || IS_ERR(hdr)) {
446 return -PTR_ERR(hdr);
449 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
451 CERROR("%s: error %d\n", __FUNCTION__, error);
459 int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
463 struct izo_upcall_hdr *hdr;
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);
475 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
477 CERROR("InterMezzo: error %d\n", error);
480 PRESTO_FREE(path, pathlen);
486 int izo_upc_server_make_branch(int minor, char *fsetname)
489 struct izo_upcall_hdr *hdr;
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);
498 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
500 CERROR("InterMezzo: error %d\n", error);
507 int izo_upc_branch_undo(int minor, char *fsetname, char *branchname)
511 struct izo_upcall_hdr *hdr;
514 if (!presto_lento_up(minor)) {
519 hdr = upc_pack(IZO_UPC_BRANCH_UNDO, strlen(branchname), branchname,
520 fsetname, 0, NULL, &size);
521 if (!hdr || IS_ERR(hdr)) {
523 return -PTR_ERR(hdr);
526 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
528 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
534 int izo_upc_branch_redo(int minor, char *fsetname, char *branchname)
538 struct izo_upcall_hdr *hdr;
541 if (!presto_lento_up(minor)) {
546 hdr = upc_pack(IZO_UPC_BRANCH_REDO, strlen(branchname) + 1, branchname,
547 fsetname, 0, NULL, &size);
548 if (!hdr || IS_ERR(hdr)) {
550 return -PTR_ERR(hdr);
553 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
555 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);