blob: 37491a4c3dd003c035dfbb5613b5920ca973021b [file] [log] [blame]
/*
* 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;
}