/* * Mostly platform independent upcall operations to Venus: * -- upcalls * -- upcall routines * * Linux 2.0 version * Copyright (C) 1996 Peter J. Braam , * Michael Callahan * * 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 . * * Much cleaned up for InterMezzo * Copyright (C) 1998 Peter J. Braam , * Copyright (C) 1999 Carnegie Mellon University * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* 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; }