Subversion Repositories HelenOS

Rev

Rev 2248 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  * Copyright (c) 2006 Martin Decky
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * - Redistributions of source code must retain the above copyright
  10.  *   notice, this list of conditions and the following disclaimer.
  11.  * - Redistributions in binary form must reproduce the above copyright
  12.  *   notice, this list of conditions and the following disclaimer in the
  13.  *   documentation and/or other materials provided with the distribution.
  14.  * - The name of the author may not be used to endorse or promote products
  15.  *   derived from this software without specific prior written permission.
  16.  *
  17.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
  18.  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  19.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  20.  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
  21.  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  22.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23.  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24.  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25.  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26.  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27.  */
  28.  
  29. /** @addtogroup fs
  30.  * @{
  31.  */
  32.  
  33. /**
  34.  * @file    fs.c
  35.  * @brief   File system driver for HelenOS.
  36.  */
  37.  
  38. #include <ipc/ipc.h>
  39. #include <ipc/services.h>
  40. #include <ipc/ns.h>
  41. #include <sysinfo.h>
  42. #include <io/io.h>
  43. #include <as.h>
  44. #include <ddi.h>
  45. #include <align.h>
  46. #include <bool.h>
  47. #include <errno.h>
  48. #include <async.h>
  49. #include <cap.h>
  50. #include <sys/mman.h>
  51. #include "fs.h"
  52. #include "dir.h"
  53. #include "../console/console.h"
  54.  
  55.  
  56. static int fs_call;
  57. static ipc_call_t m_input;          /* the input message used for request */
  58. static ipc_callid_t callid;         /* caller's number */
  59. static int new_consument;       /* if new consumer wants to connect to FS */
  60. static int check_con;           /* check of connection of consument */
  61.            
  62. static void prepare_message(void);
  63. static int load_super(void);
  64. static int new_consument_map(void);
  65.  
  66. static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
  67. {
  68.  
  69.     int result;
  70.  
  71.     ipc_answer_fast(iid, 0, 0, 0);
  72.  
  73.     while (1)
  74.     {
  75.         prepare_message();
  76.        
  77.         if (fs_call == IPC_M_PHONE_HUNGUP) {
  78.             ipc_answer_fast(callid, 0,0,0);
  79.             return;
  80.         }
  81.  
  82.         if (fs_call == FS_NEW_CONSUMER) {
  83.             if (!new_consument) {
  84.                 ipc_answer_fast(callid, FS_ECONNECT, 0, 0);
  85.             }
  86.             else {
  87.                 result = new_consument_map();  
  88.                 ipc_answer_fast(callid, result, 0, 0);
  89.  
  90.                 if (!result) {
  91.                     new_consument = FALSE;     
  92.                 }
  93.             }
  94.             continue;  
  95.         }
  96.  
  97.         if (fs_call == IPC_M_AS_AREA_SEND) {
  98.             if (!new_consument)
  99.                 ipc_answer_fast(callid, FS_ECONNECT, 0, 0);    
  100.             else {
  101.                 ipc_answer_fast(callid, 0, (uintptr_t)fp->buffer, 0);
  102.                 fp =  &fproc[new_consument];
  103.                 fp->connected = TRUE;
  104.                 new_consument = FALSE;
  105.             }
  106.             continue;
  107.         }
  108.    
  109.         if (check_con < 0) {
  110.             ipc_answer_fast(callid, err_code, 0, 0);
  111.             check_con = TRUE;
  112.             continue;  
  113.         }
  114.  
  115.         if (FS_IN_RANGE(fs_call)) {  
  116.            result = call_vector[fs_call-FS_BASE]();
  117.         }
  118.         else {
  119.            result = FS_EBADCALL;
  120.         }
  121.  
  122.         ipc_answer_fast(callid, result, 0, 0);             
  123.     }  
  124. }
  125.  
  126. /* Extracts parameters from message and prepare them for later usage. */
  127. void prepare_message(void)
  128. {
  129.    
  130.     int shift, id_task;
  131.    
  132.     callid = async_get_call(&m_input);
  133.     fs_call = IPC_GET_METHOD(m_input);
  134.    
  135.     if (fs_call == IPC_M_AS_AREA_SEND) {   
  136.         if (!new_consument) {
  137.             new_consument = FALSE;
  138.         }
  139.  
  140.         return;
  141.     }
  142.    
  143.     id_task = IPC_GET_ARG1(m_input);    
  144.    
  145.     /* Setup new consument. */
  146.     if (fs_call == FS_NEW_CONSUMER) {
  147.         if (!new_consument) {
  148.             new_consument = id_task;
  149.         }
  150.         else {
  151.             new_consument = FALSE;
  152.         }
  153.  
  154.         return;
  155.     }
  156.    
  157.     /* Other messages discard process of new consument connecting. */
  158.     if (new_consument) {
  159.         new_consument = FALSE;
  160.     }
  161.    
  162.     if (id_task < 0 || id_task >= NR_PROCS) {
  163.         check_con = FS_EINVAL;
  164.         return;    
  165.     }
  166.    
  167.     /* Switch to active consument. */
  168.     fp = &fproc[id_task];
  169.    
  170.     /* Check if consument was connected. */
  171.     if (!(fp->connected)) {
  172.         check_con = FS_ENOTCONNECT;
  173.         return;
  174.     }
  175.  
  176.    
  177.     /* Unpacking extended input message into message_params structure. */
  178.     unpack_message(&message_params, m_input, fp->buffer);
  179. }
  180.  
  181. /* Map some memory to the task */
  182. int new_consument_map()
  183. {
  184.    
  185.     size_t size;
  186.     task_id_t task_id;
  187.  
  188.     task_id = new_consument;   
  189.     if (task_id < 0 || task_id >= NR_PROCS) {
  190.         return FS_EINVAL;
  191.     }
  192.  
  193.     fp = &fproc[task_id];
  194.     size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
  195.     fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
  196.  
  197.     return TRUE;
  198. }
  199. /* Reads in the superblock from image. */
  200. int load_super(void)
  201. {
  202.    
  203.     super_block_t *sp;
  204.    
  205.     if (!init_super_block())
  206.         return FALSE;
  207.  
  208.         sp = get_super();
  209.     if (read_super(sp) != OK)
  210.     {
  211.         print_console("Super block read error\n");
  212.         return FALSE;
  213.     }
  214.  
  215.     return TRUE;
  216. }
  217.  
  218. /* Basic initialization. */
  219. static bool fs_init(void)
  220. {
  221.    
  222.     register inode_t *rip;
  223.     int bad, i;
  224.    
  225.  
  226.     bad = 0;
  227.     callid = SERVICE_FS;
  228.     fp = (fproc_t *)NULL;
  229.    
  230.     print_console("FS initialization...");
  231.  
  232.     /* Block cache initialization. */
  233.     if (!init_block())
  234.         return FALSE;
  235.    
  236.     /* Loading superblock. */
  237.     if (!load_super())
  238.         return FALSE;
  239.        
  240.     for (i = 0; i < NR_PROCS; i++) {
  241.         if (i == SERVICE_FS)
  242.             continue;
  243.  
  244.         fp = &fproc[i];
  245.         rip = get_inode(ROOT_INODE);
  246.         fp->fp_rootdir = rip;
  247.         dup_inode(rip);
  248.         fp->fp_workdir = rip;
  249.     }
  250.    
  251.     fp = &fproc[SERVICE_FS];
  252.  
  253.     /* Certain relations must hold for the file system to work at all. */
  254.     if (SUPER_SIZE > BLOCK_SIZE) {
  255.         print_console("SUPER_SIZE > BLOCK_SIZE\n");
  256.         bad++;
  257.     }
  258.     if (BLOCK_SIZE % V1_INODE_SIZE != 0) { 
  259.         print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
  260.         bad++;
  261.     }
  262.     if (OPEN_MAX > 127) {  
  263.         print_console("OPEN_MAX > 127\n");
  264.         bad++;
  265.     }
  266.     if (V1_INODE_SIZE != 32) { 
  267.         print_console("V1 inode size != 32\n");
  268.         bad++;
  269.     }
  270.    
  271.     if (V2_INODE_SIZE != 64) { 
  272.         print_console("V2 inode size != 64\n");
  273.         bad++;
  274.     }
  275.    
  276.     if (bad)
  277.         return FALSE;
  278.  
  279.     /* New consument flag settings. */
  280.     new_consument = FALSE;
  281.     check_con = FALSE;
  282.  
  283.     print_console("OK\n");
  284.    
  285.     return TRUE;
  286. }
  287.  
  288. int main(int argc, char **argv)
  289. {
  290.    
  291.     int retval, flags;
  292.     unsigned int size;
  293.  
  294.  
  295.     /* Initializing printing functions. */
  296.     if (!init_printing())
  297.         return -1;
  298.  
  299.     print_console("FS task\n");
  300.  
  301.     /* Connection to SERVICE_RD service. */
  302.     print_console("Connnection to SERVICE_RD...");
  303.     if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
  304.         print_console("OK\n");
  305.     else {
  306.         print_console("FALSE\n");
  307.         return -1;
  308.     }
  309.    
  310.     /* Creating shared memory for usage with SERVICE_RD.  */
  311.     print_console("Creating address space area for share with SERVICE_RD task...");
  312.     size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
  313.     buffer = mmap(buffer, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  314.     if ((int)buffer < 0) {
  315.         print_console_int("As_area_create error %d", (int)buffer);
  316.         return -1;
  317.     }
  318.     print_console("OK\n");
  319.  
  320.  
  321.     /* Mapping memory to SERVICE_RD. */
  322.     print_console("Sending memory to RD_SERVICE...");
  323.     flags = 0;
  324.     flags = AS_AREA_READ | AS_AREA_WRITE;
  325.     retval = async_req_3(rd_phone, IPC_M_AS_AREA_SEND, (uintptr_t)buffer, size, flags, NULL, NULL, NULL);
  326.     if (retval < 0) {
  327.         print_console_int("%d\n", retval);
  328.         return -1;
  329.     }
  330.     print_console("OK\n");
  331.  
  332.     if (fs_init()) {
  333.         ipcarg_t phonead;
  334.    
  335.         async_set_client_connection(fs_connection);
  336.  
  337.         /* Register service at nameserver */
  338.         if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
  339.             return -1;
  340.        
  341.         async_manager();
  342.  
  343.         /* Never reached */
  344.         return 0;
  345.     }
  346.    
  347.     return -1;
  348. }
  349.  
  350. /**
  351.  * @}
  352.  */
  353.