📄 upcall.c
字号:
/* * Mostly platform independent upcall operations to Venus: * -- upcalls * -- upcall routines * * Linux 2.0 version * Copyright (C) 1996 Peter J. Braam <braam@maths.ox.ac.uk>, * 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>. */#include <asm/system.h>#include <linux/signal.h>#include <linux/sched.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/time.h>#include <linux/fs.h>#include <linux/file.h>#include <linux/stat.h>#include <linux/errno.h>#include <linux/string.h>#include <asm/uaccess.h>#include <linux/vmalloc.h>#include <linux/vfs.h>#include <linux/coda.h>#include <linux/coda_linux.h>#include <linux/coda_psdev.h>#include <linux/coda_fs_i.h>#include <linux/coda_cache.h>#include "coda_int.h"static int coda_upcall(struct venus_comm *vc, int inSize, int *outSize, union inputArgs *buffer);static void *alloc_upcall(int opcode, int size){ union inputArgs *inp; CODA_ALLOC(inp, union inputArgs *, size); if (!inp) return ERR_PTR(-ENOMEM); inp->ih.opcode = opcode; inp->ih.pid = current->pid; inp->ih.pgid = task_pgrp_nr(current);#ifdef CONFIG_CODA_FS_OLD_API memset(&inp->ih.cred, 0, sizeof(struct coda_cred)); inp->ih.cred.cr_fsuid = current->fsuid;#else inp->ih.uid = current->fsuid;#endif return (void*)inp;}#define UPARG(op)\do {\ inp = (union inputArgs *)alloc_upcall(op, insize); \ if (IS_ERR(inp)) { return PTR_ERR(inp); }\ outp = (union outputArgs *)(inp); \ outsize = insize; \} while (0)#define INSIZE(tag) sizeof(struct coda_ ## tag ## _in)#define OUTSIZE(tag) sizeof(struct coda_ ## tag ## _out)#define SIZE(tag) max_t(unsigned int, INSIZE(tag), OUTSIZE(tag))/* the upcalls */int venus_rootfid(struct super_block *sb, struct CodaFid *fidp){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; insize = SIZE(root); UPARG(CODA_ROOT); error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) *fidp = outp->coda_root.VFid; CODA_FREE(inp, insize); return error;}int venus_getattr(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *attr) { union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; insize = SIZE(getattr); UPARG(CODA_GETATTR); inp->coda_getattr.VFid = *fid; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) *attr = outp->coda_getattr.attr; CODA_FREE(inp, insize); return error;}int venus_setattr(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *vattr){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; insize = SIZE(setattr); UPARG(CODA_SETATTR); inp->coda_setattr.VFid = *fid; inp->coda_setattr.attr = *vattr; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_lookup(struct super_block *sb, struct CodaFid *fid, const char *name, int length, int * type, struct CodaFid *resfid){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset; offset = INSIZE(lookup); insize = max_t(unsigned int, offset + length +1, OUTSIZE(lookup)); UPARG(CODA_LOOKUP); inp->coda_lookup.VFid = *fid; inp->coda_lookup.name = offset; inp->coda_lookup.flags = CLU_CASE_SENSITIVE; /* send Venus a null terminated string */ memcpy((char *)(inp) + offset, name, length); *((char *)inp + offset + length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) { *resfid = outp->coda_lookup.VFid; *type = outp->coda_lookup.vtype; } CODA_FREE(inp, insize); return error;}int venus_close(struct super_block *sb, struct CodaFid *fid, int flags, vuid_t uid){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error;#ifdef CONFIG_CODA_FS_OLD_API struct coda_cred cred = { 0, }; cred.cr_fsuid = uid;#endif insize = SIZE(release); UPARG(CODA_CLOSE); #ifdef CONFIG_CODA_FS_OLD_API memcpy(&(inp->ih.cred), &cred, sizeof(cred));#else inp->ih.uid = uid;#endif inp->coda_close.VFid = *fid; inp->coda_close.flags = flags; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_open(struct super_block *sb, struct CodaFid *fid, int flags, struct file **fh){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; insize = SIZE(open_by_fd); UPARG(CODA_OPEN_BY_FD); inp->coda_open_by_fd.VFid = *fid; inp->coda_open_by_fd.flags = flags; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) *fh = outp->coda_open_by_fd.fh; CODA_FREE(inp, insize); return error;} int venus_mkdir(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length, struct CodaFid *newfid, struct coda_vattr *attrs){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset; offset = INSIZE(mkdir); insize = max_t(unsigned int, offset + length + 1, OUTSIZE(mkdir)); UPARG(CODA_MKDIR); inp->coda_mkdir.VFid = *dirfid; inp->coda_mkdir.attr = *attrs; inp->coda_mkdir.name = offset; /* Venus must get null terminated string */ memcpy((char *)(inp) + offset, name, length); *((char *)inp + offset + length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) { *attrs = outp->coda_mkdir.attr; *newfid = outp->coda_mkdir.VFid; } CODA_FREE(inp, insize); return error; }int venus_rename(struct super_block *sb, struct CodaFid *old_fid, struct CodaFid *new_fid, size_t old_length, size_t new_length, const char *old_name, const char *new_name){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset, s; offset = INSIZE(rename); insize = max_t(unsigned int, offset + new_length + old_length + 8, OUTSIZE(rename)); UPARG(CODA_RENAME); inp->coda_rename.sourceFid = *old_fid; inp->coda_rename.destFid = *new_fid; inp->coda_rename.srcname = offset; /* Venus must receive an null terminated string */ s = ( old_length & ~0x3) +4; /* round up to word boundary */ memcpy((char *)(inp) + offset, old_name, old_length); *((char *)inp + offset + old_length) = '\0'; /* another null terminated string for Venus */ offset += s; inp->coda_rename.destname = offset; s = ( new_length & ~0x3) +4; /* round up to word boundary */ memcpy((char *)(inp) + offset, new_name, new_length); *((char *)inp + offset + new_length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_create(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length, int excl, int mode, struct CodaFid *newfid, struct coda_vattr *attrs) { union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset; offset = INSIZE(create); insize = max_t(unsigned int, offset + length + 1, OUTSIZE(create)); UPARG(CODA_CREATE); inp->coda_create.VFid = *dirfid; inp->coda_create.attr.va_mode = mode; inp->coda_create.excl = excl; inp->coda_create.mode = mode; inp->coda_create.name = offset; /* Venus must get null terminated string */ memcpy((char *)(inp) + offset, name, length); *((char *)inp + offset + length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) { *attrs = outp->coda_create.attr; *newfid = outp->coda_create.VFid; } CODA_FREE(inp, insize); return error; }int venus_rmdir(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset; offset = INSIZE(rmdir); insize = max_t(unsigned int, offset + length + 1, OUTSIZE(rmdir)); UPARG(CODA_RMDIR); inp->coda_rmdir.VFid = *dirfid; inp->coda_rmdir.name = offset; memcpy((char *)(inp) + offset, name, length); *((char *)inp + offset + length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_remove(struct super_block *sb, struct CodaFid *dirfid, const char *name, int length){ union inputArgs *inp; union outputArgs *outp; int error=0, insize, outsize, offset; offset = INSIZE(remove); insize = max_t(unsigned int, offset + length + 1, OUTSIZE(remove)); UPARG(CODA_REMOVE); inp->coda_remove.VFid = *dirfid; inp->coda_remove.name = offset; memcpy((char *)(inp) + offset, name, length); *((char *)inp + offset + length) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_readlink(struct super_block *sb, struct CodaFid *fid, char *buffer, int *length){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int retlen; char *result; insize = max_t(unsigned int, INSIZE(readlink), OUTSIZE(readlink)+ *length + 1); UPARG(CODA_READLINK); inp->coda_readlink.VFid = *fid; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); if (!error) { retlen = outp->coda_readlink.count; if ( retlen > *length ) retlen = *length; *length = retlen; result = (char *)outp + (long)outp->coda_readlink.data; memcpy(buffer, result, retlen); *(buffer + retlen) = '\0'; } CODA_FREE(inp, insize); return error;}int venus_link(struct super_block *sb, struct CodaFid *fid, struct CodaFid *dirfid, const char *name, int len ){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset; offset = INSIZE(link); insize = max_t(unsigned int, offset + len + 1, OUTSIZE(link)); UPARG(CODA_LINK); inp->coda_link.sourceFid = *fid; inp->coda_link.destFid = *dirfid; inp->coda_link.tname = offset; /* make sure strings are null terminated */ memcpy((char *)(inp) + offset, name, len); *((char *)inp + offset + len) = '\0'; error = coda_upcall(coda_vcp(sb), insize, &outsize, inp); CODA_FREE(inp, insize); return error;}int venus_symlink(struct super_block *sb, struct CodaFid *fid, const char *name, int len, const char *symname, int symlen){ union inputArgs *inp; union outputArgs *outp; int insize, outsize, error; int offset, s; offset = INSIZE(symlink); insize = max_t(unsigned int, offset + len + symlen + 8, OUTSIZE(symlink)); UPARG(CODA_SYMLINK); /* inp->coda_symlink.attr = *tva; XXXXXX */ inp->coda_symlink.VFid = *fid; /* Round up to word boundary and null terminate */ inp->coda_symlink.srcname = offset; s = ( symlen & ~0x3 ) + 4; memcpy((char *)(inp) + offset, symname, symlen); *((char *)inp + offset + symlen) = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -