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/locks.h>
43 #include <linux/string.h>
44 #include <asm/uaccess.h>
45 #include <linux/vmalloc.h>
46 #include <asm/segment.h>
48 #include <linux/intermezzo_lib.h>
49 #include <linux/intermezzo_fs.h>
50 #include <linux/intermezzo_psdev.h>
52 #include <linux/intermezzo_idl.h>
56 -- Asynchronous calls:
57 - kml: give a "more" kml indication to userland
58 - kml_truncate: initiate KML truncation
59 - release_permit: kernel is done with permit
62 - permit: get a permit
64 Errors returned by user level code are positive
68 static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
69 char *fsetname, int reclen, char *rec,
72 struct izo_upcall_hdr *hdr;
76 *size = sizeof(struct izo_upcall_hdr);
78 *size += round_strlen(fsetname);
81 *size += round_strlen(path);
84 *size += size_round(reclen);
86 PRESTO_ALLOC(hdr, *size);
88 CERROR("intermezzo upcall: out of memory (opc %d)\n", opcode);
92 memset(hdr, 0, *size);
94 ptr = (char *)hdr + sizeof(*hdr);
96 /* XXX do we need fsuid ? */
98 hdr->u_version = IZO_UPC_VERSION;
100 hdr->u_pid = current->pid;
101 hdr->u_uid = current->fsuid;
104 /*XXX Robert: please review what len to pass in for
105 NUL terminated strings */
106 hdr->u_pathlen = strlen(path);
107 LOGL0(path, hdr->u_pathlen, ptr);
110 hdr->u_fsetlen = strlen(fsetname);
111 LOGL0(fsetname, strlen(fsetname), ptr);
114 hdr->u_reclen = reclen;
115 LOGL(rec, reclen, ptr);
123 int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length, __u32 last_recno, char *fsetname)
127 struct izo_upcall_hdr *hdr;
130 if (!presto_lento_up(minor)) {
135 hdr = upc_pack(IZO_UPC_KML, 0, NULL, fsetname, 0, NULL, &size);
136 if (!hdr || IS_ERR(hdr)) {
138 return -PTR_ERR(hdr);
141 hdr->u_offset = offset;
142 hdr->u_first_recno = first_recno;
143 hdr->u_length = length;
144 hdr->u_last_recno = last_recno;
146 CDEBUG(D_UPCALL, "KML: fileset %s, offset %Lu, length %Lu, "
147 "first %u, last %d; minor %d\n",
148 fsetname, hdr->u_offset, hdr->u_length, hdr->u_first_recno,
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",
180 fsetname, hdr->u_length, hdr->u_last_recno, minor);
182 error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
188 int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname, struct lento_vfs_context *info)
192 struct izo_upcall_hdr *hdr;
195 if (!presto_lento_up(minor)) {
200 hdr = upc_pack(IZO_UPC_OPEN, pathlen, path, fsetname,
201 sizeof(*info), (char*)info, &size);
202 if (!hdr || IS_ERR(hdr)) {
204 return -PTR_ERR(hdr);
207 CDEBUG(D_UPCALL, "path %s\n", path);
209 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
211 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
217 int izo_upc_get_fileid(int minor, __u32 reclen, char *rec,
218 __u32 pathlen, char *path, char *fsetname)
222 struct izo_upcall_hdr *hdr;
225 if (!presto_lento_up(minor)) {
230 hdr = upc_pack(IZO_UPC_GET_FILEID, pathlen, path, fsetname, reclen, rec, &size);
231 if (!hdr || IS_ERR(hdr)) {
233 return -PTR_ERR(hdr);
236 CDEBUG(D_UPCALL, "path %s\n", path);
238 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
240 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
246 int izo_upc_backfetch(int minor, char *path, char *fsetname, struct lento_vfs_context *info)
250 struct izo_upcall_hdr *hdr;
253 if (!presto_lento_up(minor)) {
258 hdr = upc_pack(IZO_UPC_BACKFETCH, strlen(path), path, fsetname,
259 sizeof(*info), (char *)info, &size);
260 if (!hdr || IS_ERR(hdr)) {
262 return -PTR_ERR(hdr);
265 /* This is currently synchronous, kml_reint_record blocks */
266 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
268 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
274 int izo_upc_permit(int minor, struct dentry *dentry, __u32 pathlen, char *path,
279 struct izo_upcall_hdr *hdr;
283 hdr = upc_pack(IZO_UPC_PERMIT, pathlen, path, fsetname, 0, NULL, &size);
284 if (!hdr || IS_ERR(hdr)) {
286 return -PTR_ERR(hdr);
289 CDEBUG(D_UPCALL, "Permit minor %d path %s\n", minor, path);
291 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
293 if (error == -EROFS) {
295 CERROR("InterMezzo: ERROR - requested permit for read-only "
296 "fileset.\n Setting \"%s\" read-only!\n", path);
297 err = izo_mark_cache(dentry, 0xFFFFFFFF, CACHE_CLIENT_RO, NULL);
299 CERROR("InterMezzo ERROR: mark_cache %d\n", err);
301 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
308 /* This is a ping-pong upcall handled on the server when a client (uuid)
309 * requests the permit for itself. */
310 int izo_upc_revoke_permit(int minor, char *fsetname, __u8 uuid[16])
314 struct izo_upcall_hdr *hdr;
318 hdr = upc_pack(IZO_UPC_REVOKE_PERMIT, 0, NULL, fsetname, 0, NULL, &size);
319 if (!hdr || IS_ERR(hdr)) {
321 return -PTR_ERR(hdr);
324 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
326 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
329 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
335 int izo_upc_go_fetch_kml(int minor, char *fsetname, __u8 uuid[16],
340 struct izo_upcall_hdr *hdr;
343 if (!presto_lento_up(minor)) {
348 hdr = upc_pack(IZO_UPC_GO_FETCH_KML, 0, NULL, fsetname, 0, NULL, &size);
349 if (!hdr || IS_ERR(hdr)) {
351 return -PTR_ERR(hdr);
354 hdr->u_offset = kmlsize;
355 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
357 error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
359 CERROR("%s: error %d\n", __FUNCTION__, error);
365 int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
370 struct izo_upcall_hdr *hdr;
373 if (!presto_lento_up(minor)) {
378 hdr = upc_pack(IZO_UPC_CONNECT, 0, NULL, NULL, 0, NULL, &size);
379 if (!hdr || IS_ERR(hdr)) {
381 return -PTR_ERR(hdr);
384 hdr->u_offset = ip_address;
385 hdr->u_length = port;
386 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
387 hdr->u_first_recno = client_flag;
389 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
391 CERROR("%s: error %d\n", __FUNCTION__, error);
398 int izo_upc_set_kmlsize(int minor, char *fsetname, __u8 uuid[16], __u64 kmlsize)
402 struct izo_upcall_hdr *hdr;
405 if (!presto_lento_up(minor)) {
410 hdr = upc_pack(IZO_UPC_SET_KMLSIZE, 0, NULL, fsetname, 0, NULL, &size);
411 if (!hdr || IS_ERR(hdr)) {
413 return -PTR_ERR(hdr);
416 memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
417 hdr->u_length = kmlsize;
419 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
421 CERROR("%s: error %d\n", __FUNCTION__, error);
427 int izo_upc_repstatus(int minor, char * fsetname, struct izo_rcvd_rec *lr_server)
431 struct izo_upcall_hdr *hdr;
434 if (!presto_lento_up(minor)) {
439 hdr = upc_pack(IZO_UPC_REPSTATUS, 0, NULL, fsetname,
440 sizeof(*lr_server), (char*)lr_server,
442 if (!hdr || IS_ERR(hdr)) {
444 return -PTR_ERR(hdr);
447 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
449 CERROR("%s: error %d\n", __FUNCTION__, error);
457 int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
461 struct izo_upcall_hdr *hdr;
466 hdr = upc_pack(IZO_UPC_CLIENT_MAKE_BRANCH, strlen(tagname), tagname,
467 fsetname, strlen(branchname) + 1, branchname, &size);
468 if (!hdr || IS_ERR(hdr)) {
469 error = -PTR_ERR(hdr);
473 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
475 CERROR("InterMezzo: error %d\n", error);
478 PRESTO_FREE(path, pathlen);
484 int izo_upc_server_make_branch(int minor, char *fsetname)
487 struct izo_upcall_hdr *hdr;
490 hdr = upc_pack(IZO_UPC_SERVER_MAKE_BRANCH, 0, NULL, fsetname, 0, NULL, &size);
491 if (!hdr || IS_ERR(hdr)) {
492 error = -PTR_ERR(hdr);
496 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
498 CERROR("InterMezzo: error %d\n", error);
505 int izo_upc_branch_undo(int minor, char *fsetname, char *branchname)
509 struct izo_upcall_hdr *hdr;
512 if (!presto_lento_up(minor)) {
517 hdr = upc_pack(IZO_UPC_BRANCH_UNDO, strlen(branchname), branchname,
518 fsetname, 0, NULL, &size);
519 if (!hdr || IS_ERR(hdr)) {
521 return -PTR_ERR(hdr);
524 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
526 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);
532 int izo_upc_branch_redo(int minor, char *fsetname, char *branchname)
536 struct izo_upcall_hdr *hdr;
539 if (!presto_lento_up(minor)) {
544 hdr = upc_pack(IZO_UPC_BRANCH_REDO, strlen(branchname) + 1, branchname,
545 fsetname, 0, NULL, &size);
546 if (!hdr || IS_ERR(hdr)) {
548 return -PTR_ERR(hdr);
551 error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
553 CERROR("InterMezzo: %s: error %d\n", __FUNCTION__, error);