X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffilesys%2Ffilesys.c;h=c0e3938d7dcac457be1d5f54afb5b2e83311a39b;hb=f2f8875638593bd5365cfd6a5ba7c9578e52322f;hp=2cc07217aa19dddb75d8f188bcb77e7a579d8db5;hpb=621963e2a383d53b2c5eca627102625421b46545;p=pintos-anon diff --git a/src/filesys/filesys.c b/src/filesys/filesys.c index 2cc0721..c0e3938 100644 --- a/src/filesys/filesys.c +++ b/src/filesys/filesys.c @@ -1,94 +1,143 @@ -#include "filesys.h" -#include "bitmap.h" -#include "debug.h" -#include "directory.h" -#include "disk.h" -#include "file.h" -#include "filehdr.h" -#include "lib.h" - -#define FREE_MAP_SECTOR 0 -#define ROOT_DIR_SECTOR 1 - -#define NUM_DIR_ENTRIES 10 -#define ROOT_DIR_FILE_SIZE (sizeof (struct dir_entry) * NUM_DIR_ENTRIES) - +/* This file is derived from source code for the Nachos + instructional operating system. The Nachos copyright notice + is reproduced in full below. */ + +/* Copyright (c) 1992-1996 The Regents of the University of California. + All rights reserved. + + Permission to use, copy, modify, and distribute this software + and its documentation for any purpose, without fee, and + without written agreement is hereby granted, provided that the + above copyright notice and the following two paragraphs appear + in all copies of this software. + + IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO + ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR + CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE + AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA + HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY + WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" + BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO + PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + MODIFICATIONS. +*/ + +#include "filesys/filesys.h" +#include +#include +#include +#include +#include "filesys/file.h" +#include "filesys/filehdr.h" +#include "filesys/directory.h" +#include "devices/disk.h" + +/* Filesystem. + + The filesystem consists of a set of files. Each file has a + header, represented by struct filehdr, that is stored by + itself in a single sector (see filehdr.h). The header + contains the file's length in bytes and an array that lists + the sector numbers for the file's contents. + + Two files are special. The first special file is the free + map, whose header is always stored in sector 0 + (FREE_MAP_SECTOR). The free map stores a bitmap (see + lib/bitmap.h) that contains one bit for each sector on the + disk. Each bit that corresponds to a sector within a file is + set to true, and the other bits, which are not part of any + file, are set to false. + + The second special file is the root directory, whose header is + always stored in sector 1 (ROOT_DIR_SECTOR). The root + directory file stores an array of `struct dir_entry' (see + directory.h), each of which, if it is in use, associates a + filename with the sector of the file's header. + + The filesystem implemented here has the following limitations: + + - No synchronization. Concurrent accesses will interfere + with one another. + + - File size is fixed at creation time. Because the root + 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 sector + times the size of a sector, or 126 * 512 == 63 kB given + 32-bit sizes and 512-byte sectors. + + - No nested subdirectories. + + - Filenames limited to 14 characters. + + - A system crash mid-operation may corrupt the disk in a way + that cannot be repaired automatically. No `fsck' tool is + provided in any case. + + Note: 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. */ + +/* File header sectors for system files. */ +#define FREE_MAP_SECTOR 0 /* Free map file header sector. */ +#define ROOT_DIR_SECTOR 1 /* Root directory file header sector. */ + +/* Root directory. */ +#define NUM_DIR_ENTRIES 10 /* Maximum number of directory entries. */ +#define ROOT_DIR_FILE_SIZE /* Root directory file size in bytes. */ \ + (sizeof (struct dir_entry) * NUM_DIR_ENTRIES) + +/* The disk that contains the filesystem. */ struct disk *filesys_disk; +/* The free map and root directory files. + These files are opened by filesys_init() and never closed. */ static struct file free_map_file, root_dir_file; -static void -do_format (void) -{ - struct bitmap free_map; - struct filehdr *map_hdr, *dir_hdr; - struct dir dir; - - /* Create the initial bitmap and reserve sectors for the - free map and root directory file headers. */ - if (!bitmap_init (&free_map, disk_size (filesys_disk))) - panic ("bitmap creation failed--disk 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 file header to disk. */ - map_hdr = filehdr_allocate (&free_map, bitmap_storage_size (&free_map)); - if (map_hdr == NULL) - panic ("free map creation failed--disk is too large"); - filehdr_write (map_hdr, FREE_MAP_SECTOR); - filehdr_destroy (map_hdr); - - /* Allocate data sector(s) for the root directory file - and write its file header to disk. */ - dir_hdr = filehdr_allocate (&free_map, ROOT_DIR_FILE_SIZE); - if (dir_hdr == NULL) - panic ("root directory creation failed"); - filehdr_write (dir_hdr, ROOT_DIR_SECTOR); - filehdr_destroy (dir_hdr); - - /* Write out the free map now that we have space reserved - for it. */ - file_open (&free_map_file, FREE_MAP_SECTOR); - bitmap_write (&free_map, &free_map_file); - bitmap_destroy (&free_map); - file_close (&free_map_file); - - /* Write out the root directory in the same way. */ - if (!file_open (&root_dir_file, ROOT_DIR_SECTOR)) - panic ("can't open root directory"); - if (!dir_init (&dir, NUM_DIR_ENTRIES)) - panic ("can't initialize root directory"); - dir_write (&dir, &root_dir_file); - dir_destroy (&dir); - file_close (&free_map_file); -} +static void do_format (void); +/* Initializes the filesystem module. + If FORMAT is true, reformats the filesystem. */ void filesys_init (bool format) { - filesys_disk = disk_get (1); + filesys_disk = disk_get (0, 1); if (filesys_disk == NULL) - panic ("ide1:1 not present, filesystem initialization failed"); + PANIC ("hd0:1 (hdb) not present, filesystem initialization failed"); if (format) do_format (); - file_open (&free_map_file, FREE_MAP_SECTOR); - file_open (&root_dir_file, ROOT_DIR_SECTOR); + if (!file_open (&free_map_file, FREE_MAP_SECTOR)) + PANIC ("can't open free map file"); + if (!file_open (&root_dir_file, ROOT_DIR_SECTOR)) + PANIC ("can't open root dir file"); } +/* Creates a file named NAME with the given INITIAL_SIZE. + Returns true if successful, false otherwise. + Fails if a file named NAME already exists, + or if internal memory allocation fails. */ bool filesys_create (const char *name, off_t initial_size) { struct dir dir; struct bitmap free_map; - disk_sector_no hdr_sector; + disk_sector_t hdr_sector; struct filehdr *filehdr; bool success = false; /* Read the root directory. */ - dir_init (&dir, NUM_DIR_ENTRIES); + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + return false; dir_read (&dir, &root_dir_file); if (dir_lookup (&dir, name, NULL)) goto exit1; @@ -127,14 +176,20 @@ filesys_create (const char *name, off_t initial_size) return success; } +/* 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. + Fails if no file named NAME exists, + or if an internal memory allocation fails. */ bool filesys_open (const char *name, struct file *file) { struct dir dir; - disk_sector_no hdr_sector; + disk_sector_t hdr_sector; bool success = false; - dir_init (&dir, NUM_DIR_ENTRIES); + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + return false; dir_read (&dir, &root_dir_file); if (dir_lookup (&dir, name, &hdr_sector)) success = file_open (file, hdr_sector); @@ -143,17 +198,22 @@ filesys_open (const char *name, struct file *file) return success; } +/* Deletes the file named NAME. + Returns true if successful, false on failure. + Fails if no file named NAME exists, + or if an internal memory allocation fails. */ bool filesys_remove (const char *name) { struct dir dir; - disk_sector_no hdr_sector; + disk_sector_t hdr_sector; struct filehdr *filehdr; struct bitmap free_map; bool success = false; /* Read the root directory. */ - dir_init (&dir, NUM_DIR_ENTRIES); + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + return false; dir_read (&dir, &root_dir_file); if (!dir_lookup (&dir, name, &hdr_sector)) goto exit1; @@ -189,17 +249,57 @@ filesys_remove (const char *name) return success; } -static void must_succeed_function (int, int) ATTRIBUTE((noinline)); +/* Prints a list of files in the filesystem to the system + console. + Returns true if successful, false on failure, + which occurs only if an internal memory allocation fails. */ +bool +filesys_list (void) +{ + struct dir dir; -static void -must_succeed_function (int line_no, int success) + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + return false; + dir_read (&dir, &root_dir_file); + dir_list (&dir); + dir_destroy (&dir); + + return true; +} + +/* Dumps the filesystem 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. */ +bool +filesys_dump (void) { - if (!success) - panic ("filesys_self_test: operation failed on line %d", line_no); + struct bitmap free_map; + struct dir dir; + + printf ("Free map:\n"); + if (!bitmap_init (&free_map, disk_size (filesys_disk))) + return false; + bitmap_read (&free_map, &free_map_file); + bitmap_dump (&free_map); + bitmap_destroy (&free_map); + printf ("\n"); + + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + return false; + dir_read (&dir, &root_dir_file); + dir_dump (&dir); + dir_destroy (&dir); + + return true; } +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 + called. */ void filesys_self_test (void) { @@ -223,5 +323,67 @@ filesys_self_test (void) MUST_SUCCEED (filesys_remove ("foo")); - printk ("filesys: self test ok\n"); + printf ("filesys: self test ok\n"); +} + +/* Formats the filesystem. */ +static void +do_format (void) +{ + struct bitmap free_map; + struct filehdr *map_hdr, *dir_hdr; + struct dir dir; + + printf ("Formatting filesystem..."); + + /* Create the initial bitmap and reserve sectors for the + free map and root directory file headers. */ + if (!bitmap_init (&free_map, disk_size (filesys_disk))) + PANIC ("bitmap creation failed--disk 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 file header to disk. */ + map_hdr = filehdr_allocate (&free_map, bitmap_file_size (&free_map)); + if (map_hdr == NULL) + PANIC ("free map creation failed--disk is too large"); + filehdr_write (map_hdr, FREE_MAP_SECTOR); + filehdr_destroy (map_hdr); + + /* Allocate data sector(s) for the root directory file + and write its file header to disk. */ + dir_hdr = filehdr_allocate (&free_map, ROOT_DIR_FILE_SIZE); + if (dir_hdr == NULL) + PANIC ("root directory creation failed"); + filehdr_write (dir_hdr, ROOT_DIR_SECTOR); + filehdr_destroy (dir_hdr); + + /* Write out the free map now that we have space reserved + for it. */ + if (!file_open (&free_map_file, FREE_MAP_SECTOR)) + PANIC ("can't open free map file"); + bitmap_write (&free_map, &free_map_file); + bitmap_destroy (&free_map); + file_close (&free_map_file); + + /* Write out the root directory in the same way. */ + if (!file_open (&root_dir_file, ROOT_DIR_SECTOR)) + PANIC ("can't open root directory"); + if (!dir_init (&dir, NUM_DIR_ENTRIES)) + PANIC ("can't initialize root directory"); + dir_write (&dir, &root_dir_file); + dir_destroy (&dir); + file_close (&free_map_file); + + printf ("done.\n"); +} + +/* If SUCCESS is false, panics with an error complaining about + LINE_NO. */ +static void +must_succeed_function (int line_no, bool success) +{ + if (!success) + PANIC ("filesys_self_test: operation failed on line %d", line_no); }