Start work on partition support.
[pintos-anon] / src / filesys / filesys.c
index 59212ca774f3cf64e3878d82a593216bf294101d..847bfb85c93b81b8846fd2908e110532db1b0672 100644 (file)
 #include "filesys/inode.h"
 #include "filesys/directory.h"
 #include "devices/disk.h"
+#include "devices/partition.h"
 
 /* Filesystem.
 
-   For the purposes of the "user processes" assignment (project
-   2), please treat all the code in the filesys directory as a
-   black box.  No changes should be needed.  For that project, a
-   single lock external to the filesystem code suffices.
+   For the purposes of the "user processes" and "virtual memory"
+   assignments (projects 2 and 3), please treat all the code in
+   the filesys directory as a black box.  No changes should be
+   needed.  For those projects, a single lock external to the
+   file system code suffices.
 
-   The filesystem consists of a set of files.  Each file has a
+   The file system consists of a set of files.  Each file has a
    header called an `index node' or `inode', represented by
    struct inode, that is stored by itself in a single sector (see
    inode.h).  The header contains the file's length in bytes and
@@ -64,7 +66,7 @@
    directory.h), each of which, if it is in use, associates a
    filename with the sector of the file's inode.
 
-   The filesystem implemented here has the following limitations:
+   The file system implemented here has the following limitations:
 
      - No synchronization.  Concurrent accesses will interfere
        with one another, so external synchronization is needed.
        directory is represented as a file, the number of files
        that may be created is also limited.
 
-     - No indirect blocks.  This limits maximum file size to the
-       number of sector pointers that fit in a single inode
-       times the size of a sector, or 126 * 512 == 63 kB given
-       32-bit sizes and 512-byte sectors.
+     - File data is allocated as a single extent, so that
+       external fragmentation can become a serious problem as a
+       file system is used over time.
 
      - No subdirectories.
 
 /* Root directory. */
 #define NUM_DIR_ENTRIES 10      /* Maximum number of directory entries. */
 
-/* The disk that contains the filesystem. */
-struct disk *filesys_disk;
+/* The partition that contains the file system. */
+struct partition *filesys_partition;
 
 /* The free map and root directory files.
    These files are opened by filesys_init() and never closed. */
@@ -109,16 +110,16 @@ struct file *free_map_file, *root_dir_file;
 
 static void do_format (void);
 
-/* Initializes the filesystem module.
-   If FORMAT is true, reformats the filesystem. */
+/* Initializes the file system module.
+   If FORMAT is true, reformats the file system. */
 void
 filesys_init (bool format) 
 {
   inode_init ();
 
-  filesys_disk = disk_get (0, 1);
-  if (filesys_disk == NULL)
-    PANIC ("hd0:1 (hdb) not present, filesystem initialization failed");
+  filesys_partition = partition_get (PARTITION_FILESYS);
+  if (filesys_partition == NULL)
+    PANIC ("missing file system partition");
 
   if (format) 
     do_format ();
@@ -131,7 +132,7 @@ filesys_init (bool format)
     PANIC ("can't open root dir file");
 }
 
-/* Shuts down the filesystem module, writing any unwritten data
+/* Shuts down the file system module, writing any unwritten data
    to disk.
    Currently there's nothing to do.  You'll need to add code here
    when you implement write-behind caching. */
@@ -149,7 +150,6 @@ filesys_create (const char *name, off_t initial_size)
 {
   struct dir *dir = NULL;
   struct bitmap *free_map = NULL;
-  struct inode *inode = NULL;
   disk_sector_t inode_sector;
   bool success = false;
 
@@ -162,11 +162,11 @@ filesys_create (const char *name, off_t initial_size)
     goto done;
 
   /* Allocate a block for the inode. */
-  free_map = bitmap_create (disk_size (filesys_disk));
+  free_map = bitmap_create (partition_size (filesys_partition));
   if (free_map == NULL)
     goto done;
   bitmap_read (free_map, free_map_file);
-  inode_sector = bitmap_find_and_set (free_map);
+  inode_sector = bitmap_scan_and_flip (free_map, 0, 1, false);
   if (inode_sector == BITMAP_ERROR)
     goto done;
 
@@ -175,12 +175,10 @@ filesys_create (const char *name, off_t initial_size)
     goto done;
 
   /* Allocate space for the file. */
-  inode = inode_create (free_map, inode_sector, initial_size);
-  if (inode == NULL)
+  if (!inode_create (free_map, inode_sector, initial_size))
     goto done;
 
   /* Write everything back. */
-  inode_commit (inode);
   dir_write (dir, root_dir_file);
   bitmap_write (free_map, free_map_file);
 
@@ -188,7 +186,6 @@ filesys_create (const char *name, off_t initial_size)
 
   /* Clean up. */
  done:
-  inode_close (inode);
   bitmap_destroy (free_map);
   dir_destroy (dir);
 
@@ -197,7 +194,8 @@ filesys_create (const char *name, off_t initial_size)
 
 /* Opens a file named NAME and initializes FILE for usage with
    the file_*() functions declared in file.h.
-   Returns true if successful, false on failure.
+   Returns the new file if successful or a null pointer
+   otherwise.
    Fails if no file named NAME exists,
    or if an internal memory allocation fails. */
 struct file *
@@ -241,7 +239,7 @@ filesys_remove (const char *name)
   if (!dir_lookup (dir, name, &inode_sector))
     goto done;
 
-  /* Open the inode and delete it it. */
+  /* Open the inode and delete it. */
   inode = inode_open (inode_sector);
   if (inode == NULL)
     goto done;
@@ -262,7 +260,7 @@ filesys_remove (const char *name)
   return success;
 }
 
