upcall.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:15k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
  2.  * vim:expandtab:shiftwidth=8:tabstop=8:
  3.  *
  4.  * Copyright (C) 2001, 2002 Cluster File Systems, Inc. <braam@clusterfs.com>
  5.  * Copyright (C) 2001 Tacit Networks, Inc. <phil@off.net>
  6.  *
  7.  *   This file is part of InterMezzo, http://www.inter-mezzo.org.
  8.  *
  9.  *   InterMezzo is free software; you can redistribute it and/or
  10.  *   modify it under the terms of version 2 of the GNU General Public
  11.  *   License as published by the Free Software Foundation.
  12.  *
  13.  *   InterMezzo is distributed in the hope that it will be useful,
  14.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *   GNU General Public License for more details.
  17.  *
  18.  *   You should have received a copy of the GNU General Public License
  19.  *   along with InterMezzo; if not, write to the Free Software
  20.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  *
  22.  * Mostly platform independent upcall operations to a cache manager:
  23.  *  -- upcalls
  24.  *  -- upcall routines
  25.  *
  26.  */
  27. #include <asm/system.h>
  28. #include <asm/segment.h>
  29. #include <asm/signal.h>
  30. #include <linux/signal.h>
  31. #include <linux/types.h>
  32. #include <linux/kernel.h>
  33. #include <linux/mm.h>
  34. #include <linux/vmalloc.h>
  35. #include <linux/slab.h>
  36. #include <linux/sched.h>
  37. #include <linux/fs.h>
  38. #include <linux/stat.h>
  39. #include <linux/errno.h>
  40. #include <linux/locks.h>
  41. #include <linux/string.h>
  42. #include <asm/uaccess.h>
  43. #include <linux/vmalloc.h>
  44. #include <asm/segment.h>
  45. #include <linux/intermezzo_lib.h>
  46. #include <linux/intermezzo_fs.h>
  47. #include <linux/intermezzo_psdev.h>
  48. #include <linux/intermezzo_idl.h>
  49. /*
  50.   At present:
  51.   -- Asynchronous calls:
  52.    - kml:            give a "more" kml indication to userland
  53.    - kml_truncate:   initiate KML truncation
  54.    - release_permit: kernel is done with permit
  55.   -- Synchronous
  56.    - open:           fetch file
  57.    - permit:         get a permit
  58.   Errors returned by user level code are positive
  59.  */
  60. static struct izo_upcall_hdr *upc_pack(__u32 opcode, int pathlen, char *path,
  61.                                        char *fsetname, int reclen, char *rec,
  62.                                        int *size)
  63. {
  64.         struct izo_upcall_hdr *hdr;
  65.         char *ptr;
  66.         ENTRY;
  67.         *size = sizeof(struct izo_upcall_hdr);
  68.         if ( fsetname ) {
  69.                 *size += round_strlen(fsetname);
  70.         }
  71.         if ( path ) { 
  72.                 *size += round_strlen(path);
  73.         }
  74.         if ( rec ) { 
  75.                 *size += size_round(reclen);
  76.         }
  77.         PRESTO_ALLOC(hdr, *size);
  78.         if (!hdr) { 
  79.                 CERROR("intermezzo upcall: out of memory (opc %d)n", opcode);
  80.                 EXIT;
  81.                 return NULL;
  82.         }
  83.         memset(hdr, 0, *size);
  84.         ptr = (char *)hdr + sizeof(*hdr);
  85.         /* XXX do we need fsuid ? */
  86.         hdr->u_len = *size;
  87.         hdr->u_version = IZO_UPC_VERSION;
  88.         hdr->u_opc = opcode;
  89.         hdr->u_pid = current->pid;
  90.         hdr->u_uid = current->fsuid;
  91.         if (path) { 
  92.                 /*XXX Robert: please review what len to pass in for 
  93.                   NUL terminated strings */
  94.                 hdr->u_pathlen = strlen(path);
  95.                 LOGL0(path, hdr->u_pathlen, ptr);
  96.         }
  97.         if (fsetname) { 
  98.                 hdr->u_fsetlen = strlen(fsetname);
  99.                 LOGL0(fsetname, strlen(fsetname), ptr);
  100.         }
  101.         if (rec) { 
  102.                 hdr->u_reclen = reclen;
  103.                 LOGL(rec, reclen, ptr);
  104.         }
  105.         
  106.         EXIT;
  107.         return hdr;
  108. }
  109. /* the upcalls */
  110. int izo_upc_kml(int minor, __u64 offset, __u32 first_recno, __u64 length, __u32 last_recno, char *fsetname)
  111. {
  112.         int size;
  113.         int error;
  114.         struct izo_upcall_hdr *hdr;
  115.         ENTRY;
  116.         if (!presto_lento_up(minor)) {
  117.                 EXIT;
  118.                 return 0;
  119.         }
  120.         hdr = upc_pack(IZO_UPC_KML, 0, NULL, fsetname, 0, NULL, &size);
  121.         if (!hdr || IS_ERR(hdr)) {
  122.                 EXIT;
  123.                 return -PTR_ERR(hdr);
  124.         }
  125.         hdr->u_offset = offset;
  126.         hdr->u_first_recno = first_recno;
  127.         hdr->u_length = length;
  128.         hdr->u_last_recno = last_recno;
  129.         CDEBUG(D_UPCALL, "KML: fileset %s, offset %Lu, length %Lu, "
  130.                "first %u, last %d; minor %dn",
  131.                fsetname, hdr->u_offset, hdr->u_length, hdr->u_first_recno,
  132.                hdr->u_last_recno, minor);
  133.         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
  134.         EXIT;
  135.         return -error;
  136. }
  137. int izo_upc_kml_truncate(int minor, __u64 length, __u32 last_recno, char *fsetname)
  138. {
  139.         int size;
  140.         int error;
  141.         struct izo_upcall_hdr *hdr;
  142.         ENTRY;
  143.         if (!presto_lento_up(minor)) {
  144.                 EXIT;
  145.                 return 0;
  146.         }
  147.         hdr = upc_pack(IZO_UPC_KML_TRUNC, 0, NULL, fsetname, 0, NULL, &size);
  148.         if (!hdr || IS_ERR(hdr)) {
  149.                 EXIT;
  150.                 return -PTR_ERR(hdr);
  151.         }
  152.         hdr->u_length = length;
  153.         hdr->u_last_recno = last_recno;
  154.         CDEBUG(D_UPCALL, "KML TRUNCATE: fileset %s, length %Lu, "
  155.                "last recno %d, minor %dn",
  156.                fsetname, hdr->u_length, hdr->u_last_recno, minor);
  157.         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
  158.         EXIT;
  159.         return error;
  160. }
  161. int izo_upc_open(int minor, __u32 pathlen, char *path, char *fsetname, struct lento_vfs_context *info)
  162. {
  163.         int size;
  164.         int error;
  165.         struct izo_upcall_hdr *hdr;
  166.         ENTRY;
  167.         if (!presto_lento_up(minor)) {
  168.                 EXIT;
  169.                 return -EIO;
  170.         }
  171.         hdr = upc_pack(IZO_UPC_OPEN, pathlen, path, fsetname, 
  172.                        sizeof(*info), (char*)info, &size);
  173.         if (!hdr || IS_ERR(hdr)) {
  174.                 EXIT;
  175.                 return -PTR_ERR(hdr);
  176.         }
  177.         CDEBUG(D_UPCALL, "path %sn", path);
  178.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  179.         if (error)
  180.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  181.         EXIT;
  182.         return -error;
  183. }
  184. int izo_upc_get_fileid(int minor, __u32 reclen, char *rec, 
  185.                        __u32 pathlen, char *path, char *fsetname)
  186. {
  187.         int size;
  188.         int error;
  189.         struct izo_upcall_hdr *hdr;
  190.         ENTRY;
  191.         if (!presto_lento_up(minor)) {
  192.                 EXIT;
  193.                 return -EIO;
  194.         }
  195.         hdr = upc_pack(IZO_UPC_GET_FILEID, pathlen, path, fsetname, reclen, rec, &size);
  196.         if (!hdr || IS_ERR(hdr)) {
  197.                 EXIT;
  198.                 return -PTR_ERR(hdr);
  199.         }
  200.         CDEBUG(D_UPCALL, "path %sn", path);
  201.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  202.         if (error)
  203.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  204.         EXIT;
  205.         return -error;
  206. }
  207. int izo_upc_backfetch(int minor, char *path, char *fsetname, struct lento_vfs_context *info)
  208. {
  209.         int size;
  210.         int error;
  211.         struct izo_upcall_hdr *hdr;
  212.         ENTRY;
  213.         if (!presto_lento_up(minor)) {
  214.                 EXIT;
  215.                 return -EIO;
  216.         }
  217.         hdr = upc_pack(IZO_UPC_BACKFETCH, strlen(path), path, fsetname, 
  218.                        sizeof(*info), (char *)info, &size);
  219.         if (!hdr || IS_ERR(hdr)) {
  220.                 EXIT;
  221.                 return -PTR_ERR(hdr);
  222.         }
  223.         /* This is currently synchronous, kml_reint_record blocks */
  224.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  225.         if (error)
  226.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  227.         EXIT;
  228.         return -error;
  229. }
  230. int izo_upc_permit(int minor, struct dentry *dentry, __u32 pathlen, char *path,
  231.                    char *fsetname)
  232. {
  233.         int size;
  234.         int error;
  235.         struct izo_upcall_hdr *hdr;
  236.         ENTRY;
  237.         hdr = upc_pack(IZO_UPC_PERMIT, pathlen, path, fsetname, 0, NULL, &size);
  238.         if (!hdr || IS_ERR(hdr)) {
  239.                 EXIT;
  240.                 return -PTR_ERR(hdr);
  241.         }
  242.         CDEBUG(D_UPCALL, "Permit minor %d path %sn", minor, path);
  243.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  244.         if (error == -EROFS) {
  245.                 int err;
  246.                 CERROR("InterMezzo: ERROR - requested permit for read-only "
  247.                        "fileset.n   Setting "%s" read-only!n", path);
  248.                 err = izo_mark_cache(dentry, 0xFFFFFFFF, CACHE_CLIENT_RO, NULL);
  249.                 if (err)
  250.                         CERROR("InterMezzo ERROR: mark_cache %dn", err);
  251.         } else if (error) {
  252.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  253.         }
  254.         EXIT;
  255.         return error;
  256. }
  257. /* This is a ping-pong upcall handled on the server when a client (uuid)
  258.  * requests the permit for itself. */
  259. int izo_upc_revoke_permit(int minor, char *fsetname, __u8 uuid[16])
  260. {
  261.         int size;
  262.         int error;
  263.         struct izo_upcall_hdr *hdr;
  264.         ENTRY;
  265.         hdr = upc_pack(IZO_UPC_REVOKE_PERMIT, 0, NULL, fsetname, 0, NULL, &size);
  266.         if (!hdr || IS_ERR(hdr)) {
  267.                 EXIT;
  268.                 return -PTR_ERR(hdr);
  269.         }
  270.         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
  271.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  272.         if (error)
  273.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  274.         EXIT;
  275.         return -error;
  276. }
  277. int izo_upc_go_fetch_kml(int minor, char *fsetname, __u8 uuid[16],
  278.                          __u64 kmlsize)
  279. {
  280.         int size;
  281.         int error;
  282.         struct izo_upcall_hdr *hdr;
  283.         ENTRY;
  284.         if (!presto_lento_up(minor)) {
  285.                 EXIT;
  286.                 return -EIO;
  287.         }
  288.         hdr = upc_pack(IZO_UPC_GO_FETCH_KML, 0, NULL, fsetname, 0, NULL, &size);
  289.         if (!hdr || IS_ERR(hdr)) {
  290.                 EXIT;
  291.                 return -PTR_ERR(hdr);
  292.         }
  293.         hdr->u_offset = kmlsize;
  294.         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
  295.         error = izo_upc_upcall(minor, &size, hdr, ASYNCHRONOUS);
  296.         if (error)
  297.                 CERROR("%s: error %dn", __FUNCTION__, error);
  298.         EXIT;
  299.         return -error;
  300. }
  301. int izo_upc_connect(int minor, __u64 ip_address, __u64 port, __u8 uuid[16],
  302.                     int client_flag)
  303. {
  304.         int size;
  305.         int error;
  306.         struct izo_upcall_hdr *hdr;
  307.         ENTRY;
  308.         if (!presto_lento_up(minor)) {
  309.                 EXIT;
  310.                 return -EIO;
  311.         }
  312.         hdr = upc_pack(IZO_UPC_CONNECT, 0, NULL, NULL, 0, NULL, &size);
  313.         if (!hdr || IS_ERR(hdr)) {
  314.                 EXIT;
  315.                 return -PTR_ERR(hdr);
  316.         }
  317.         hdr->u_offset = ip_address;
  318.         hdr->u_length = port;
  319.         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
  320.         hdr->u_first_recno = client_flag;
  321.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  322.         if (error) {
  323.                 CERROR("%s: error %dn", __FUNCTION__, error);
  324.         }
  325.         EXIT;
  326.         return -error;
  327. }
  328. int izo_upc_set_kmlsize(int minor, char *fsetname, __u8 uuid[16], __u64 kmlsize)
  329. {
  330.         int size;
  331.         int error;
  332.         struct izo_upcall_hdr *hdr;
  333.         ENTRY;
  334.         if (!presto_lento_up(minor)) {
  335.                 EXIT;
  336.                 return -EIO;
  337.         }
  338.         hdr = upc_pack(IZO_UPC_SET_KMLSIZE, 0, NULL, fsetname, 0, NULL, &size);
  339.         if (!hdr || IS_ERR(hdr)) {
  340.                 EXIT;
  341.                 return -PTR_ERR(hdr);
  342.         }
  343.         memcpy(hdr->u_uuid, uuid, sizeof(hdr->u_uuid));
  344.         hdr->u_length = kmlsize;
  345.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  346.         if (error)
  347.                 CERROR("%s: error %dn", __FUNCTION__, error);
  348.         EXIT;
  349.         return -error;
  350. }
  351. int izo_upc_repstatus(int minor,  char * fsetname, struct izo_rcvd_rec *lr_server)
  352. {
  353.         int size;
  354.         int error;
  355.         struct izo_upcall_hdr *hdr;
  356.         ENTRY;
  357.         if (!presto_lento_up(minor)) {
  358.                 EXIT;
  359.                 return -EIO;
  360.         }
  361.         hdr = upc_pack(IZO_UPC_REPSTATUS, 0, NULL, fsetname, 
  362.                        sizeof(*lr_server), (char*)lr_server, 
  363.                        &size);
  364.         if (!hdr || IS_ERR(hdr)) {
  365.                 EXIT;
  366.                 return -PTR_ERR(hdr);
  367.         }
  368.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  369.         if (error)
  370.                 CERROR("%s: error %dn", __FUNCTION__, error);
  371.         EXIT;
  372.         return -error;
  373. }
  374. #if 0
  375. int izo_upc_client_make_branch(int minor, char *fsetname, char *tagname,
  376.                                char *branchname)
  377. {
  378.         int size, error;
  379.         struct izo_upcall_hdr *hdr;
  380.         int pathlen;
  381.         char *path;
  382.         ENTRY;
  383.         hdr = upc_pack(IZO_UPC_CLIENT_MAKE_BRANCH, strlen(tagname), tagname,
  384.                        fsetname, strlen(branchname) + 1, branchname, &size);
  385.         if (!hdr || IS_ERR(hdr)) {
  386.                 error = -PTR_ERR(hdr);
  387.                 goto error;
  388.         }
  389.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  390.         if (error)
  391.                 CERROR("InterMezzo: error %dn", error);
  392.  error:
  393.         PRESTO_FREE(path, pathlen);
  394.         EXIT;
  395.         return error;
  396. }
  397. #endif
  398. int izo_upc_server_make_branch(int minor, char *fsetname)
  399. {
  400.         int size, error;
  401.         struct izo_upcall_hdr *hdr;
  402.         ENTRY;
  403.         hdr = upc_pack(IZO_UPC_SERVER_MAKE_BRANCH, 0, NULL, fsetname, 0, NULL, &size);
  404.         if (!hdr || IS_ERR(hdr)) {
  405.                 error = -PTR_ERR(hdr);
  406.                 goto error;
  407.         }
  408.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  409.         if (error)
  410.                 CERROR("InterMezzo: error %dn", error);
  411.  error:
  412.         EXIT;
  413.         return -error;
  414. }
  415. int izo_upc_branch_undo(int minor, char *fsetname, char *branchname)
  416. {
  417.         int size;
  418.         int error;
  419.         struct izo_upcall_hdr *hdr;
  420.         ENTRY;
  421.         if (!presto_lento_up(minor)) {
  422.                 EXIT;
  423.                 return -EIO;
  424.         }
  425.         hdr = upc_pack(IZO_UPC_BRANCH_UNDO, strlen(branchname), branchname,
  426.                        fsetname, 0, NULL, &size);
  427.         if (!hdr || IS_ERR(hdr)) {
  428.                 EXIT;
  429.                 return -PTR_ERR(hdr);
  430.         }
  431.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  432.         if (error)
  433.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  434.         EXIT;
  435.         return -error;
  436. }
  437. int izo_upc_branch_redo(int minor, char *fsetname, char *branchname)
  438. {
  439.         int size;
  440.         int error;
  441.         struct izo_upcall_hdr *hdr;
  442.         ENTRY;
  443.         if (!presto_lento_up(minor)) {
  444.                 EXIT;
  445.                 return -EIO;
  446.         }
  447.         hdr = upc_pack(IZO_UPC_BRANCH_REDO, strlen(branchname) + 1, branchname,
  448.                        fsetname, 0, NULL, &size);
  449.         if (!hdr || IS_ERR(hdr)) {
  450.                 EXIT;
  451.                 return -PTR_ERR(hdr);
  452.         }
  453.         error = izo_upc_upcall(minor, &size, hdr, SYNCHRONOUS);
  454.         if (error)
  455.                 CERROR("InterMezzo: %s: error %dn", __FUNCTION__, error);
  456.         EXIT;
  457.         return -error;
  458. }