thread: Properly protect 'all_list' around insertion.
[pintos-anon] / solutions / p4.patch
index 61ef9e8ab541aae4cd490003585a50b318db4c91..b94410b937d2629aa47de76bdbae127036420dfa 100644 (file)
@@ -1,7 +1,7 @@
 Index: src/Makefile.build
 diff -u src/Makefile.build~ src/Makefile.build
---- src/Makefile.build 2005-06-18 20:20:47.000000000 -0700
-+++ src/Makefile.build 2006-05-18 21:26:51.000000000 -0700
+--- src/Makefile.build~
++++ src/Makefile.build
 @@ -53,7 +53,9 @@ userprog_SRC += userprog/gdt.c               # GDT in
  userprog_SRC += userprog/tss.c                # TSS management.
  
@@ -23,8 +23,8 @@ diff -u src/Makefile.build~ src/Makefile.build
  OBJECTS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(SOURCES)))
 Index: src/devices/timer.c
 diff -u src/devices/timer.c~ src/devices/timer.c
---- src/devices/timer.c        2005-07-06 13:45:36.000000000 -0700
-+++ src/devices/timer.c        2006-05-18 21:26:51.000000000 -0700
+--- src/devices/timer.c~
++++ src/devices/timer.c
 @@ -23,6 +23,9 @@ static volatile int64_t ticks;
     Initialized by timer_calibrate(). */
  static unsigned loops_per_tick;
@@ -44,7 +44,7 @@ diff -u src/devices/timer.c~ src/devices/timer.c
  }
  
  /* Calibrates loops_per_tick, used to implement brief delays. */
-@@ -87,15 +92,36 @@ timer_elapsed (int64_t then) 
+@@ -93,16 +93,37 @@
    return timer_ticks () - then;
  }
  
@@ -60,7 +60,8 @@ diff -u src/devices/timer.c~ src/devices/timer.c
 +  return a->wakeup_time < b->wakeup_time;
 +}
 +
- /* Suspends execution for approximately TICKS timer ticks. */
+ /* Sleeps for approximately TICKS timer ticks.  Interrupts must
+    be turned on. */
  void
  timer_sleep (int64_t ticks) 
  {
@@ -83,7 +84,7 @@ diff -u src/devices/timer.c~ src/devices/timer.c
 +  sema_down (&t->timer_sema);
  }
  
- /* Suspends execution for approximately MS milliseconds. */
+ /* Sleeps for approximately MS milliseconds.  Interrupts must be
 @@ -132,6 +158,16 @@ timer_interrupt (struct intr_frame *args
  {
    ticks++;
@@ -103,36 +104,36 @@ diff -u src/devices/timer.c~ src/devices/timer.c
  /* Returns true if LOOPS iterations waits for more than one timer
 Index: src/filesys/Make.vars
 diff -u src/filesys/Make.vars~ src/filesys/Make.vars
---- src/filesys/Make.vars      2005-06-20 13:24:21.000000000 -0700
-+++ src/filesys/Make.vars      2006-05-18 21:26:51.000000000 -0700
-@@ -6,7 +6,7 @@ TEST_SUBDIRS = tests/userprog tests/file
+--- src/filesys/Make.vars~
++++ src/filesys/Make.vars
+@@ -6,8 +6,8 @@ TEST_SUBDIRS = tests/userprog tests/file
  GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.no-vm
+ SIMULATOR = --qemu
  
  # Uncomment the lines below to enable VM.
--#os.dsk: DEFINES += -DVM
+-#kernel.bin: DEFINES += -DVM
 -#KERNEL_SUBDIRS += vm
 -#TEST_SUBDIRS += tests/vm
 -#GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.with-vm
-+os.dsk: DEFINES += -DVM
++kernel.bin: DEFINES += -DVM
 +KERNEL_SUBDIRS += vm
 +TEST_SUBDIRS += tests/vm
 +GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.with-vm
 Index: src/filesys/cache.c
 diff -u src/filesys/cache.c~ src/filesys/cache.c
---- src/filesys/cache.c        1969-12-31 16:00:00.000000000 -0800
-+++ src/filesys/cache.c        2006-05-18 21:26:51.000000000 -0700
-@@ -0,0 +1,473 @@
+--- src/filesys/cache.c~
++++ src/filesys/cache.c
+@@ -0,0 +1,472 @@
 +#include "filesys/cache.h"
 +#include <debug.h>
 +#include <string.h>
 +#include "filesys/filesys.h"
-+#include "devices/disk.h"
 +#include "devices/timer.h"
 +#include "threads/malloc.h"
 +#include "threads/synch.h"
 +#include "threads/thread.h"
 +
-+#define INVALID_SECTOR ((disk_sector_t) -1)
++#define INVALID_SECTOR ((block_sector_t) -1)
 +
 +/* A cached block. */
 +struct cache_block 
@@ -151,7 +152,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +       Changing from allocated to free requires block_lock, block
 +       must be up-to-date and not dirty, and no one may be
 +       waiting on it. */
-+    disk_sector_t sector;
++    block_sector_t sector;
 +
 +    /* Is data[] correct?
 +       Requires write lock or data_lock. */
@@ -166,7 +167,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +       Access to data[] requires up-to-date and read or write lock.
 +       Bringing up-to-date requires write lock or data_lock. */
 +    struct lock data_lock;              /* Protects fields in group. */
-+    uint8_t data[DISK_SECTOR_SIZE];     /* Disk data. */
++    uint8_t data[BLOCK_SECTOR_SIZE];    /* Disk data. */
 +  };
 +
 +/* Cache. */
@@ -190,7 +191,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +
 +static void flushd_init (void);
 +static void readaheadd_init (void);
-+static void readaheadd_submit (disk_sector_t sector);
++static void readaheadd_submit (block_sector_t sector);
 +\f
 +/* Initializes cache. */
 +void
