upcall.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
- /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
- * vim:expandtab:shiftwidth=8:tabstop=8:
- *
- * Copyright (C) 2001, 2002 Cluster File Systems, Inc. <braam@clusterfs.com>
- * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
- *
- * This file is part of InterMezzo, http://www.inter-mezzo.org.
- *
- * InterMezzo is free software; you can redistribute it and/or
- * modify it under the terms of version 2 of the GNU General Public
- * License as published by the Free Software Foundation.
- *
- * InterMezzo is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with InterMezzo; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Mostly platform independent upcall operations to a cache manager:
- * -- upcalls
- * -- upcall routines
- *
- */
- #include <asm/system.h>
- #include <asm/segment.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/sched.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 <asm/segment.h>
- #include <linux/intermezzo_lib.h>
- #include <linux/intermezzo_fs.h>
- #include <linux/intermezzo_psdev.h>
- #include <linux/intermezzo_idl.h>
- /*
- At present:
- -- Asynchronous calls:
- - kml: give a "more" kml indication to userland
- - kml_truncate: initiate KML truncation
- - release_permit: kernel is done with permit
- -- Synchronous
- - open: fetch file
- - permit: get a permit
- Errors returned by user level code are positive
- */
- static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
- char *fsetname, int reclen, char *rec,
- int *size)
- {
- struct izo_upcall_hdr *hdr;
- char *ptr;
- ENTRY;
- *size = sizeof(struct izo_upcall_hdr);
- if ( fsetname ) {
- *size += round_strlen(fsetname);
- }
- if ( path ) {
- *size += round_strlen(path);
- }
- if ( rec ) {
- *size += size_round(reclen);
- }
- PRESTO_ALLOC(hdr, *size);
- if (!hdr) {
- CERROR("intermezzo upcall: out of memory (opc %d)n", opcode);
- EXIT;
- return NULL;
- }
- memset(hdr, 0, *size);
- ptr = (char *)hdr + sizeof(*hdr);
- /* XXX do we need fsuid ? */
- hdr->u_len = *size;
- hdr->u_version = IZO_UPC_VERSION;
- hdr->u_opc = opcode;
- hdr->u_pid = current->pid;
- hdr->u_uid = current->fsuid;
- if (path) {
- /*XXX Robert: please review what len to pass in for
- NUL terminated strings */
- hdr->u_pathlen = strlen(path);
- LOGL0(path, hdr->u_pathlen, ptr);
- }
- if (fsetname) {
- hdr->u_fsetlen = strlen(fsetname);
- LOGL0(fsetname, strlen(fsetname), ptr);
- }
- if (rec) {
- hdr->u_reclen = reclen;
- LOGL(rec, reclen, ptr);
- }
-
- EXIT;
- return hdr;
- }
- /* the upcalls */
- int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length, __u32 last_recno, char *fsetname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return 0;
- }
- hdr = upc_pack(IZO_UPC_KML, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- hdr->u_offset = offset;
- hdr->u_first_recno = first_recno;
- hdr->u_length = length;
- hdr->u_last_recno = last_recno;
- CDEBUG(D_UPCALL, "KML: fileset %s, offset %Lu, length %Lu, "
- "first %u, last %d; minor %dn",
- fsetname, hdr->u_offset, hdr->u_length, hdr->u_first_recno,
- hdr->u_last_recno, minor);
- error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
- EXIT;
- return -error;
- }
- int izo_upc_kml_truncate(int minor, __u64 length, __u32 last_recno, char *fsetname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return 0;
- }
- hdr = upc_pack(IZO_UPC_KML_TRUNC, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- hdr->u_length = length;
- hdr->u_last_recno = last_recno;
- CDEBUG(D_UPCALL, "KML TRUNCATE: fileset %s, length %Lu, "
- "last recno %d, minor %dn",
- fsetname, hdr->u_length, hdr->u_last_recno, minor);
- error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
- EXIT;
- return error;
- }
- int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname, struct lento_vfs_context *info)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_OPEN, pathlen, path, fsetname,
- sizeof(*info), (char*)info, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- CDEBUG(D_UPCALL, "path %sn", path);
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_get_fileid(int minor, __u32 reclen, char *rec,
- __u32 pathlen, char *path, char *fsetname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_GET_FILEID, pathlen, path, fsetname, reclen, rec, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- CDEBUG(D_UPCALL, "path %sn", path);
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_backfetch(int minor, char *path, char *fsetname, struct lento_vfs_context *info)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_BACKFETCH, strlen(path), path, fsetname,
- sizeof(*info), (char *)info, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- /* This is currently synchronous, kml_reint_record blocks */
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_permit(int minor, struct dentry *dentry, __u32 pathlen, char *path,
- char *fsetname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- hdr = upc_pack(IZO_UPC_PERMIT, pathlen, path, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- CDEBUG(D_UPCALL, "Permit minor %d path %sn", minor, path);
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error == -EROFS) {
- int err;
- CERROR("InterMezzo: ERROR - requested permit for read-only "
- "fileset.n Setting "%s" read-only!n", path);
- err = izo_mark_cache(dentry, 0xFFFFFFFF, CACHE_CLIENT_RO, NULL);
- if (err)
- CERROR("InterMezzo ERROR: mark_cache %dn", err);
- } else if (error) {
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- }
- EXIT;
- return error;
- }
- /* This is a ping-pong upcall handled on the server when a client (uuid)
- * requests the permit for itself. */
- int izo_upc_revoke_permit(int minor, char *fsetname, __u8 uuid[16])
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- hdr = upc_pack(IZO_UPC_REVOKE_PERMIT, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_go_fetch_kml(int minor, char *fsetname, __u8 uuid[16],
- __u64 kmlsize)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_GO_FETCH_KML, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- hdr->u_offset = kmlsize;
- memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
- error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
- if (error)
- CERROR("%s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
- int client_flag)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_CONNECT, 0, NULL, NULL, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- hdr->u_offset = ip_address;
- hdr->u_length = port;
- memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
- hdr->u_first_recno = client_flag;
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error) {
- CERROR("%s: error %dn", __FUNCTION__, error);
- }
- EXIT;
- return -error;
- }
- int izo_upc_set_kmlsize(int minor, char *fsetname, __u8 uuid[16], __u64 kmlsize)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_SET_KMLSIZE, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
- hdr->u_length = kmlsize;
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("%s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_repstatus(int minor, char * fsetname, struct izo_rcvd_rec *lr_server)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_REPSTATUS, 0, NULL, fsetname,
- sizeof(*lr_server), (char*)lr_server,
- &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("%s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- #if 0
- int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
- char *branchname)
- {
- int size, error;
- struct izo_upcall_hdr *hdr;
- int pathlen;
- char *path;
- ENTRY;
- hdr = upc_pack(IZO_UPC_CLIENT_MAKE_BRANCH, strlen(tagname), tagname,
- fsetname, strlen(branchname) + 1, branchname, &size);
- if (!hdr || IS_ERR(hdr)) {
- error = -PTR_ERR(hdr);
- goto error;
- }
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: error %dn", error);
- error:
- PRESTO_FREE(path, pathlen);
- EXIT;
- return error;
- }
- #endif
- int izo_upc_server_make_branch(int minor, char *fsetname)
- {
- int size, error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- hdr = upc_pack(IZO_UPC_SERVER_MAKE_BRANCH, 0, NULL, fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- error = -PTR_ERR(hdr);
- goto error;
- }
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: error %dn", error);
- error:
- EXIT;
- return -error;
- }
- int izo_upc_branch_undo(int minor, char *fsetname, char *branchname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_BRANCH_UNDO, strlen(branchname), branchname,
- fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }
- int izo_upc_branch_redo(int minor, char *fsetname, char *branchname)
- {
- int size;
- int error;
- struct izo_upcall_hdr *hdr;
- ENTRY;
- if (!presto_lento_up(minor)) {
- EXIT;
- return -EIO;
- }
- hdr = upc_pack(IZO_UPC_BRANCH_REDO, strlen(branchname) + 1, branchname,
- fsetname, 0, NULL, &size);
- if (!hdr || IS_ERR(hdr)) {
- EXIT;
- return -PTR_ERR(hdr);
- }
- error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
- if (error)
- CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
- EXIT;
- return -error;
- }