-/* Prints a list of files in the filesystem to the system
+/* Prints a list of files in the file system to the system
    console.
    Returns true if successful, false on failure,
    which occurs only if an internal memory allocation fails. */
@@ -279,7 +277,7 @@ filesys_list (void)
   return true;
 }
 
-/* Dumps the filesystem state to the system console,
+/* Dumps the file system state to the system console,
    including the free map, the list of files, and file contents.
    Returns true if successful, false on failure,
    which occurs only if an internal memory allocation fails. */
@@ -290,7 +288,7 @@ filesys_dump (void)
   struct dir *dir;  
 
   printf ("Free map:\n");
-  free_map = bitmap_create (disk_size (filesys_disk));
+  free_map = bitmap_create (partition_size (filesys_partition));
   if (free_map == NULL)
     return false;
   bitmap_read (free_map, free_map_file);
@@ -311,8 +309,8 @@ filesys_dump (void)
 static void must_succeed_function (int, bool) NO_INLINE;
 #define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
 
-/* Performs basic sanity checks on the filesystem.
-   The filesystem should not contain a file named `foo' when
+/* Performs basic sanity checks on the file system.
+   The file system should not contain a file named `foo' when
    called. */
 void
 filesys_self_test (void)
@@ -347,54 +345,39 @@ filesys_self_test (void)
          Delete file while open to check proper semantics. */
       MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
       MUST_SUCCEED (filesys_remove ("foo"));
+      MUST_SUCCEED (filesys_open ("foo") == NULL);
       MUST_SUCCEED (file_read (file, s2, sizeof s) == sizeof s);
       MUST_SUCCEED (memcmp (s, s2, sizeof s) == 0);
       MUST_SUCCEED (file_tell (file) == sizeof s);
       MUST_SUCCEED (file_length (file) == sizeof s);
       file_close (file);
-
-      /* Make sure file is deleted. */
-      MUST_SUCCEED ((file = filesys_open ("foo")) == NULL);
     }
   
   printf ("filesys: self test ok\n");
 }
 \f
-/* Formats the filesystem. */
+/* Formats the file system. */
 static void
 do_format (void)
 {
   struct bitmap *free_map;
-  struct inode *map_inode, *dir_inode;
   struct dir *dir;
 
-  printf ("Formatting filesystem...");
+  printf ("Formatting file system...");
 
   /* Create the initial bitmap and reserve sectors for the
      free map and root directory inodes. */
-  free_map = bitmap_create (disk_size (filesys_disk));
+  free_map = bitmap_create (partition_size (filesys_partition));
   if (free_map == NULL)
-    PANIC ("bitmap creation failed--disk is too large");
+    PANIC ("bitmap creation failed--file system partition is too large");
   bitmap_mark (free_map, FREE_MAP_SECTOR);
   bitmap_mark (free_map, ROOT_DIR_SECTOR);
 
-  /* Allocate data sector(s) for the free map file
-     and write its inode to disk. */
-  map_inode = inode_create (free_map, FREE_MAP_SECTOR,
-                            bitmap_file_size (free_map));
-  if (map_inode == NULL)
-    PANIC ("free map creation failed--disk is too large");
-  inode_commit (map_inode);
-  inode_close (map_inode);
-
-  /* Allocate data sector(s) for the root directory file
-     and write its inodes to disk. */
-  dir_inode = inode_create (free_map, ROOT_DIR_SECTOR,
-                            dir_size (NUM_DIR_ENTRIES));
-  if (dir_inode == NULL)
+  /* Allocate free map and root dir files. */
+  if (!inode_create (free_map, FREE_MAP_SECTOR, bitmap_file_size (free_map)))
+    PANIC ("free map creation failed--file system partition is too large");
+  if (!inode_create (free_map, ROOT_DIR_SECTOR, dir_size (NUM_DIR_ENTRIES)))
     PANIC ("root directory creation failed");
-  inode_commit (dir_inode);
-  inode_close (dir_inode);
 
   /* Write out the free map now that we have space reserved
      for it. */