@@ -224,7 +225,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +  for (i = 0; i < CACHE_CNT; i++)
 +    {
 +      struct cache_block *b = &cache[i];
-+      disk_sector_t sector;
++      block_sector_t sector;
 +      
 +      lock_acquire (&b->block_lock);
 +      sector = b->sector;
@@ -236,7 +237,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +      b = cache_lock (sector, EXCLUSIVE);
 +      if (b->up_to_date && b->dirty) 
 +        {
-+          disk_write (filesys_disk, b->sector, b->data);
++          block_write (fs_device, b->sector, b->data);
 +          b->dirty = false; 
 +        }
 +      cache_unlock (b);
@@ -252,7 +253,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +   any number of other callers.  The calling thread may already
 +   have any number of non-exclusive locks on the block. */
 +struct cache_block *
-+cache_lock (disk_sector_t sector, enum lock_type type) 
++cache_lock (block_sector_t sector, enum lock_type type) 
 +{
 +  int i;
 +
@@ -358,7 +359,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +      /* Write block to disk if dirty. */
 +      if (b->up_to_date && b->dirty) 
 +        {
-+          disk_write (filesys_disk, b->sector, b->data);
++          block_write (fs_device, b->sector, b->data);
 +          b->dirty = false;
 +        }
 +
@@ -387,7 +388,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +
 +  /* Wait for cache contention to die down. */
 +  lock_release (&cache_sync);
-+  timer_sleep (1000);
++  timer_msleep (1000);
 +  goto try_again;
 +}
 +
@@ -401,7 +402,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +  lock_acquire (&b->data_lock);
 +  if (!b->up_to_date) 
 +    {
-+      disk_read (filesys_disk, b->sector, b->data);
++      block_read (fs_device, b->sector, b->data);
 +      b->up_to_date = true;
 +      b->dirty = false; 
 +    }
@@ -417,7 +418,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +cache_zero (struct cache_block *b) 
 +{
 +  ASSERT (b->writers);
-+  memset (b->data, 0, DISK_SECTOR_SIZE);
++  memset (b->data, 0, BLOCK_SECTOR_SIZE);
 +  b->up_to_date = true;
 +  b->dirty = true;
 +
@@ -467,7 +468,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +   writing it back to disk (even if dirty).
 +   The block must be entirely unused. */
 +void
-+cache_free (disk_sector_t sector) 
++cache_free (block_sector_t sector) 
 +{
 +  int i;
 +  
@@ -498,7 +499,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +}
 +
 +void
-+cache_readahead (disk_sector_t sector) 
++cache_readahead (block_sector_t sector) 
 +{
 +  readaheadd_submit (sector);
 +}
@@ -529,7 +530,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +struct readahead_block 
 +  {
 +    struct list_elem list_elem;         /* readahead_list element. */
-+    disk_sector_t sector;               /* Sector to read. */
++    block_sector_t sector;              /* Sector to read. */
 +  };
 +
 +/* Protects readahead_list.
@@ -556,7 +557,7 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +
 +/* Adds SECTOR to the read-ahead queue. */
 +static void
-+readaheadd_submit (disk_sector_t sector) 
++readaheadd_submit (block_sector_t sector) 
 +{
 +  /* Allocate readahead block. */
 +  struct readahead_block *block = malloc (sizeof *block);
@@ -597,13 +598,13 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +}
 Index: src/filesys/cache.h
 diff -u src/filesys/cache.h~ src/filesys/cache.h
---- src/filesys/cache.h        1969-12-31 16:00:00.000000000 -0800
-+++ src/filesys/cache.h        2006-05-18 21:26:51.000000000 -0700
+--- src/filesys/cache.h~
++++ src/filesys/cache.h
 @@ -0,0 +1,23 @@
 +#ifndef FILESYS_CACHE_H
 +#define FILESYS_CACHE_H
 +
-+#include "devices/disk.h"
++#include "devices/block.h"
 +
 +/* Type of block lock. */
 +enum lock_type 
@@ -614,34 +615,71 @@ diff -u src/filesys/cache.h~ src/filesys/cache.h
 +
 +void cache_init (void);
 +void cache_flush (void);
-+struct cache_block *cache_lock (disk_sector_t, enum lock_type);
++struct cache_block *cache_lock (block_sector_t, enum lock_type);
 +void *cache_read (struct cache_block *);
 +void *cache_zero (struct cache_block *);
 +void cache_dirty (struct cache_block *);
 +void cache_unlock (struct cache_block *);
-+void cache_free (disk_sector_t);
-+void cache_readahead (disk_sector_t);
++void cache_free (block_sector_t);
++void cache_readahead (block_sector_t);
 +
 +#endif /* filesys/cache.h */
 Index: src/filesys/directory.c
 diff -u src/filesys/directory.c~ src/filesys/directory.c
---- src/filesys/directory.c    2006-05-18 22:26:21.000000000 -0700
-+++ src/filesys/directory.c    2006-05-18 22:18:19.000000000 -0700
-@@ -20,21 +20,13 @@ struct dir_entry 
+--- src/filesys/directory.c~
++++ src/filesys/directory.c
+@@ -1,4 +1,5 @@
+ #include <string.h>
+ #include <list.h>
++#include "filesys/free-map.h"
+ #include "filesys/filesys.h"
+ #include "filesys/inode.h"
+@@ -21,12 +21,39 @@ struct dir_entry 
      bool in_use;                        /* In use or free? */
    };
  
 -/* Creates a directory with space for ENTRY_CNT entries in the
 -   given SECTOR.  Returns true if successful, false on failure. */
++/* Creates a directory in the given SECTOR.
++   The directory's parent is in PARENT_SECTOR.
++   Returns inode of created directory if successful,
++   null pointer on faiilure.
++   On failure, SECTOR is released in the free map. */
 -bool
--dir_create (disk_sector_t sector, size_t entry_cnt) 
--{
++struct inode *
+-dir_create (block_sector_t sector, size_t entry_cnt)
++dir_create (block_sector_t sector, block_sector_t parent_sector)
+ {
 -  return inode_create (sector, entry_cnt * sizeof (struct dir_entry));
--}
--
++  struct inode *inode = inode_create (sector, DIR_INODE);
++  if (inode != NULL) 
++    {
++      struct dir_entry entries[2];
++
++      memset (entries, 0, sizeof entries);
++
++      /* "." entry. */
++      entries[0].inode_sector = sector;
++      strlcpy (entries[0].name, ".", sizeof entries[0].name);
++      entries[0].in_use = true;
++
++      /* ".." entry. */
++      entries[1].inode_sector = parent_sector;
++      strlcpy (entries[1].name, "..", sizeof entries[1].name);
++      entries[1].in_use = true;
++      
++      if (inode_write_at (inode, entries, sizeof entries, 0) != sizeof entries)
++        {
++          inode_remove (inode);
++          inode_close (inode); 
++          inode = NULL;
++        } 
++    }
++  return inode;
+ }
  /* Opens and returns the directory for the given INODE, of which
-    it takes ownership.  Returns a null pointer on failure. */
- struct dir *
+@@ -35,7 +59,7 @@ struct dir *
  dir_open (struct inode *inode) 
  {
    struct dir *dir = calloc (1, sizeof *dir);
@@ -649,8 +687,8 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
 +  if (inode != NULL && dir != NULL && inode_get_type (inode) == DIR_INODE)
      {
        dir->inode = inode;
-       return dir;
-@@ -67,10 +67,8 @@ dir_close (struct dir *dir) 
+       dir->pos = 0;
+@@ -84,10 +108,8 @@ dir_get_inode (struct dir *dir) 
  }
  
  /* Searches DIR for a file with the given NAME.
@@ -663,20 +701,28 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
  static bool
  lookup (const struct dir *dir, const char *name,
          struct dir_entry *ep, off_t *ofsp) 
-@@ -107,10 +105,12 @@ dir_lookup (const struct dir *dir, const
+@@ -120,15 +142,16 @@ dir_lookup (const struct dir *dir, const
+             struct inode **inode) 
+ {
+   struct dir_entry e;
++  bool ok;
    ASSERT (dir != NULL);
    ASSERT (name != NULL);
  
+-  if (lookup (dir, name, &e, NULL))
+-    *inode = inode_open (e.inode_sector);
+-  else
+-    *inode = NULL;
 +  inode_lock (dir->inode);
-   if (lookup (dir, name, &e, NULL))
-     *inode = inode_open (e.inode_sector);
-   else
-     *inode = NULL;
++  ok = lookup (dir, name, &e, NULL);
 +  inode_unlock (dir->inode);
  
++  *inode = ok ? inode_open (e.inode_sector) : NULL;
    return *inode != NULL;
  }
-@@ -132,10 +132,11 @@ dir_add (struct dir *dir, const char *na
+@@ -149,10 +172,11 @@ dir_add (struct dir *dir, const char *na
    ASSERT (name != NULL);
  
    /* Check NAME for validity. */
@@ -689,7 +735,7 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
    if (lookup (dir, name, NULL, NULL))
      goto done;
  
-@@ -158,6 +159,7 @@ dir_add (struct dir *dir, const char *na
+@@ -175,6 +199,7 @@ dir_add (struct dir *dir, const char *na
    success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
  
   done:
@@ -697,32 +743,53 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
    return success;
  }
  
-@@ -176,12 +178,14 @@ dir_remove (struct dir *dir, const char 
+@@ -192,13 +217,37 @@ dir_remove (struct dir *dir, const char 
+   ASSERT (dir != NULL);
    ASSERT (name != NULL);
  
++  if (!strcmp (name, ".") || !strcmp (name, ".."))
++    return false;
++
    /* Find directory entry. */
 +  inode_lock (dir->inode);
    if (!lookup (dir, name, &e, &ofs))
      goto done;
  
--  /* Open inode. */
-+  /* Open inode and verify that it is not an in-use directory. */
+   /* Open inode. */
    inode = inode_open (e.inode_sector);
--  if (inode == NULL)
-+  if (inode == NULL
-+      || (inode_get_type (inode) == DIR_INODE && inode_open_cnt (inode) != 1))
+   if (inode == NULL)
      goto done;
  
++  /* Verify that it is not an in-use or non-empty directory. */
++  if (inode_get_type (inode) == DIR_INODE)
++    {
++      struct dir_entry e2;
++      off_t pos;
++
++      if (inode_open_cnt (inode) != 1)
++        goto done;
++
++      inode_lock (inode);
++      for (pos = 0; inode_read_at (inode, &e2, sizeof e2, pos) == sizeof e2;
++           pos += sizeof e2)
++        if (e2.in_use && strcmp (e2.name, ".") && strcmp (e2.name, ".."))
++          {
++            inode_unlock (inode);
++            goto done;
++          }
++      inode_unlock (inode);
++    }
++ 
    /* Erase directory entry. */
-@@ -195,6 +199,7 @@ dir_remove (struct dir *dir, const char 
+@@ -211,6 +241,7 @@ dir_remove (struct dir *dir, const char 
+   success = true;
  
   done:
-   inode_close (inode);
 +  inode_unlock (dir->inode);
+   inode_close (inode);
    return success;
  }
-@@ -216,14 +216,17 @@
+@@ -223,14 +254,17 @@ dir_readdir (struct dir *dir, char name[
  {
    struct dir_entry e;
  
@@ -730,10 +797,11 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
    while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
      {
        dir->pos += sizeof e;
-       if (e.in_use)
+-      if (e.in_use)
++      if (e.in_use && strcmp (e.name, ".") && strcmp (e.name, ".."))
          {
-           strlcpy (name, e.name, NAME_MAX + 1);
 +          inode_unlock (dir->inode);
+           strlcpy (name, e.name, NAME_MAX + 1);
            return true;
          } 
      }
@@ -742,20 +810,53 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
  }
 Index: src/filesys/directory.h
 diff -u src/filesys/directory.h~ src/filesys/directory.h
---- src/filesys/directory.h    2006-05-18 22:26:02.000000000 -0700
-+++ src/filesys/directory.h    2006-05-18 22:05:40.000000000 -0700
-@@ -12,6 +11,5 @@
+--- src/filesys/directory.h~
++++ src/filesys/directory.h
+@@ -14,7 +14,7 @@
  struct inode;
  
  /* Opening and closing directories. */
--bool dir_create (disk_sector_t sector, size_t entry_cnt);
+-bool dir_create (block_sector_t sector, size_t entry_cnt);
++struct inode *dir_create (block_sector_t sector, block_sector_t parent_sector);
  struct dir *dir_open (struct inode *);
  struct dir *dir_open_root (void);
+ struct dir *dir_reopen (struct dir *);
 Index: src/filesys/file.c
 diff -u src/filesys/file.c~ src/filesys/file.c
---- src/filesys/file.c 2005-06-18 20:20:48.000000000 -0700
-+++ src/filesys/file.c 2006-05-18 22:14:15.000000000 -0700
-@@ -18,7 +18,7 @@ struct file *
+--- src/filesys/file.c~
++++ src/filesys/file.c
+@@ -1,4 +1,5 @@
+ #include "filesys/file.h"
+ #include <debug.h>
++#include "filesys/free-map.h"
+ #include "filesys/inode.h"
+ #include "threads/malloc.h"
+@@ -11,6 +11,24 @@ struct file 
+     bool deny_write;            /* Has file_deny_write() been called? */
+   };
++/* Creates a file in the given SECTOR,
++   initially LENGTH bytes long. 
++   Returns inode for the file on success, null pointer on failure.
++   On failure, SECTOR is released in the free map. */
++struct inode *
++file_create (block_sector_t sector, off_t length) 
++{
++  struct inode *inode = inode_create (sector, FILE_INODE);
++  if (inode != NULL && length > 0
++      && inode_write_at (inode, "", 1, length - 1) != 1)
++    {
++      inode_remove (inode); 
++      inode_close (inode);
++      inode = NULL;
++    }
++  return inode;
++}
++
+ /* Opens a file for the given INODE, of which it takes ownership,
+    and returns the new file.  Returns a null pointer if an
+    allocation fails or if INODE is null. */
+@@ -18,7 +34,7 @@ struct file *
  file_open (struct inode *inode) 
  {
    struct file *file = calloc (1, sizeof *file);
@@ -764,11 +865,30 @@ diff -u src/filesys/file.c~ src/filesys/file.c
      {
        file->inode = inode;
        file->pos = 0;
+Index: src/filesys/file.h
+diff -u src/filesys/file.h~ src/filesys/file.h
+--- src/filesys/file.h~
++++ src/filesys/file.h
+@@ -1,11 +1,14 @@
+ #ifndef FILESYS_FILE_H
+ #define FILESYS_FILE_H
++#include <stdbool.h>
++#include "devices/block.h"
+ #include "filesys/off_t.h"
+ struct inode;
+ /* Opening and closing files. */
++struct inode *file_create (block_sector_t sector, off_t length);
+ struct file *file_open (struct inode *);
+ struct file *file_reopen (struct file *);
+ void file_close (struct file *);
 Index: src/filesys/filesys.c
 diff -u src/filesys/filesys.c~ src/filesys/filesys.c
---- src/filesys/filesys.c      2006-05-18 22:26:21.000000000 -0700
-+++ src/filesys/filesys.c      2006-05-18 22:35:43.000000000 -0700
-@@ -2,11 +2,13 @@
+--- src/filesys/filesys.c~
++++ src/filesys/filesys.c
+@@ -2,10 +2,12 @@
  #include <debug.h>
  #include <stdio.h>
  #include <string.h>
@@ -777,11 +897,10 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  #include "filesys/free-map.h"
  #include "filesys/inode.h"
  #include "filesys/directory.h"
- #include "devices/disk.h"
 +#include "threads/thread.h"
  
  /* The disk that contains the file system. */
- struct disk *filesys_disk;
+ struct disk *fs_device;
 @@ -23,6 +25,7 @@ filesys_init (bool format) 
      PANIC ("hd0:1 (hdb) not present, file system initialization failed");
  
@@ -790,7 +909,7 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
    free_map_init ();
  
    if (format) 
-@@ -37,6 +40,99 @@ void
+@@ -37,6 +40,130 @@ void
  filesys_done (void) 
  {
    free_map_close ();
@@ -837,8 +956,8 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +   Stores the directory corresponding to the name into *DIRP,
 +   and the file name part into BASE_NAME. */
 +static bool
-+resolve_name (const char *name,
-+              struct dir **dirp, char base_name[NAME_MAX + 1]) 
++resolve_name_to_entry (const char *name,
++                       struct dir **dirp, char base_name[NAME_MAX + 1]) 
 +{
 +  struct dir *dir = NULL;
 +  struct inode *inode;
@@ -887,35 +1006,83 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +  *dirp = NULL;
 +  base_name[0] = '\0';
 +  return false;
++}
++
++/* Resolves relative or absolute file NAME to an inode.
++   Returns an inode if successful, or a null pointer on failure.
++   The caller is responsible for closing the returned inode. */
++static struct inode *
++resolve_name_to_inode (const char *name)
++{
++  if (name[0] == '/' && name[strspn (name, "/")] == '\0') 
++    {
++      /* The name represents the root directory.
++         There's no name part at all, so resolve_name_to_entry()
++         would reject it entirely.
++         Special case it. */
++      return inode_open (ROOT_DIR_SECTOR);
++    }
++  else 
++    {
++      struct dir *dir;
++      char base_name[NAME_MAX + 1];
++
++      if (resolve_name_to_entry (name, &dir, base_name)) 
++        {
++          struct inode *inode;
++          dir_lookup (dir, base_name, &inode);
++          dir_close (dir);
++          return inode; 
++        }
++      else
++        return NULL;
++    }
  }
  \f
  /* Creates a file named NAME with the given INITIAL_SIZE.
-@@ -44,16 +140,17 @@ filesys_done (void) 
+@@ -44,16 +171,32 @@ filesys_done (void) 
     Fails if a file named NAME already exists,
     or if internal memory allocation fails. */
  bool
 -filesys_create (const char *name, off_t initial_size) 
 +filesys_create (const char *name, off_t initial_size, enum inode_type type) 
  {
-+  struct dir *dir;
-+  char base_name[NAME_MAX + 1];
-   disk_sector_t inode_sector = 0;
+-  block_sector_t inode_sector = 0;
 -  struct dir *dir = dir_open_root ();
 -  bool success = (dir != NULL
 -                  && free_map_allocate (1, &inode_sector)
 -                  && inode_create (inode_sector, initial_size)
 -                  && dir_add (dir, name, inode_sector));
-+  bool success = (resolve_name (name, &dir, base_name)
-+                  && free_map_allocate (&inode_sector)
-+                  && inode_create (inode_sector, initial_size, type)
-+                  && dir_add (dir, base_name, inode_sector));
-   if (!success && inode_sector != 0) 
+-  if (!success && inode_sector != 0) 
 -    free_map_release (inode_sector, 1);
-+    free_map_release (inode_sector);
++  struct dir *dir;
++  char base_name[NAME_MAX + 1];
++  block_sector_t inode_sector;
++
++  bool success = (resolve_name_to_entry (name, &dir, base_name)
++                  && free_map_allocate (&inode_sector));
++  if (success) 
++    {
++      struct inode *inode;
++      if (type == FILE_INODE)
++        inode = file_create (inode_sector, initial_size);
++      else
++        inode = dir_create (inode_sector,
++                            inode_get_inumber (dir_get_inode (dir))); 
++      if (inode != NULL)
++        {
++          success = dir_add (dir, base_name, inode_sector);
++          if (!success)
++            inode_remove (inode);
++          inode_close (inode);
++        }
++      else
++        success = false;
++    }
    dir_close (dir);
  
    return success;
-@@ -64,17 +161,22 @@ filesys_create (const char *name, off_t 
+@@ -64,17 +199,10 @@ filesys_create (const char *name, off_t 
     otherwise.
     Fails if no file named NAME exists,
     or if an internal memory allocation fails. */
@@ -924,40 +1091,36 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  filesys_open (const char *name)
  {
 -  struct dir *dir = dir_open_root ();
-+  struct dir *dir = NULL;
-+  char base_name[NAME_MAX + 1];
-   struct inode *inode = NULL;
+-  struct inode *inode = NULL;
+-
 -  if (dir != NULL)
 -    dir_lookup (dir, name, &inode);
-+  if (!strcmp (name, "/"))
-+    inode = inode_open (ROOT_DIR_SECTOR);
-+  else if (!strcmp (name, "."))
-+    inode = inode_reopen (dir_get_inode (thread_current ()->wd));
-+  else if (resolve_name (name, &dir, base_name))
-+    dir_lookup (dir, base_name, &inode);
-   dir_close (dir);
+-  dir_close (dir);
+-
 -  return file_open (inode);
-+  return inode;
++  return resolve_name_to_inode (name);
  }
  
  /* Deletes the file named NAME.
-@@ -84,7 +182,11 @@ filesys_open (const char *name)
+@@ -84,12 +212,35 @@ filesys_open (const char *name)
  bool
  filesys_remove (const char *name) 
  {
 -  struct dir *dir = dir_open_root ();
 -  bool success = dir != NULL && dir_remove (dir, name);
-+  struct dir *dir = NULL;
+-  dir_close (dir); 
++  struct dir *dir;
 +  char base_name[NAME_MAX + 1];
-+  bool success = false;
-+
-+  if (resolve_name (name, &dir, base_name)) 
-+    success = dir_remove (dir, base_name);
-   dir_close (dir); 
++  bool success;
  
-@@ -91,5 +193,44 @@
++  if (resolve_name_to_entry (name, &dir, base_name)) 
++    {
++      success = dir_remove (dir, base_name);
++      dir_close (dir);
++    }
++  else
++    success = false;
++  
    return success;
  }
 +/* Change current directory to NAME.
@@ -965,75 +1128,23 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +bool
 +filesys_chdir (const char *name) 
 +{
-+  struct dir *dir;
-+
-+  /* Find new directory. */
-+  if (*name == '\0')
-+    return false;
-+  else if (name[strspn (name, "/")] == '\0')
-+    {
-+      dir = dir_open_root ();
-+      if (dir == NULL)
-+        return false; 
-+    }
-+  else 
++  struct dir *dir = dir_open (resolve_name_to_inode (name));
++  if (dir != NULL) 
 +    {
-+      char base_name[NAME_MAX + 1];
-+      struct inode *base_inode;
-+      struct dir *base_dir;
-+      if (!resolve_name (name, &dir, base_name)
-+          || !dir_lookup (dir, base_name, &base_inode)
-+          || (base_dir = dir_open (base_inode)) == NULL)
-+        {
-+          dir_close (dir);
-+          return false;
-+        }
-+      dir_close (dir);
-+      dir = base_dir;
++      dir_close (thread_current ()->wd);
++      thread_current ()->wd = dir;
++      return true;
 +    }
-+
-+  /* Change current directory. */
-+  dir_close (thread_current ()->wd);
-+  thread_current ()->wd = dir;
-+  
-+  return true;
++  else
++    return false;
 +}
-+
  \f
  static void must_succeed_function (int, bool) NO_INLINE;
  #define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
-@@ -129,8 +264,8 @@ filesys_self_test (void)
-     {
-       /* Create file and check that it contains zeros
-          throughout the created length. */
--      MUST_SUCCEED (filesys_create ("foo", sizeof s));
--      MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
-+      MUST_SUCCEED (filesys_create ("foo", sizeof s, FILE_INODE));
-+      MUST_SUCCEED ((file = file_open (filesys_open ("foo"))) != NULL);
-       MUST_SUCCEED (file_read (file, s2, sizeof s2) == sizeof s2);
-       MUST_SUCCEED (memcmp (s2, zeros, sizeof s) == 0);
-       MUST_SUCCEED (file_tell (file) == sizeof s);
-@@ -138,7 +273,7 @@ filesys_self_test (void)
-       file_close (file);
-       /* Reopen file and write to it. */
--      MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
-+      MUST_SUCCEED ((file = file_open (filesys_open ("foo"))) != NULL);
-       MUST_SUCCEED (file_write (file, s, sizeof s) == sizeof s);
-       MUST_SUCCEED (file_tell (file) == sizeof s);
-       MUST_SUCCEED (file_length (file) == sizeof s);
-@@ -146,7 +281,7 @@ filesys_self_test (void)
-       /* Reopen file and verify that it reads back correctly.
-          Delete file while open to check proper semantics. */
--      MUST_SUCCEED ((file = filesys_open ("foo")) != NULL);
-+      MUST_SUCCEED ((file = file_open (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);
-@@ -173,9 +308,13 @@ static void
+@@ -155,9 +306,18 @@ static void
  do_format (void)
  {
++  struct inode *inode;
    printf ("Formatting file system...");
 +
 +  /* Set up free map. */
@@ -1041,16 +1152,19 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 -  if (!dir_create (ROOT_DIR_SECTOR, 16))
 +
 +  /* Set up root directory. */
-+  if (!inode_create (ROOT_DIR_SECTOR, 0, DIR_INODE))
++  inode = dir_create (ROOT_DIR_SECTOR, ROOT_DIR_SECTOR);
++  if (inode == NULL)
      PANIC ("root directory creation failed");
--  free_map_close ();
++  inode_close (inode);  
++
+   free_map_close ();
 +
    printf ("done.\n");
  }
 Index: src/filesys/filesys.h
 diff -u src/filesys/filesys.h~ src/filesys/filesys.h
---- src/filesys/filesys.h      2005-06-18 20:20:48.000000000 -0700
-+++ src/filesys/filesys.h      2006-05-18 21:26:51.000000000 -0700
+--- src/filesys/filesys.h~
++++ src/filesys/filesys.h
 @@ -3,6 +3,7 @@
  
  #include <stdbool.h>
@@ -1059,7 +1173,7 @@ diff -u src/filesys/filesys.h~ src/filesys/filesys.h
  
  /* Sectors of system file inodes. */
  #define FREE_MAP_SECTOR 0       /* Free map file inode sector. */
-@@ -13,9 +14,10 @@ extern struct disk *filesys_disk;
+@@ -13,9 +14,10 @@ extern struct disk *fs_device;
  
  void filesys_init (bool format);
  void filesys_done (void);
@@ -1074,8 +1188,8 @@ diff -u src/filesys/filesys.h~ src/filesys/filesys.h
  
 Index: src/filesys/free-map.c
 diff -u src/filesys/free-map.c~ src/filesys/free-map.c
---- src/filesys/free-map.c     2005-06-18 20:20:48.000000000 -0700
-+++ src/filesys/free-map.c     2006-05-18 21:26:51.000000000 -0700
+--- src/filesys/free-map.c~
++++ src/filesys/free-map.c
 @@ -3,15 +3,18 @@
  #include <debug.h>
  #include "filesys/file.h"
@@ -1084,7 +1198,7 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
 +#include "threads/synch.h"
  
  static struct file *free_map_file;   /* Free map file. */
- static struct bitmap *free_map;      /* Free map, one bit per disk sector. */
+ static struct bitmap *free_map;      /* Free map, one bit per sector. */
 +static struct lock free_map_lock;    /* Mutual exclusion. */
  
  /* Initializes the free map. */
@@ -1093,25 +1207,25 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
  {
 +  lock_init (&free_map_lock);
 +
-   free_map = bitmap_create (disk_size (filesys_disk));
+   free_map = bitmap_create (block_size (fs_device));
    if (free_map == NULL)
-     PANIC ("bitmap creation failed--disk is too large");
-@@ -19,33 +22,32 @@ free_map_init (void) 
+     PANIC ("bitmap creation failed--file system device is too large");
+@@ -19,34 +22,33 @@
    bitmap_mark (free_map, ROOT_DIR_SECTOR);
  }
  
 -/* Allocates CNT consecutive sectors from the free map and stores
 -   the first into *SECTORP.
--   Returns true if successful, false if all sectors were
 +/* Allocates a sector from the free map and stores it into
 +   *SECTORP.
-+   Return true if successful, false if all sectors were
-    available. */
+    Returns true if successful, false if not enough consecutive
+    sectors were available or if the free_map file could not be
+    written. */
  bool
--free_map_allocate (size_t cnt, disk_sector_t *sectorp) 
-+free_map_allocate (disk_sector_t *sectorp) 
+-free_map_allocate (size_t cnt, block_sector_t *sectorp)
++free_map_allocate (block_sector_t *sectorp)
  {
--  disk_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
+-  block_sector_t sector = bitmap_scan_and_flip (free_map, 0, cnt, false);
 -  if (sector != BITMAP_ERROR
 -      && free_map_file != NULL
 -      && !bitmap_write (free_map, free_map_file))
@@ -1134,8 +1248,8 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
 -/* Makes CNT sectors starting at SECTOR available for use. */
 +/* Makes SECTOR available for use. */
  void
--free_map_release (disk_sector_t sector, size_t cnt)
-+free_map_release (disk_sector_t sector)
+-free_map_release (block_sector_t sector, size_t cnt)
++free_map_release (block_sector_t sector)
  {
 -  ASSERT (bitmap_all (free_map, sector, cnt));
 -  bitmap_set_multiple (free_map, sector, cnt, false);
@@ -1147,7 +1261,7 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
  }
  
  /* Opens the free map file and reads it from disk. */
-@@ -63,6 +65,8 @@ free_map_open (void) 
+@@ -64,6 +66,8 @@
  void
  free_map_close (void) 
  {
@@ -1156,40 +1270,40 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
    file_close (free_map_file);
  }
  
-@@ -72,7 +76,7 @@ void
+@@ -72,9 +76,13 @@
+ void
  free_map_create (void) 
  {
++  struct inode *inode;
++
    /* Create inode. */
 -  if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map)))
-+  if (!inode_create (FREE_MAP_SECTOR, bitmap_file_size (free_map), FILE_INODE))
++  inode = file_create (FREE_MAP_SECTOR, 0);
++  if (inode == NULL)   
      PANIC ("free map creation failed");
++  inode_close (inode);
  
    /* Write bitmap to file. */
-@@ -81,4 +85,5 @@ free_map_create (void) 
-     PANIC ("can't open free map");
-   if (!bitmap_write (free_map, free_map_file))
-     PANIC ("can't write free map");
-+  file_close (free_map_file);
- }
+   free_map_file = file_open (inode_open (FREE_MAP_SECTOR));
 Index: src/filesys/free-map.h
 diff -u src/filesys/free-map.h~ src/filesys/free-map.h
---- src/filesys/free-map.h     2005-06-18 20:20:48.000000000 -0700
-+++ src/filesys/free-map.h     2006-05-18 21:26:51.000000000 -0700
+--- src/filesys/free-map.h~
++++ src/filesys/free-map.h
 @@ -11,7 +11,7 @@ void free_map_create (void);
  void free_map_open (void);
  void free_map_close (void);
  
--bool free_map_allocate (size_t, disk_sector_t *);
--void free_map_release (disk_sector_t, size_t);
-+bool free_map_allocate (disk_sector_t *);
-+void free_map_release (disk_sector_t);
+-bool free_map_allocate (size_t, block_sector_t *);
+-void free_map_release (block_sector_t, size_t);
++bool free_map_allocate (block_sector_t *);
++void free_map_release (block_sector_t);
  
  #endif /* filesys/free-map.h */
 Index: src/filesys/fsutil.c
 diff -u src/filesys/fsutil.c~ src/filesys/fsutil.c
---- src/filesys/fsutil.c       2006-04-22 22:25:13.000000000 -0700
-+++ src/filesys/fsutil.c       2006-05-18 21:26:51.000000000 -0700
-@@ -30,7 +30,7 @@ fsutil_cat (char **argv)
+--- src/filesys/fsutil.c~
++++ src/filesys/fsutil.c
+@@ -38,7 +38,7 @@ fsutil_cat (char **argv)
    char *buffer;
  
    printf ("Printing '%s' to the console...\n", file_name);
@@ -1198,19 +1312,19 @@ diff -u src/filesys/fsutil.c~ src/filesys/fsutil.c
    if (file == NULL)
      PANIC ("%s: open failed", file_name);
    buffer = palloc_get_page (PAL_ASSERT);
-@@ -102,9 +102,9 @@ fsutil_put (char **argv) 
-     PANIC ("%s: invalid file size %d", file_name, size);
-   
-   /* Create destination file. */
--  if (!filesys_create (file_name, size))
-+  if (!filesys_create (file_name, size, FILE_INODE))
-     PANIC ("%s: create failed", file_name);
--  dst = filesys_open (file_name);
-+  dst = file_open (filesys_open (file_name));
-   if (dst == NULL)
-     PANIC ("%s: open failed", file_name);
-@@ -154,7 +154,7 @@ fsutil_get (char **argv)
+@@ -117,9 +117,9 @@
+           printf ("Putting '%s' into the file system...\n", file_name);
+           /* Create destination file. */
+-          if (!filesys_create (file_name, size))
++          if (!filesys_create (file_name, size, FILE_INODE))
+             PANIC ("%s: create failed", file_name);
+-          dst = filesys_open (file_name);
++          dst = file_open (filesys_open (file_name));
+           if (dst == NULL)
+             PANIC ("%s: open failed", file_name);
+@@ -162,7 +162,7 @@ fsutil_get (char **argv)
      PANIC ("couldn't allocate buffer");
  
    /* Open source file. */
@@ -1221,8 +1335,8 @@ diff -u src/filesys/fsutil.c~ src/filesys/fsutil.c
    size = file_length (src);
 Index: src/filesys/inode.c
 diff -u src/filesys/inode.c~ src/filesys/inode.c
---- src/filesys/inode.c        2006-04-08 12:09:33.000000000 -0700
-+++ src/filesys/inode.c        2006-05-18 22:18:19.000000000 -0700
+--- src/filesys/inode.c~
++++ src/filesys/inode.c
 @@ -1,23 +1,38 @@
  #include "filesys/inode.h"
 +#include <bitmap.h>
@@ -1245,18 +1359,18 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +#define DBL_INDIRECT_CNT 1
 +#define SECTOR_CNT (DIRECT_CNT + INDIRECT_CNT + DBL_INDIRECT_CNT)
 +
-+#define PTRS_PER_SECTOR ((off_t) (DISK_SECTOR_SIZE / sizeof (disk_sector_t))) 
++#define PTRS_PER_SECTOR ((off_t) (BLOCK_SECTOR_SIZE / sizeof (block_sector_t)))
 +#define INODE_SPAN ((DIRECT_CNT                                              \
 +                     + PTRS_PER_SECTOR * INDIRECT_CNT                        \
 +                     + PTRS_PER_SECTOR * PTRS_PER_SECTOR * DBL_INDIRECT_CNT) \
-+                    * DISK_SECTOR_SIZE)
++                    * BLOCK_SECTOR_SIZE)
 +
  /* On-disk inode.
-    Must be exactly DISK_SECTOR_SIZE bytes long. */
+    Must be exactly BLOCK_SECTOR_SIZE bytes long. */
  struct inode_disk
    {
--    disk_sector_t start;                /* First data sector. */
-+    disk_sector_t sectors[SECTOR_CNT];  /* Sectors. */
+-    block_sector_t start;               /* First data sector. */
++    block_sector_t sectors[SECTOR_CNT]; /* Sectors. */
 +    enum inode_type type;               /* FILE_INODE or DIR_INODE. */
      off_t length;                       /* File size in bytes. */
      unsigned magic;                     /* Magic number. */
@@ -1264,8 +1378,8 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    };
  
  /* Returns the number of sectors to allocate for an inode SIZE
-@@ -35,33 +50,30 @@ struct inode 
-     disk_sector_t sector;               /* Sector number of disk location. */
+@@ -35,74 +50,59 @@ struct inode 
+     block_sector_t sector;              /* Sector number of disk location. */
      int open_cnt;                       /* Number of openers. */
      bool removed;                       /* True if deleted, false otherwise. */
 +    struct lock lock;                   /* Protects the inode. */
@@ -1278,16 +1392,16 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +    int writer_cnt;                     /* Number of writers. */
    };
  
--/* Returns the disk sector that contains byte offset POS within
--   INODE.
+-/* Returns the block device sector that contains byte offset POS
+-   within INODE.
 -   Returns -1 if INODE does not contain data for a byte at offset
 -   POS. */
--static disk_sector_t
+-static block_sector_t
 -byte_to_sector (const struct inode *inode, off_t pos) 
 -{
 -  ASSERT (inode != NULL);
 -  if (pos < inode->data.length)
--    return inode->data.start + pos / DISK_SECTOR_SIZE;
+-    return inode->data.start + pos / BLOCK_SECTOR_SIZE;
 -  else
 -    return -1;
 -}
@@ -1309,27 +1423,32 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +  lock_init (&open_inodes_lock);
  }
  
- /* Initializes an inode with LENGTH bytes of data and
-@@ -70,38 +82,35 @@ inode_init (void) 
-    Returns true if successful.
-    Returns false if memory or disk allocation fails. */
- bool
--inode_create (disk_sector_t sector, off_t length)
-+inode_create (disk_sector_t sector, off_t length, enum inode_type type) 
+-/* Initializes an inode with LENGTH bytes of data and
+-   writes the new inode to sector SECTOR on the file system
+-   device.
+-   Returns true if successful.
+-   Returns false if memory or disk allocation fails. */
+-bool
+-inode_create (block_sector_t sector, off_t length)
++/* Initializes an inode of the given TYPE, writes the new inode
++   to sector SECTOR on the file system device, and returns the
++   inode thus created.  Returns a null pointer if unsuccessful,
++   in which case SECTOR is released in the free map. */  
++struct inode *
++inode_create (block_sector_t sector, enum inode_type type) 
  {
 -  struct inode_disk *disk_inode = NULL;
 -  bool success = false;
 +  struct cache_block *block;
 +  struct inode_disk *disk_inode;
-+  bool success;
-   ASSERT (length >= 0);
++  struct inode *inode;
  
+-  ASSERT (length >= 0);
 +  block = cache_lock (sector, EXCLUSIVE);
-+
    /* If this assertion fails, the inode structure is not exactly
       one sector in size, and you should fix that. */
-   ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);
+   ASSERT (sizeof *disk_inode == BLOCK_SECTOR_SIZE);
 +  disk_inode = cache_zero (block);
 +  disk_inode->type = type;
 +  disk_inode->length = 0;
@@ -1339,36 +1458,34 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  
 -  disk_inode = calloc (1, sizeof *disk_inode);
 -  if (disk_inode != NULL)
-+  if (length > 0) 
-     {
+-    {
 -      size_t sectors = bytes_to_sectors (length);
 -      disk_inode->length = length;
 -      disk_inode->magic = INODE_MAGIC;
--      if (free_map_allocate (sectors, &disk_inode->start))
+-      if (free_map_allocate (sectors, &disk_inode->start)) 
 -        {
--          disk_write (filesys_disk, sector, disk_inode);
+-          block_write (fs_device, sector, disk_inode);
 -          if (sectors > 0) 
 -            {
--              static char zeros[DISK_SECTOR_SIZE];
+-              static char zeros[BLOCK_SECTOR_SIZE];
 -              size_t i;
 -              
 -              for (i = 0; i < sectors; i++) 
--                disk_write (filesys_disk, disk_inode->start + i, zeros); 
+-                block_write (fs_device, disk_inode->start + i, zeros);
 -            }
 -          success = true; 
 -        } 
 -      free (disk_inode);
-+      struct inode *inode = inode_open (sector);
-+      success = inode != NULL && inode_write_at (inode, "", 1, length - 1);
-+      inode_close (inode);
-     }
-+  else
-+    success = true;
-+
-   return success;
+-    }
+-  return success;
++  inode = inode_open (sector);
++  if (inode == NULL)
++    free_map_release (sector);
++  return inode;
  }
  
-@@ -115,6 +124,7 @@ inode_open (disk_sector_t sector) 
+ /* Reads an inode from SECTOR
+@@ -115,29 +110,35 @@ inode_open (block_sector_t sector) 
    struct inode *inode;
  
    /* Check whether this inode is already open. */
@@ -1376,11 +1493,12 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
         e = list_next (e)) 
      {
-@@ -122,22 +132,27 @@ inode_open (disk_sector_t sector) 
+       inode = list_entry (e, struct inode, elem);
        if (inode->sector == sector) 
          {
-           inode_reopen (inode);
+-          inode_reopen (inode);
 -          return inode; 
++          inode->open_cnt++;
 +          goto done; 
          }
      }
@@ -1400,22 +1518,22 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +  lock_init (&inode->deny_write_lock);
 +  cond_init (&inode->no_writers_cond);
    inode->removed = false;
--  disk_read (filesys_disk, inode->sector, &inode->data);
+-  block_read (fs_device, inode->sector, &inode->data);
 +  
 + done:
 +  lock_release (&open_inodes_lock);
    return inode;
  }
  
-@@ -146,10 +161,25 @@ struct inode *
- inode_reopen (struct inode *inode) 
+@@ -146,9 +147,24 @@ struct inode *
+ inode_reopen (struct inode *inode)
  {
-   if (inode != NULL) 
+   if (inode != NULL)
 -    inode->open_cnt++;
 +    {
-+      inode_lock (inode);
++      lock_acquire (&open_inodes_lock);
 +      inode->open_cnt++;
-+      inode_unlock (inode); 
++      lock_release (&open_inodes_lock);
 +    }
    return inode;
  }
@@ -1431,10 +1549,9 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +  return type;
 +}
 +
- /* Closes INODE and writes it to disk.
-    If this was the last reference to INODE, frees its memory.
-    If INODE was also a removed inode, frees its blocks. */
-@@ -161,21 +191,60 @@ inode_close (struct inode *inode) 
+ /* Returns INODE's inode number. */
+ block_sector_t
+@@ -161,21 +183,60 @@ inode_close (struct inode *inode) 
      return;
  
    /* Release resources if this was the last opener. */
@@ -1465,12 +1582,12 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +   or 1 if SECTOR is indirect,
 +   or 0 if SECTOR is a data sector. */
 +static void
-+deallocate_recursive (disk_sector_t sector, int level) 
++deallocate_recursive (block_sector_t sector, int level) 
 +{
 +  if (level > 0) 
 +    {
 +      struct cache_block *block = cache_lock (sector, EXCLUSIVE);
-+      disk_sector_t *pointers = cache_read (block);
++      block_sector_t *pointers = cache_read (block);
 +      int i;
 +      for (i = 0; i < PTRS_PER_SECTOR; i++)
 +        if (pointers[i])
@@ -1500,7 +1617,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
  
  /* Marks INODE to be deleted when it is closed by the last caller who
-@@ -187,6 +256,156 @@ inode_remove (struct inode *inode) 
+@@ -187,6 +248,157 @@ inode_remove (struct inode *inode) 
    inode->removed = true;
  }
  
@@ -1553,14 +1670,14 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +get_data_block (struct inode *inode, off_t offset, bool allocate,
 +                struct cache_block **data_block) 
 +{
-+  disk_sector_t this_level_sector;
++  block_sector_t this_level_sector;
 +  size_t offsets[3];
 +  size_t offset_cnt;
 +  size_t level;
 +
 +  ASSERT (offset >= 0);
 +
-+  calculate_indices (offset / DISK_SECTOR_SIZE, offsets, &offset_cnt);
++  calculate_indices (offset / BLOCK_SECTOR_SIZE, offsets, &offset_cnt);
 +  level = 0;
 +  this_level_sector = inode->sector;
 +  for (;;) 
@@ -1586,7 +1703,8 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +                  || (level > 0 && offsets[level] + 1 < PTRS_PER_SECTOR)) 
 +                {
 +                  uint32_t next_sector = this_level_data[offsets[level] + 1];
-+                  if (next_sector && next_sector < disk_size (filesys_disk))
++                  if (next_sector
++                      && next_sector < block_size (fs_device))
 +                    cache_readahead (next_sector); 
 +                }
 +              cache_unlock (this_level_block);
@@ -1657,7 +1775,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  /* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
     Returns the number of bytes actually read, which may be less
     than SIZE if an error occurs or end of file is reached. */
-@@ -195,13 +414,12 @@ inode_read_at (struct inode *inode, void
+@@ -195,13 +406,12 @@ inode_read_at (struct inode *inode, void
  {
    uint8_t *buffer = buffer_;
    off_t bytes_read = 0;
@@ -1666,14 +1784,14 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    while (size > 0) 
      {
 -      /* Disk sector to read, starting byte offset within sector. */
--      disk_sector_t sector_idx = byte_to_sector (inode, offset);
+-      block_sector_t sector_idx = byte_to_sector (inode, offset);
 +      /* Sector to read, starting byte offset within sector, sector data. */
-       int sector_ofs = offset % DISK_SECTOR_SIZE;
+       int sector_ofs = offset % BLOCK_SECTOR_SIZE;
 +      struct cache_block *block;
  
        /* Bytes left in inode, bytes left in sector, lesser of the two. */
        off_t inode_left = inode_length (inode) - offset;
-@@ -210,26 +428,16 @@ inode_read_at (struct inode *inode, void
+@@ -210,26 +420,16 @@ inode_read_at (struct inode *inode, void
  
        /* Number of bytes to actually copy out of this sector. */
        int chunk_size = size < min_left ? size : min_left;
@@ -1681,10 +1799,10 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +      if (chunk_size <= 0 || !get_data_block (inode, offset, false, &block))
          break;
  
--      if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE) 
+-      if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
 -        {
 -          /* Read full sector directly into caller's buffer. */
--          disk_read (filesys_disk, sector_idx, buffer + bytes_read); 
+-          block_read (fs_device, sector_idx, buffer + bytes_read);
 -        }
 +      if (block == NULL) 
 +        memset (buffer + bytes_read, 0, chunk_size);
@@ -1694,11 +1812,11 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 -             into caller's buffer. */
 -          if (bounce == NULL) 
 -            {
--              bounce = malloc (DISK_SECTOR_SIZE);
+-              bounce = malloc (BLOCK_SECTOR_SIZE);
 -              if (bounce == NULL)
 -                break;
 -            }
--          disk_read (filesys_disk, sector_idx, bounce);
+-          block_read (fs_device, sector_idx, bounce);
 -          memcpy (buffer + bytes_read, bounce + sector_ofs, chunk_size);
 +          const uint8_t *sector_data = cache_read (block);
 +          memcpy (buffer + bytes_read, sector_data + sector_ofs, chunk_size);
@@ -1706,7 +1824,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
          }
        
        /* Advance. */
-@@ -237,75 +445,84 @@ inode_read_at (struct inode *inode, void
+@@ -237,75 +437,82 @@ inode_read_at (struct inode *inode, void
        offset += chunk_size;
        bytes_read += chunk_size;
      }
@@ -1734,11 +1852,10 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +
  /* Writes SIZE bytes from BUFFER into INODE, starting at OFFSET.
     Returns the number of bytes actually written, which may be
-    less than SIZE if end of file is reached or an error occurs.
+-   less than SIZE if end of file is reached or an error occurs.
 -   (Normally a write at end of file would extend the inode, but
 -   growth is not yet implemented.) */
-+   (Normally a write at end of file would extend the file, but
-+   file growth is not yet implemented.) */
++   less than SIZE if an error occurs. */
  off_t
  inode_write_at (struct inode *inode, const void *buffer_, off_t size,
                  off_t offset) 
@@ -1762,9 +1879,9 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    while (size > 0) 
      {
 -      /* Sector to write, starting byte offset within sector. */
--      disk_sector_t sector_idx = byte_to_sector (inode, offset);
+-      block_sector_t sector_idx = byte_to_sector (inode, offset);
 +      /* Sector to write, starting byte offset within sector, sector data. */
-       int sector_ofs = offset % DISK_SECTOR_SIZE;
+       int sector_ofs = offset % BLOCK_SECTOR_SIZE;
 +      struct cache_block *block;
 +      uint8_t *sector_data;
  
@@ -1772,7 +1889,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 -      off_t inode_left = inode_length (inode) - offset;
 +      /* Bytes to max inode size, bytes left in sector, lesser of the two. */
 +      off_t inode_left = INODE_SPAN - offset;
-       int sector_left = DISK_SECTOR_SIZE - sector_ofs;
+       int sector_left = BLOCK_SECTOR_SIZE - sector_ofs;
        int min_left = inode_left < sector_left ? inode_left : sector_left;
  
        /* Number of bytes to actually write into this sector. */
@@ -1780,17 +1897,17 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 -      if (chunk_size <= 0)
 -        break;
  
--      if (sector_ofs == 0 && chunk_size == DISK_SECTOR_SIZE) 
+-      if (sector_ofs == 0 && chunk_size == BLOCK_SECTOR_SIZE)
 -        {
 -          /* Write full sector directly to disk. */
--          disk_write (filesys_disk, sector_idx, buffer + bytes_written); 
+-          block_write (fs_device, sector_idx, buffer + bytes_written);
 -        }
 -      else 
 -        {
 -          /* We need a bounce buffer. */
 -          if (bounce == NULL) 
 -            {
--              bounce = malloc (DISK_SECTOR_SIZE);
+-              bounce = malloc (BLOCK_SECTOR_SIZE);
 -              if (bounce == NULL)
 -                break;
 -            }
@@ -1801,11 +1918,11 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 -             we're writing, then we need to read in the sector
 -             first.  Otherwise we start with a sector of all zeros. */
 -          if (sector_ofs > 0 || chunk_size < sector_left) 
--            disk_read (filesys_disk, sector_idx, bounce);
+-            block_read (fs_device, sector_idx, bounce);
 -          else
--            memset (bounce, 0, DISK_SECTOR_SIZE);
+-            memset (bounce, 0, BLOCK_SECTOR_SIZE);
 -          memcpy (bounce + sector_ofs, buffer + bytes_written, chunk_size);
--          disk_write (filesys_disk, sector_idx, bounce); 
+-          block_write (fs_device, sector_idx, bounce);
 -        }
 +      sector_data = cache_read (block);
 +      memcpy (sector_data + sector_ofs, buffer + bytes_written, chunk_size);
@@ -1828,7 +1945,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  
    return bytes_written;
  }
-@@ -315,8 +532,12 @@ inode_write_at (struct inode *inode, con
+@@ -315,8 +522,12 @@ inode_write_at (struct inode *inode, con
  void
  inode_deny_write (struct inode *inode) 
  {
@@ -1842,7 +1959,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
  
  /* Re-enables writes to INODE.
-@@ -325,14 +546,47 @@ inode_deny_write (struct inode *inode) 
+@@ -325,14 +536,47 @@ inode_deny_write (struct inode *inode) 
  void
  inode_allow_write (struct inode *inode) 
  {
@@ -1893,29 +2010,30 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
 Index: src/filesys/inode.h
 diff -u src/filesys/inode.h~ src/filesys/inode.h
---- src/filesys/inode.h        2005-06-18 20:20:48.000000000 -0700
-+++ src/filesys/inode.h        2006-05-18 21:46:41.000000000 -0700
-@@ -7,10 +7,18 @@
+--- src/filesys/inode.h~
++++ src/filesys/inode.h
+@@ -7,11 +7,19 @@
  
  struct bitmap;
  
 +/* Type of an inode. */
 +enum inode_type 
 +  {
-+    FILE_INODE,       /* Ordinary file. */
-+    DIR_INODE         /* Directory. */
++    FILE_INODE,         /* Ordinary file. */
++    DIR_INODE           /* Directory. */
 +  };
 +
  void inode_init (void);
--bool inode_create (disk_sector_t, off_t);
-+bool inode_create (disk_sector_t, off_t, enum inode_type);
- struct inode *inode_open (disk_sector_t);
+-bool inode_create (block_sector_t, off_t);
++struct inode *inode_create (block_sector_t, enum inode_type);
+ struct inode *inode_open (block_sector_t);
  struct inode *inode_reopen (struct inode *);
 +enum inode_type inode_get_type (const struct inode *);
+ block_sector_t inode_get_inumber (const struct inode *);
  void inode_close (struct inode *);
  void inode_remove (struct inode *);
  off_t inode_read_at (struct inode *, void *, off_t size, off_t offset);
-@@ -18,5 +26,8 @@ off_t inode_write_at (struct inode *, co
+@@ -18,5 +27,8 @@ off_t inode_write_at (struct inode *, co
  void inode_deny_write (struct inode *);
  void inode_allow_write (struct inode *);
  off_t inode_length (const struct inode *);
@@ -1926,8 +2044,8 @@ diff -u src/filesys/inode.h~ src/filesys/inode.h
  #endif /* filesys/inode.h */
 Index: src/threads/init.c
 diff -u src/threads/init.c~ src/threads/init.c
---- src/threads/init.c 2006-05-18 17:35:54.000000000 -0700
-+++ src/threads/init.c 2006-05-18 21:26:51.000000000 -0700
+--- src/threads/init.c~
++++ src/threads/init.c
 @@ -33,6 +33,8 @@
  #include "filesys/filesys.h"
  #include "filesys/fsutil.h"
@@ -1936,7 +2054,7 @@ diff -u src/threads/init.c~ src/threads/init.c
 +#include "vm/swap.h"
  
  /* Amount of physical memory, in 4 kB pages. */
- size_t ram_pages;
+ size_t init_ram_pages;
 @@ -124,6 +126,9 @@ main (void)
    filesys_init (format_filesys);
  #endif
@@ -1949,8 +2067,8 @@ diff -u src/threads/init.c~ src/threads/init.c
    /* Run actions specified on kernel command line. */
 Index: src/threads/interrupt.c
 diff -u src/threads/interrupt.c~ src/threads/interrupt.c
---- src/threads/interrupt.c    2006-04-22 22:25:21.000000000 -0700
-+++ src/threads/interrupt.c    2006-05-18 21:26:51.000000000 -0700
+--- src/threads/interrupt.c~
++++ src/threads/interrupt.c
 @@ -354,6 +354,8 @@ intr_handler (struct intr_frame *frame) 
        in_external_intr = true;
        yield_on_return = false;
@@ -1962,8 +2080,8 @@ diff -u src/threads/interrupt.c~ src/threads/interrupt.c
       If there is no handler, invoke the unexpected interrupt
 Index: src/threads/thread.c
 diff -u src/threads/thread.c~ src/threads/thread.c
---- src/threads/thread.c       2006-04-22 22:25:22.000000000 -0700
-+++ src/threads/thread.c       2006-05-18 21:26:51.000000000 -0700
+--- src/threads/thread.c~
++++ src/threads/thread.c
 @@ -13,6 +13,7 @@
  #include "threads/vaddr.h"
  #ifdef USERPROG
@@ -2004,35 +2122,27 @@ diff -u src/threads/thread.c~ src/threads/thread.c
  
    /* Stack frame for kernel_thread(). */
    kf = alloc_frame (t, sizeof *kf);
-@@ -253,16 +254,19 @@ thread_tid (void) 
+@@ -288,10 +289,11 @@ thread_tid (void) 
  void
  thread_exit (void) 
  {
-+  struct thread *t = thread_current ();
-+
    ASSERT (!intr_context ());
  
 +  syscall_exit ();
  #ifdef USERPROG
    process_exit ();
  #endif
--
-+  
-   /* Just set our status to dying and schedule another process.
-      We will be destroyed during the call to schedule_tail(). */
-   intr_disable ();
--  thread_current ()->status = THREAD_DYING;
-+  t->status = THREAD_DYING;
-   schedule ();
-   NOT_REACHED ();
- }
-@@ -406,17 +410,29 @@ is_thread (struct thread *t)
+   /* Remove thread from all threads list, set our status to dying,
+@@ -406,23 +410,35 @@ is_thread (struct thread *t)
  /* Does basic initialization of T as a blocked thread named
     NAME. */
  static void
 -init_thread (struct thread *t, const char *name, int priority)
 +init_thread (struct thread *t, const char *name, int priority, tid_t tid)
  {
+   enum intr_level old_level;
    ASSERT (t != NULL);
    ASSERT (PRI_MIN <= priority && priority <= PRI_MAX);
    ASSERT (name != NULL);
@@ -2055,12 +2165,16 @@ diff -u src/threads/thread.c~ src/threads/thread.c
 +  t->next_handle = 2;
 +  t->wd = NULL;
    t->magic = THREAD_MAGIC;
+   old_level = intr_disable ();
+   list_push_back (&all_list, &t->allelem);
+   intr_set_level (old_level);
  }
  
 Index: src/threads/thread.h
 diff -u src/threads/thread.h~ src/threads/thread.h
---- src/threads/thread.h       2006-04-22 22:25:22.000000000 -0700
-+++ src/threads/thread.h       2006-05-18 21:26:51.000000000 -0700
+--- src/threads/thread.h~
++++ src/threads/thread.h
 @@ -2,8 +2,10 @@
  #define THREADS_THREAD_H
  
@@ -2122,13 +2236,13 @@ diff -u src/threads/thread.h~ src/threads/thread.h
 +    struct semaphore dead;              /* 1=child alive, 0=child dead. */
 +  };
 +
- void thread_init (void);
- void thread_start (void);
+ /* If false (default), use round-robin scheduler.
+    If true, use multi-level feedback queue scheduler.
+    Controlled by kernel command-line options "-o mlfqs".
 Index: src/userprog/exception.c
 diff -u src/userprog/exception.c~ src/userprog/exception.c
---- src/userprog/exception.c   2006-01-29 13:32:56.000000000 -0800
-+++ src/userprog/exception.c   2006-05-18 21:26:51.000000000 -0700
+--- src/userprog/exception.c~
++++ src/userprog/exception.c
 @@ -4,6 +4,7 @@
  #include "userprog/gdt.h"
  #include "threads/interrupt.h"
@@ -2157,10 +2271,10 @@ diff -u src/userprog/exception.c~ src/userprog/exception.c
            not_present ? "not present" : "rights violation",
 Index: src/userprog/pagedir.c
 diff -u src/userprog/pagedir.c~ src/userprog/pagedir.c
---- src/userprog/pagedir.c     2006-04-22 22:25:23.000000000 -0700
-+++ src/userprog/pagedir.c     2006-05-18 21:26:51.000000000 -0700
+--- src/userprog/pagedir.c~
++++ src/userprog/pagedir.c
 @@ -35,15 +35,7 @@ pagedir_destroy (uint32_t *pd) 
-   ASSERT (pd != base_page_dir);
+   ASSERT (pd != init_page_dir);
    for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
      if (*pde & PTE_P) 
 -      {
@@ -2178,8 +2292,8 @@ diff -u src/userprog/pagedir.c~ src/userprog/pagedir.c
  
 Index: src/userprog/process.c
 diff -u src/userprog/process.c~ src/userprog/process.c
---- src/userprog/process.c     2006-05-18 17:35:55.000000000 -0700
-+++ src/userprog/process.c     2006-05-18 22:12:19.000000000 -0700
+--- src/userprog/process.c~
++++ src/userprog/process.c
 @@ -14,12 +14,27 @@
  #include "threads/flags.h"
  #include "threads/init.h"
@@ -2191,12 +2305,12 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +#include "vm/page.h"
 +#include "vm/frame.h"
  
- static thread_func execute_thread NO_RETURN;
+ static thread_func start_process NO_RETURN;
 -static bool load (const char *cmdline, void (**eip) (void), void **esp);
 +static bool load (const char *cmd_line, void (**eip) (void), void **esp);
 +
 +/* Data structure shared between process_execute() in the
-+   invoking thread and execute_thread() in the newly invoked
++   invoking thread and start_process() in the newly invoked
 +   thread. */
 +struct exec_info 
 +  {
@@ -2208,7 +2322,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +  };
  
  /* Starts a new thread running a user program loaded from
-    FILE_NAME.  The new thread may be scheduled (and may even exit)
+    FILENAME.  The new thread may be scheduled (and may even exit)
 @@ -28,41 +43,78 @@ static bool load (const char *cmdline, v
  tid_t
  process_execute (const char *file_name) 
@@ -2233,12 +2347,12 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +  sema_init (&exec.load_done, 0);
  
    /* Create a new thread to execute FILE_NAME. */
--  tid = thread_create (file_name, PRI_DEFAULT, execute_thread, fn_copy);
+-  tid = thread_create (file_name, PRI_DEFAULT, start_process, fn_copy);
 -  if (tid == TID_ERROR)
 -    palloc_free_page (fn_copy); 
 +  strlcpy (thread_name, file_name, sizeof thread_name);
 +  strtok_r (thread_name, " ", &save_ptr);
-+  tid = thread_create (thread_name, PRI_DEFAULT, execute_thread, &exec);
++  tid = thread_create (thread_name, PRI_DEFAULT, start_process, &exec);
 +  if (tid != TID_ERROR)
 +    {
 +      sema_down (&exec.load_done);
@@ -2259,8 +2373,8 @@ diff -u src/userprog/process.c~ src/userprog/process.c
  /* A thread function that loads a user process and starts it
     running. */
  static void
--execute_thread (void *file_name_)
-+execute_thread (void *exec_)
+-start_process (void *file_name_)
++start_process (void *exec_)
  {
 -  char *file_name = file_name_;
 +  struct exec_info *exec = exec_;
@@ -2302,7 +2416,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    if (!success) 
      thread_exit ();
  
-@@ -76,18 +128,47 @@ execute_thread (void *file_name_)
+@@ -76,18 +128,47 @@ start_process (void *file_name_)
    NOT_REACHED ();
  }
  
@@ -2417,7 +2531,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    int i;
  
    /* Allocate and activate page directory. */
-@@ -220,13 +330,28 @@ load (const char *file_name, void (**eip)
+@@ -220,13 +330,28 @@ load (const char *file_name, void (**eip
      goto done;
    process_activate ();
  
@@ -2447,7 +2561,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
  
    /* Read and verify executable header. */
    if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
-@@ -301,7 +426,7 @@ load (const char *file_name, void (**eip)
+@@ -301,7 +426,7 @@ load (const char *file_name, void (**eip
      }
  
    /* Set up stack. */
@@ -2456,7 +2570,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
      goto done;
  
    /* Start address. */
-@@ -311,14 +436,11 @@ load (const char *file_name, void (**eip)
+@@ -311,14 +436,11 @@ load (const char *file_name, void (**eip
  
   done:
    /* We arrive here whether the load is successful or not. */
@@ -2653,16 +2767,17 @@ diff -u src/userprog/process.c~ src/userprog/process.c
  }
 Index: src/userprog/syscall.c
 diff -u src/userprog/syscall.c~ src/userprog/syscall.c
---- src/userprog/syscall.c     2005-06-18 20:21:21.000000000 -0700
-+++ src/userprog/syscall.c     2006-05-18 21:26:51.000000000 -0700
-@@ -1,20 +1,671 @@
+--- src/userprog/syscall.c~
++++ src/userprog/syscall.c
+@@ -1,20 +1,685 @@
  #include "userprog/syscall.h"
  #include <stdio.h>
 +#include <string.h>
  #include <syscall-nr.h>
 +#include "userprog/process.h"
 +#include "userprog/pagedir.h"
-+#include "devices/kbd.h"
++#include "devices/input.h"
++#include "devices/shutdown.h"
 +#include "filesys/directory.h"
 +#include "filesys/filesys.h"
 +#include "filesys/file.h"
@@ -2695,6 +2810,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +static int sys_mkdir (const char *udir);
 +static int sys_readdir (int handle, char *name);
 +static int sys_isdir (int handle);
++static int sys_inumber (int handle);
 + 
  static void syscall_handler (struct intr_frame *);
 -
@@ -2741,12 +2857,13 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +      {1, (syscall_function *) sys_mkdir},
 +      {2, (syscall_function *) sys_readdir},
 +      {1, (syscall_function *) sys_isdir},
++      {1, (syscall_function *) sys_inumber},
 +    };
++
 +  const struct syscall *sc;
 +  unsigned call_nr;
 +  int args[3];
-+
 +  /* Get the system call. */
 +  copy_in (&call_nr, f->esp, sizeof call_nr);
 +  if (call_nr >= sizeof syscall_table / sizeof *syscall_table)
@@ -2769,7 +2886,8 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
  static void
 -syscall_handler (struct intr_frame *f UNUSED) 
 +copy_in (void *dst_, const void *usrc_, size_t size) 
-+{
+ {
+-  printf ("system call!\n");
 +  uint8_t *dst = dst_;
 +  const uint8_t *usrc = usrc_;
 +
@@ -2858,14 +2976,14 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  page_unlock (upage);
 + lock_error:
 +  palloc_free_page (ks);
-+  thread_exit ();
-+}
+   thread_exit ();
+ }
 + 
 +/* Halt system call. */
 +static int
 +sys_halt (void)
 +{
-+  power_off ();
++  shutdown_power_off ();
 +}
 + 
 +/* Exit system call. */
@@ -3062,7 +3180,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +          size_t i;
 +          
 +          for (i = 0; i < read_amt; i++) 
-+            udst[i] = kbd_getc ();
++            udst[i] = input_getc ();
 +          bytes_read = read_amt;
 +        }
 +
@@ -3084,8 +3202,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +/* Write system call. */
 +static int
 +sys_write (int handle, void *usrc_, unsigned size) 
- {
--  printf ("system call!\n");
++{
 +  uint8_t *usrc = usrc_;
 +  struct file_descriptor *fd = NULL;
 +  int bytes_written = 0;
@@ -3193,8 +3310,8 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +        return m;
 +    }
 + 
-   thread_exit ();
- }
++  thread_exit ();
++}
 +
 +/* Remove mapping M from the virtual address space,
 +   writing back any pages that have changed. */
@@ -3304,6 +3421,17 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  struct file_descriptor *fd = lookup_fd (handle);
 +  return fd->dir != NULL;
 +}
++
++/* Inumber system call. */
++static int
++sys_inumber (int handle)
++{
++  struct file_descriptor *fd = lookup_fd (handle);
++  struct inode *inode = (fd->file 
++                         ? file_get_inode (fd->file)
++                         : dir_get_inode (fd->dir));
++  return inode_get_inumber (inode);
++}
 +\f 
 +/* On thread exit, close all open files and unmap all mappings. */
 +void
@@ -3333,8 +3461,8 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +}
 Index: src/userprog/syscall.h
 diff -u src/userprog/syscall.h~ src/userprog/syscall.h
---- src/userprog/syscall.h     2004-09-05 22:38:45.000000000 -0700
-+++ src/userprog/syscall.h     2006-05-18 21:26:51.000000000 -0700
+--- src/userprog/syscall.h~
++++ src/userprog/syscall.h
 @@ -2,5 +2,6 @@
  #define USERPROG_SYSCALL_H
  
@@ -3344,8 +3472,8 @@ diff -u src/userprog/syscall.h~ src/userprog/syscall.h
  #endif /* userprog/syscall.h */
 Index: src/vm/frame.c
 diff -u src/vm/frame.c~ src/vm/frame.c
---- src/vm/frame.c     1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.c     2006-05-18 21:26:51.000000000 -0700
+--- src/vm/frame.c~
++++ src/vm/frame.c
 @@ -0,0 +1,161 @@
 +#include "vm/frame.h"
 +#include <stdio.h>
@@ -3371,7 +3499,7 @@ diff -u src/vm/frame.c~ src/vm/frame.c
 +
 +  lock_init (&scan_lock);
 +  
-+  frames = malloc (sizeof *frames * ram_pages);
++  frames = malloc (sizeof *frames * init_ram_pages);
 +  if (frames == NULL)
 +    PANIC ("out of memory allocating page frames");
 +
@@ -3510,8 +3638,8 @@ diff -u src/vm/frame.c~ src/vm/frame.c
 +}
 Index: src/vm/frame.h
 diff -u src/vm/frame.h~ src/vm/frame.h
---- src/vm/frame.h     1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.h     2006-05-18 21:26:51.000000000 -0700
+--- src/vm/frame.h~
++++ src/vm/frame.h
 @@ -0,0 +1,23 @@
 +#ifndef VM_FRAME_H
 +#define VM_FRAME_H
@@ -3538,8 +3666,8 @@ diff -u src/vm/frame.h~ src/vm/frame.h
 +#endif /* vm/frame.h */
 Index: src/vm/page.c
 diff -u src/vm/page.c~ src/vm/page.c
---- src/vm/page.c      1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.c      2006-05-18 21:26:51.000000000 -0700
+--- src/vm/page.c~
++++ src/vm/page.c
 @@ -0,0 +1,294 @@
 +#include "vm/page.h"
 +#include <stdio.h>
@@ -3613,7 +3741,7 @@ diff -u src/vm/page.c~ src/vm/page.c
 +    return false;
 +
 +  /* Copy data into the frame. */
-+  if (p->sector != (disk_sector_t) -1) 
++  if (p->sector != (block_sector_t) -1) 
 +    {
 +      /* Get data from swap. */
 +      swap_in (p); 
@@ -3751,7 +3879,7 @@ diff -u src/vm/page.c~ src/vm/page.c
 +
 +      p->frame = NULL;
 +
-+      p->sector = (disk_sector_t) -1;
++      p->sector = (block_sector_t) -1;
 +
 +      p->file = NULL;
 +      p->file_offset = 0;
@@ -3837,14 +3965,14 @@ diff -u src/vm/page.c~ src/vm/page.c
 +}
 Index: src/vm/page.h
 diff -u src/vm/page.h~ src/vm/page.h
---- src/vm/page.h      1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.h      2006-05-18 21:26:51.000000000 -0700
+--- src/vm/page.h~
++++ src/vm/page.h
 @@ -0,0 +1,50 @@
 +#ifndef VM_PAGE_H
 +#define VM_PAGE_H
 +
 +#include <hash.h>
-+#include "devices/disk.h"
++#include "devices/block.h"
 +#include "filesys/off_t.h"
 +#include "threads/synch.h"
 +
@@ -3864,7 +3992,7 @@ diff -u src/vm/page.h~ src/vm/page.h
 +    struct frame *frame;        /* Page frame. */
 +
 +    /* Swap information, protected by frame->frame_lock. */
-+    disk_sector_t sector;       /* Starting sector of swap area, or -1. */
++    block_sector_t sector;       /* Starting sector of swap area, or -1. */
 +    
 +    /* Memory-mapped file information, protected by frame->frame_lock. */
 +    bool private;               /* False to write back to file,
@@ -3892,21 +4020,21 @@ diff -u src/vm/page.h~ src/vm/page.h
 +#endif /* vm/page.h */
 Index: src/vm/swap.c
 diff -u src/vm/swap.c~ src/vm/swap.c
---- src/vm/swap.c      1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.c      2006-05-18 21:26:51.000000000 -0700
-@@ -0,0 +1,85 @@
+--- src/vm/swap.c~
++++ src/vm/swap.c
+@@ -0,0 +1,86 @@
 +#include "vm/swap.h"
 +#include <bitmap.h>
 +#include <debug.h>
 +#include <stdio.h>
 +#include "vm/frame.h"
 +#include "vm/page.h"
-+#include "devices/disk.h"
++#include "devices/block.h"
 +#include "threads/synch.h"
 +#include "threads/vaddr.h"
 +
-+/* The swap disk. */
-+static struct disk *swap_disk;
++/* The swap partition. */
++static struct block *swap_device;
 +
 +/* Used swap pages. */
 +static struct bitmap *swap_bitmap;
@@ -3915,20 +4043,21 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +static struct lock swap_lock;
 +
 +/* Number of sectors per page. */
-+#define PAGE_SECTORS (PGSIZE / DISK_SECTOR_SIZE)
++#define PAGE_SECTORS (PGSIZE / BLOCK_SECTOR_SIZE)
 +
 +/* Sets up swap. */
 +void
 +swap_init (void) 
 +{
-+  swap_disk = disk_get (1, 1);
-+  if (swap_disk == NULL) 
++  swap_device = block_get_role (BLOCK_SWAP);
++  if (swap_device == NULL) 
 +    {
-+      printf ("no swap disk--swap disabled\n");
++      printf ("no swap device--swap disabled\n");
 +      swap_bitmap = bitmap_create (0);
 +    }
 +  else
-+    swap_bitmap = bitmap_create (disk_size (swap_disk) / PAGE_SECTORS);
++    swap_bitmap = bitmap_create (block_size (swap_device)
++                                 / PAGE_SECTORS);
 +  if (swap_bitmap == NULL)
 +    PANIC ("couldn't create swap bitmap");
 +  lock_init (&swap_lock);
@@ -3943,13 +4072,13 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +  
 +  ASSERT (p->frame != NULL);
 +  ASSERT (lock_held_by_current_thread (&p->frame->lock));
-+  ASSERT (p->sector != (disk_sector_t) -1);
++  ASSERT (p->sector != (block_sector_t) -1);
 +
 +  for (i = 0; i < PAGE_SECTORS; i++)
-+    disk_read (swap_disk, p->sector + i,
-+               p->frame->base + i * DISK_SECTOR_SIZE);
++    block_read (swap_device, p->sector + i,
++                p->frame->base + i * BLOCK_SECTOR_SIZE);
 +  bitmap_reset (swap_bitmap, p->sector / PAGE_SECTORS);
-+  p->sector = (disk_sector_t) -1;
++  p->sector = (block_sector_t) -1;
 +}
 +
 +/* Swaps out page P, which must have a locked frame. */
@@ -3970,8 +4099,8 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +
 +  p->sector = slot * PAGE_SECTORS;
 +  for (i = 0; i < PAGE_SECTORS; i++)
-+    disk_write (swap_disk, p->sector + i,
-+                p->frame->base + i * DISK_SECTOR_SIZE);
++    block_write (swap_device, p->sector + i,
++                 p->frame->base + i * BLOCK_SECTOR_SIZE);
 +  
 +  p->private = false;
 +  p->file = NULL;
@@ -3982,8 +4111,8 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +}
 Index: src/vm/swap.h
 diff -u src/vm/swap.h~ src/vm/swap.h
---- src/vm/swap.h      1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.h      2006-05-18 21:26:51.000000000 -0700
+--- src/vm/swap.h~
++++ src/vm/swap.h
 @@ -0,0 +1,11 @@
 +#ifndef VM_SWAP_H
 +#define VM_SWAP_H 1