Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  * Copyright (c) 2007 Konopa-Jelen-Majer
  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 FileSystemTask
  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. /**
  67.  * Respond to incoming requests from user tasks
  68.  */
  69. static void fs_connection(ipc_callid_t iid, ipc_call_t *icall)
  70. {
  71.  
  72.     int result = 0;
  73.     ipcarg_t arg = 0;
  74.  
  75.     ipc_answer_fast(iid, 0, 0, 0);
  76.    
  77.     while (1)
  78.     {
  79.         prepare_message();
  80.        
  81.         switch (fs_call)
  82.         {
  83.             case IPC_M_PHONE_HUNGUP:
  84.                 ipc_answer_fast(callid, 0,0,0);
  85.                 return;
  86.  
  87.             case FS_NEW_CONSUMER:
  88.                 if (!new_consument) {
  89.                     result = FS_ECONNECT;  
  90.                 }
  91.                 else {
  92.                     result = new_consument_map();  
  93.                     if (!result) {
  94.                         new_consument = FALSE;     
  95.                     }
  96.                 }
  97.                 break;
  98.  
  99.             case IPC_M_AS_AREA_SEND:
  100.                 if (!new_consument)
  101.                     result = FS_ECONNECT;      
  102.                 else {
  103.                     result = 0;
  104.                     arg = (uintptr_t)fp->buffer;
  105.                     fp = &fproc[new_consument];
  106.                     fp->connected = TRUE;
  107.                     new_consument = FALSE;
  108.                 }
  109.                 break;
  110.  
  111.             case FS_DROP_CONSUMER:
  112.                 fproc->connected = FALSE;
  113.                 fproc->buffer = NULL;
  114.                 result = 0;
  115.                 break;
  116.  
  117.             default:
  118.                 if (check_con < 0) {
  119.                     result = err_code;
  120.                     check_con = TRUE;
  121.                     break; 
  122.                 }
  123.                 if (FS_IN_RANGE(fs_call)) {  
  124.                     result = call_vector[fs_call-FS_BASE]();
  125.                 }
  126.                 else {
  127.                     result = FS_EBADCALL;
  128.                 }
  129.                 break; 
  130.            
  131.         }
  132.    
  133.         ipc_answer_fast(callid, result, arg, 0);
  134.         arg = 0;       
  135.     }  
  136. }
  137.  
  138. /**
  139.  * Extracts parameters from message and prepare them for later usage.
  140.  */
  141. void prepare_message(void)
  142. {
  143.    
  144.     int shift, id_task;
  145.  
  146.  
  147.     callid = async_get_call(&m_input);
  148.     fs_call = IPC_GET_METHOD(m_input);
  149.    
  150.     if (fs_call == IPC_M_AS_AREA_SEND) {   
  151.         if (!new_consument) {
  152.             new_consument = FALSE;
  153.         }
  154.  
  155.         return;
  156.     }
  157.    
  158.     id_task = IPC_GET_ARG1(m_input);    
  159.    
  160.     /* Setup new consument. */
  161.     if (fs_call == FS_NEW_CONSUMER) {
  162.         if (!new_consument) {
  163.             new_consument = id_task;
  164.         }
  165.         else {
  166.             new_consument = FALSE;
  167.         }
  168.  
  169.         return;
  170.     }
  171.    
  172.     /* Other messages discard process of new consument connecting. */
  173.     if (new_consument) {
  174.         new_consument = FALSE;
  175.     }
  176.    
  177.     if (id_task < 0 || id_task >= NR_PROCS) {
  178.         check_con = FS_EINVAL;
  179.         return;    
  180.     }
  181.    
  182.     /* Switch to active consument. */
  183.     fp = &fproc[id_task];
  184.    
  185.     /* Check if consument was connected. */
  186.     if (!(fp->connected)) {
  187.         check_con = FS_ENOTCONNECT;
  188.         return;
  189.     }
  190.  
  191.    
  192.     /* Unpacking extended input message into message_params structure. */
  193.     unpack_message(&message_params, m_input, fp->buffer);
  194. }
  195.  
  196. /**
  197.  * Map some memory to the task
  198.  */
  199. int new_consument_map()
  200. {
  201.    
  202.     size_t size;
  203.     task_id_t task_id;
  204.  
  205.     task_id = new_consument;   
  206.     if (task_id < 0 || task_id >= NR_PROCS) {
  207.         return FS_EINVAL;
  208.     }
  209.  
  210.     fp = &fproc[task_id];
  211.     size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
  212.     fp->buffer = as_get_mappable_page(size, PAGE_COLOR((uintptr_t)fp->buffer));
  213.  
  214.     return TRUE;
  215. }
  216. /* Reads in the superblock from image. */
  217. int load_super(void)
  218. {
  219.    
  220.     super_block_t *sp;
  221.    
  222.     if (!init_super_block())
  223.         return FALSE;
  224.  
  225.         sp = get_super();
  226.     if (read_super(sp) != OK)
  227.     {
  228.         print_console("Super block read error\n");
  229.         return FALSE;
  230.     }
  231.  
  232.     return TRUE;
  233. }
  234.  
  235. /**
  236.  * Basic initialization.
  237.  */
  238. static bool fs_init(void)
  239. {
  240.    
  241.     register inode_t *rip;
  242.     int bad, i;
  243.    
  244.  
  245.     bad = 0;
  246.     callid = SERVICE_FS;
  247.     fp = (fproc_t *)NULL;
  248.    
  249.     print_console("FS initialization...");
  250.  
  251.     /* Block cache initialization. */
  252.     if (!init_block())
  253.         return FALSE;
  254.    
  255.     /* Loading superblock. */
  256.     if (!load_super())
  257.         return FALSE;
  258.        
  259.     for (i = 0; i < NR_PROCS; i++) {
  260.         if (i == SERVICE_FS)
  261.             continue;
  262.  
  263.         fp = &fproc[i];
  264.         rip = get_inode(ROOT_INODE);
  265.         fp->fp_rootdir = rip;
  266.         dup_inode(rip);
  267.         fp->fp_workdir = rip;
  268.     }
  269.    
  270.     fp = &fproc[SERVICE_FS];
  271.  
  272.     /* Certain relations must hold for the file system to work at all. */
  273.     if (SUPER_SIZE > BLOCK_SIZE) {
  274.         print_console("SUPER_SIZE > BLOCK_SIZE\n");
  275.         bad++;
  276.     }
  277.     if (BLOCK_SIZE % V1_INODE_SIZE != 0) { 
  278.         print_console("BLOCK_SIZE mod V1_INODE_SIZE != 0\n");
  279.         bad++;
  280.     }
  281.     if (OPEN_MAX > 127) {  
  282.         print_console("OPEN_MAX > 127\n");
  283.         bad++;
  284.     }
  285.     if (V1_INODE_SIZE != 32) { 
  286.         print_console("V1 inode size != 32\n");
  287.         bad++;
  288.     }
  289.    
  290.     if (V2_INODE_SIZE != 64) { 
  291.         print_console("V2 inode size != 64\n");
  292.         bad++;
  293.     }
  294.    
  295.     if (bad)
  296.         return FALSE;
  297.  
  298.     /* New consument flag settings. */
  299.     new_consument = FALSE;
  300.     check_con = FALSE;
  301.  
  302.     print_console("OK\n");
  303.    
  304.     return TRUE;
  305. }
  306.  
  307. /**
  308.  * The initialization method for the FS task, it connects to the RD service
  309.  * and then starts the asynchronous request listener for this task.
  310.  */
  311. int main(int argc, char **argv)
  312. {
  313.    
  314.     int retval, flags;
  315.     unsigned int size;
  316.  
  317.  
  318.     /* Initializing printing functions. */
  319.     if (!init_printing())
  320.         return -1;
  321.  
  322.     print_console("FS task\n");
  323.  
  324.     /* Connection to SERVICE_RD service. */
  325.     print_console("Connnection to SERVICE_RD...");
  326.     if (connect_to_rd(&rd_phone, RD_CONN_ATTEMPTS))
  327.         print_console("OK\n");
  328.     else {
  329.         print_console("FALSE\n");
  330.         return -1;
  331.     }
  332.    
  333.     /* Creating shared memory for usage with SERVICE_RD.  */
  334.     print_console("Creating address space area for share with SERVICE_RD task...");
  335.     size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
  336.     buffer = mmap(buffer, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
  337.     if ((int)buffer < 0) {
  338.         print_console_int("As_area_create error %d", (int)buffer);
  339.         return -1;
  340.     }
  341.     print_console("OK\n");
  342.  
  343.  
  344.     /* Mapping memory to SERVICE_RD. */
  345.     print_console("Sending memory to RD_SERVICE...");
  346.     flags = 0;
  347.     flags = AS_AREA_READ | AS_AREA_WRITE;
  348.     retval = async_req_3(rd_phone, IPC_M_AS_AREA_SEND, (uintptr_t)buffer, size, flags, NULL, NULL, NULL);
  349.     if (retval < 0) {
  350.         print_console_int("%d\n", retval);
  351.         return -1;
  352.     }
  353.     print_console("OK\n");
  354.  
  355.     if (fs_init()) {
  356.         ipcarg_t phonead;
  357.    
  358.         async_set_client_connection(fs_connection);
  359.  
  360.         /* Register service at nameserver */
  361.         if (ipc_connect_to_me(PHONE_NS, SERVICE_FS, 0, &phonead) != 0)
  362.             return -1;
  363.        
  364.         async_manager();
  365.  
  366.         /* Never reached */
  367.         return 0;
  368.     }
  369.    
  370.     return -1;
  371. }
  372.  
  373. /**
  374.  * @}
  375.  */
  376.