Subversion Repositories HelenOS

Rev

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