| /* |
| * Mostly platform independent upcall operations to Venus: |
| * -- upcalls |
| * -- upcall routines |
| * |
| * Linux 2.0 version |
| * Copyright (C) 1996 Peter J. Braam <braam@cs.cmu.edu>, |
| * Michael Callahan <callahan@maths.ox.ac.uk> |
| * |
| * Redone for Linux 2.1 |
| * Copyright (C) 1997 Carnegie Mellon University |
| * |
| * Carnegie Mellon University encourages users of this code to contribute |
| * improvements to the Coda project. Contact Peter Braam <coda@cs.cmu.edu>. |
| * |
| * Much cleaned up for InterMezzo |
| * Copyright (C) 1998 Peter J. Braam <braam@cs.cmu.edu>, |
| * Copyright (C) 1999 Carnegie Mellon University |
| * |
| */ |
| |
| #include <asm/system.h> |
| #include <asm/signal.h> |
| #include <linux/signal.h> |
| |
| #include <linux/types.h> |
| #include <linux/kernel.h> |
| #include <linux/mm.h> |
| #include <linux/vmalloc.h> |
| #include <linux/slab.h> |
| #include <linux/time.h> |
| #include <linux/fs.h> |
| #include <linux/stat.h> |
| #include <linux/errno.h> |
| #include <linux/locks.h> |
| #include <linux/string.h> |
| #include <asm/uaccess.h> |
| #include <linux/vmalloc.h> |
| |
| #include <linux/intermezzo_fs.h> |
| #include <linux/intermezzo_upcall.h> |
| #include <linux/intermezzo_psdev.h> |
| |
| /* |
| At present: four upcalls |
| - opendir: fetch a directory (synchronous & asynchronous) |
| - open: fetch file (synchronous) |
| - journal: send a journal page (asynchronous) |
| - permit: get a permit (synchronous) |
| |
| Errors returned here are positive. |
| |
| */ |
| |
| |
| #define INSIZE(tag) sizeof(struct lento_ ## tag ## _in) |
| #define OUTSIZE(tag) sizeof(struct lento_ ## tag ## _out) |
| #define SIZE(tag) ( (INSIZE(tag)>OUTSIZE(tag)) ? INSIZE(tag) : OUTSIZE(tag) ) |
| |
| #define UPARG(op)\ |
| do {\ |
| PRESTO_ALLOC(inp, union up_args *, insize);\ |
| if ( !inp ) { return -ENOMEM; }\ |
| outp = (union down_args *) (inp);\ |
| inp->uh.opcode = (op);\ |
| inp->uh.pid = current->pid;\ |
| inp->uh.uid = current->fsuid;\ |
| outsize = insize;\ |
| } while (0) |
| |
| #define BUFF_ALLOC(buffer) \ |
| PRESTO_ALLOC(buffer, char *, PAGE_SIZE); \ |
| if ( !buffer ) { \ |
| printk("PRESTO: out of memory!\n"); \ |
| return -ENOMEM; \ |
| } |
| |
| /* the upcalls */ |
| int lento_kml(int minor, unsigned int offset, unsigned int first_recno, |
| unsigned int length, unsigned int last_recno, int namelen, |
| char *fsetname) |
| { |
| union up_args *inp; |
| union down_args *outp; |
| int insize, outsize, error; |
| ENTRY; |
| |
| if (!presto_lento_up(minor)) { |
| EXIT; |
| return 0; |
| } |
| |
| insize = SIZE(kml) + namelen + 1; |
| UPARG(LENTO_KML); |
| inp->lento_kml.namelen = namelen; |
| memcpy(inp->lento_kml.fsetname, fsetname, namelen); |
| inp->lento_kml.fsetname[namelen] = '\0'; |
| inp->lento_kml.offset = offset; |
| inp->lento_kml.first_recno = first_recno; |
| inp->lento_kml.length = length; |
| inp->lento_kml.last_recno = last_recno; |
| |
| CDEBUG(D_UPCALL, "KML: fileset %s, offset %d, length %d, " |
| "first %d, last %d; minor %d\n", |
| inp->lento_kml.fsetname, |
| inp->lento_kml.offset, |
| inp->lento_kml.length, |
| inp->lento_kml.first_recno, |
| inp->lento_kml.last_recno, minor); |
| |
| error = lento_upcall(minor, insize, &outsize, inp, |
| ASYNCHRONOUS, NULL); |
| |
| EXIT; |
| return error; |
| } |
| |
| int lento_release_permit( int minor, int mycookie ) |
| { |
| union up_args *inp; |
| union down_args *outp; |
| int insize, outsize, error; |
| ENTRY; |
| |
| if (!presto_lento_up(minor)) { |
| EXIT; |
| return 0; |
| } |
| |
| insize= SIZE(response_cookie); |
| UPARG(LENTO_COOKIE); |
| inp->lento_response_cookie.cookie= mycookie; |
| |
| CDEBUG(D_UPCALL, "cookie %d\n", mycookie); |
| |
| error = lento_upcall(minor, insize, &outsize, inp, |
| ASYNCHRONOUS, NULL); |
| |
| EXIT; |
| return error; |
| } |
| |
| int lento_opendir(int minor, int pathlen, char *path, int async) |
| { |
| union up_args *inp; |
| union down_args *outp; |
| int insize, outsize, error; |
| ENTRY; |
| |
| insize = SIZE(opendir) + pathlen + 1; |
| UPARG(LENTO_OPENDIR); |
| inp->lento_opendir.async = async; |
| inp->lento_opendir.pathlen = pathlen; |
| memcpy(inp->lento_opendir.path, path, pathlen); |
| inp->lento_opendir.path[pathlen] = '\0'; |
| |
| CDEBUG(D_UPCALL, "path %s\n", inp->lento_opendir.path); |
| |
| if (async) { |
| error = lento_upcall(minor, insize, &outsize, inp, |
| ASYNCHRONOUS, NULL); |
| return 0; |
| } |
| |
| error = lento_upcall(minor, insize, &outsize, inp, |
| SYNCHRONOUS, NULL); |
| if (error && error != EISFSETROOT) { |
| printk("lento_opendir: error %d\n", error); |
| } |
| |
| EXIT; |
| return error; |
| } |
| |
| int lento_open(int minor, int pathlen, char *path) |
| { |
| union up_args *inp; |
| union down_args *outp; |
| int insize, outsize, error; |
| |
| ENTRY; |
| insize = SIZE(open) + pathlen + 1; |
| UPARG(LENTO_OPEN); |
| inp->lento_open.pathlen = pathlen; |
| memcpy(inp->lento_open.path, path, pathlen); |
| inp->lento_open.path[pathlen] = '\0'; |
| |
| CDEBUG(D_UPCALL, "path %s\n", inp->lento_open.path); |
| |
| error = lento_upcall(minor, insize, &outsize, inp, |
| SYNCHRONOUS, NULL); |
| if (error) { |
| printk("lento_open: error %d\n", error); |
| } |
| |
| EXIT; |
| return error; |
| } |
| |
| |
| int lento_permit(int minor, int pathlen, int fsetnamelen, char *path, char *fsetname) |
| { |
| union up_args *inp; |
| union down_args *outp; |
| int insize, outsize, error; |
| ENTRY; |
| |
| insize = SIZE(permit) + pathlen + 1 + fsetnamelen + 1; |
| UPARG(LENTO_PERMIT); |
| inp->lento_permit.pathlen = pathlen; |
| inp->lento_permit.fsetnamelen = fsetnamelen; |
| |
| memcpy(inp->lento_permit.path, path, pathlen); |
| inp->lento_permit.path[pathlen] = '\0'; |
| |
| memcpy(&(inp->lento_permit.path[pathlen+1]), fsetname, fsetnamelen); |
| inp->lento_permit.path[fsetnamelen + 1 + pathlen] = '\0'; |
| |
| CDEBUG(D_UPCALL, "Permit minor %d path %s\n", minor, |
| inp->lento_permit.path); |
| |
| error = lento_upcall(minor, insize, &outsize, inp, |
| SYNCHRONOUS, NULL); |
| if (error) { |
| if( error == -EROFS ) { |
| int err; |
| printk("lento_permit: ERROR - requested permit for " |
| "read-only fileset.\n" |
| " Setting \"%s\" read-only!\n", |
| path); |
| err= presto_mark_cache(path, 0xFFFFFFFF, |
| CACHE_CLIENT_RO, NULL); |
| if( err ) { |
| printk("ERROR : mark_cache %d\n", err); |
| } |
| } |
| else { |
| printk("lento_permit: error %d\n", error); |
| } |
| } |
| |
| EXIT; |
| |
| return error; |
| } |
| |