Subversion Repositories HelenOS

Rev

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