-+ list_init (&open_dirs);
-+ lock_init (&open_dirs_lock);
- }
-
--/* Opens the directory in the given INODE, of which it takes
-+/* Opens the directory for the given INODE, of which it takes
- ownership, and sets *DIRP to the new directory or a null
- pointer on failure. Return true if successful, false on
- failure. */
-@@ -36,19 +47,46 @@ bool
- dir_open (struct inode *inode, struct dir **dirp)
- {
- struct dir *dir = NULL;
-+ struct list_elem *e;
-
- ASSERT (dirp != NULL);
-
-- if (inode != NULL)
-+ lock_acquire (&open_dirs_lock);
-+
-+ if (inode == NULL)
-+ goto done;
-+
-+ /* Inode must refer to directory. */
-+ if (inode_get_type (inode) != DIR_INODE)
-+ goto done;
-+
-+ /* Check whether this directory is already open. */
-+ for (e = list_begin (&open_dirs); e != list_end (&open_dirs);
-+ e = list_next (e))
- {
-- dir = malloc (sizeof *dir);
-- if (dir != NULL)
-- dir->inode = inode;
-+ dir = list_entry (e, struct dir, list_elem);
-+ if (dir->inode == inode)
-+ {
-+ dir->open_cnt++;
-+ goto done;
-+ }
-+ }
-+
-+ /* Create new directory. */
-+ dir = calloc (1, sizeof *dir);
-+ if (dir != NULL)
-+ {
-+ list_push_front (&open_dirs, &dir->list_elem);
-+ lock_init (&dir->dir_lock);
-+ dir->open_cnt = 1;
-+ dir->inode = inode;
-+ inode_reopen (dir->inode);
- }
-
-+ done:
- *dirp = dir;
-- if (dir == NULL)
-- inode_close (inode);
-+ inode_close (inode);
-+ lock_release (&open_dirs_lock);
- return dir != NULL;
- }
-
-@@ -61,22 +99,34 @@ dir_open_root (struct dir **dirp)
- return dir_open (inode_open (ROOT_DIR_SECTOR), dirp);
- }
-
-+/* Re-opens DIR and returns true. */
-+bool
-+dir_reopen (struct dir *dir)
-+{
-+ dir->open_cnt++;
-+ return true;
-+}
-+
- /* Destroys DIR and frees associated resources. */
- void
- dir_close (struct dir *dir)