Browse Source

Reimplement directory caching (#78)

Replace the directory cache implementation.

* Fix unix domain socket lookup.

* Fix a bug in the getdents EINVAL case

* remove profiling code in dcache.c; cleaning up some style issues

* adding a note to the recursive path_lookupat() code

* remove a few compilation warnings

* Apply Chia-Che's suggested fixes; add more now-passing cases to LTP nice list.

* Ref counting bug for /proc/self/fd/.  Document and implement expected behavior in relevant helper function.
Don Porter 6 years ago
parent
commit
62f07c7181

+ 165 - 40
LibOS/shim/include/shim_fs.h

@@ -112,11 +112,22 @@ struct shim_fs_ops {
 #define DENTRY_ISLINK       0x0080  /* this dentry is a link */
 #define DENTRY_ISDIRECTORY  0x0100  /* this dentry is a directory */
 #define DENTRY_LOCKED       0x0200  /* locked by mountpoints at children */
-#define DENTRY_REACHABLE    0x0400  /* permission checked to be reachable */
-#define DENTRY_UNREACHABLE  0x0800  /* permission checked to be unreachable */
+/* These flags are not used */
+//#define DENTRY_REACHABLE    0x0400  /* permission checked to be reachable */
+//#define DENTRY_UNREACHABLE  0x0800  /* permission checked to be unreachable */
 #define DENTRY_LISTED       0x1000  /* children in directory listed */
 #define DENTRY_INO_UPDATED  0x2000  /* ino updated */
-#define DENTRY_ANCESTER     0x4000
+#define DENTRY_ANCESTOR     0x4000 /* Auto-generated dentry to connect a mount
+                                    * point in the manifest to the root, when
+                                    * one or more intermediate directories do
+                                    * not exist on the underlying FS. The
+                                    * semantics of subsequent changes to such
+                                    * directories (or attempts to really
+                                    * create them) are not currently
+                                    * well-defined. */
+
+// Catch memory corruption issues by checking for invalid state values
+#define DENTRY_INVALID_FLAGS ~0x7FFF
 
 #define DCACHE_HASH_SIZE    1024
 #define DCACHE_HASH(hash) ((hash) & (DCACHE_HASH_SIZE - 1))
@@ -132,6 +143,11 @@ struct shim_dentry {
     struct shim_qstr name;          /* caching the file's name. */
 
 
+    /* DEP 6/16/17: For now, let's try not hashing; I suspect it is 
+     * overkill for most purposes.  I'll leave the field here for now,
+     * but propose we move to a per-directory table to accelerate lookups,
+     * rather than a global table, since this just supports one process.
+     */
     LIST_TYPE(shim_dentry) hlist;    /* to resolve collisions in
                                        the hash table */
     LIST_TYPE(shim_dentry) list;     /* put dentry to different list
@@ -159,8 +175,16 @@ struct shim_d_ops {
     int (*open) (struct shim_handle * hdl, struct shim_dentry * dent,
                  int flags);
 
-    /* look up dentry and allocate internal data */
+    /* look up dentry and allocate internal data.
+     * 
+     * On a successful lookup  (non-error, can be negative),
+     * this function should call get_new_dentry(), populating additional fields,
+     * and storing the new dentry in dent.
+     * 
+     * Maybe drop force?
+     */
     int (*lookup) (struct shim_dentry * dent, bool force);
+    
     /* this is to check file type and access, returning the stat.st_mode */
     int (*mode) (struct shim_dentry * dent, mode_t * mode, bool force);
 
@@ -231,9 +255,15 @@ extern struct shim_dentry * dentry_root;
 
 #define LOOKUP_FOLLOW            001
 #define LOOKUP_DIRECTORY         002
-#define LOOKUP_CONTINUE          004
-#define LOOKUP_PARENT            010
-
+#define LOOKUP_CONTINUE          004 // No longer needed
+#define LOOKUP_PARENT            010 // Not sure we need this
+
+#define F_OK          0
+// XXX: Duplicate definition; should probably weed out includes of host system
+//include of unistd.h in future work
+//#define R_OK        001
+//#define W_OK        002
+//#define X_OK        004
 #define MAY_EXEC    001
 #define MAY_WRITE   002
 #define MAY_READ    004
@@ -246,9 +276,9 @@ extern struct shim_dentry * dentry_root;
 #define ACC_MODE(x) ((((x) == O_RDONLY || (x) == O_RDWR) ? MAY_READ : 0) | \
                      (((x) == O_WRONLY || (x) == O_RDWR) ? MAY_WRITE : 0))
 
-#define LOOKUP_OPEN             0100
-#define LOOKUP_CREATE           0200
-#define LOOKUP_ACCESS           0400
+#define LOOKUP_OPEN             0100 // Appears to be ignored
+#define LOOKUP_CREATE           0200 
+#define LOOKUP_ACCESS           0400 // Appears to be ignored
 #define LOOKUP_SYNC     (LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_ACCESS)
 
 enum lookup_type {
@@ -268,15 +298,9 @@ struct lookup {
     enum lookup_type last_type;
 };
 
-long get_dcache_stats (const char * name);
-
-void path_acquire (struct lookup * look);
-void path_release (struct lookup * look);
 
 /* initialization for fs and mounts */
-int init_config (const char ** envp);
 int init_fs (void);
-int reinit_fs (void);
 int init_mount_root (void);
 int init_mount (void);
 
@@ -285,9 +309,9 @@ const char * get_file_name (const char * path, size_t len);
 
 /* file system operations */
 int mount_fs (const char * mount_type, const char * mount_uri,
-              const char * mount_point);
+              const char * mount_point, struct shim_dentry *parent,
+              struct shim_dentry **dentp, int make_ancestor);
 int unmount_fs (const char * mount_point);
-int readdir_fs (HASHTYPE hash, struct shim_dirent ** dirent);
 int search_builtin_fs (const char * type, struct shim_mount ** fs);
 
 void get_mount (struct shim_mount * mount);
@@ -310,31 +334,108 @@ int walk_mounts (int (*walk) (struct shim_mount * mount, void * arg),
 
 /* functions for dcache supports */
 int init_dcache (void);
-int reinit_dcache (void);
 
 extern LOCKTYPE dcache_lock;
 
+/* check permission (specified by mask) of a dentry. If force is not set,
+ * permission is considered granted on invalid dentries */
+/* Assume caller has acquired dcache_lock */
 int permission (struct shim_dentry * dent, int mask, bool force);
 
-int lookup_dentry (struct shim_dentry * base, const char * name, int namelen,
-                   bool force, struct shim_dentry ** new);
-
+/* This function looks up a single dentry based on its parent dentry pointer
+ * and the name.  Namelen is the length of char * name.
+ * The dentry is returned in pointer *new.
+ * 
+ * The force flag causes the libOS to query the underlying file system for the
+ * existence of the dentry, whereas without force, a negative dentry is
+ * treated as definitive.  In some cases, this can be elided as an
+ * optimization.
+ * 
+ * The caller should hold the dcache_lock.
+ */
+int lookup_dentry (struct shim_dentry * parent, const char * name, int namelen,
+                   bool force, struct shim_dentry ** new, struct shim_mount * fs);
+
+/* Looks up path under start dentry.  Saves in dent.
+ * 
+ * Assumes dcache_lock is held; main difference from path_lookupat is that
+ * dcache_lock is not released on return.
+ * 
+ * The refcount is dropped by one on the returned dentry.
+ * 
+ * The make_ancestor flag creates pseudo-dentries for any parent paths that
+ * are not in cache and do not exist on the underlying file system.  This is
+ * intended for use only in setting up the file system view specified in the manifest.
+ *
+ * If the file isnt' found, returns -ENOENT.
+ * 
+ * If the LOOKUP_DIRECTORY flag is set, and the found file isn't a directory, 
+ *  returns -ENOTDIR.
+ */
 int __path_lookupat (struct shim_dentry * start, const char * path, int flags,
-                     struct shim_dentry ** dent);
+                     struct shim_dentry ** dent, int link_depth,
+                     struct shim_mount *fs, int make_ancestor);
+
+/* Just wraps __path_lookupat, but also acquires and releases the dcache_lock.
+ */
 int path_lookupat (struct shim_dentry * start, const char * name, int flags,
-                   struct shim_dentry ** dent);
+                   struct shim_dentry ** dent, struct shim_mount *fs);
+
+/* This function initializes dir to before a search, to either point
+ * to the current working directory (if dfd == AT_FDCWD), or to the handle pointed to by dfd,
+ * depending on the argument.  
+ * 
+ * Returns -EBADF if dfd is <0 or not a valid handle. 
+ * Returns -ENOTDIR if dfd is not a directory.
+ */
 int path_startat (int dfd, struct shim_dentry ** dir);
 
+/* Open path with given flags, in mode, similar to Unix open.
+ * 
+ * The start dentry specifies where to begin the search.
+ * hdl is an optional argument; if passed in, it is initialized to 
+ *   refer to the opened path.
+ * 
+ * The result is stored in dent.
+ */
+
 int open_namei (struct shim_handle * hdl, struct shim_dentry * start,
                 const char * path, int flags, int mode,
                 struct shim_dentry ** dent);
 
+/* This function calls the low-level file system to do the work
+ * of opening file indicated by dent, and initializing it in hdl.
+ * Flags are standard open flags.
+ *
+ * If O_TRUNC is specified, this function is responsible for calling
+ * the underlying truncate function.
+ */
+
 int dentry_open (struct shim_handle * hdl, struct shim_dentry * dent,
                  int flags);
-int directory_open (struct shim_handle * hdl, struct shim_dentry * dent,
-                    int flags);
 
+/* This function enumerates a directory and caches the results in the dentry.
+ * 
+ * Input: A dentry for a directory in the DENTRY_ISDIRECTORY and not in the
+ * DENTRY_LISTED state.  The dentry DENTRY_LISTED flag is set upon success.
+ * 
+ * Return value: 0 on success, <0 on error
+ */
+int list_directory_dentry (struct shim_dentry *dir);
+
+/* This function caches the contents of a directory (dent), already
+ * in the listed state, in a buffer associated with a handle (hdl).
+ * 
+ * This function should only be called once on a handle.
+ * 
+ * Returns 0 on success, <0 on failure.
+ */
+int list_directory_handle (struct shim_dentry *dent, struct shim_handle *hdl );
+
+
+/* Increment the reference count on dent */
 void get_dentry (struct shim_dentry * dent);
+/* Decrement the reference count on dent */
 void put_dentry (struct shim_dentry * dent);
 
 static_inline
@@ -396,26 +497,50 @@ const char * dentry_get_name (struct shim_dentry * dent)
     return qstrgetstr(&dent->name);
 }
 
-struct shim_dentry * get_new_dentry (struct shim_dentry * parent,
-                                     const char * name, int namelen);
-
-void __set_parent_dentry (struct shim_dentry * child,
-                          struct shim_dentry * parent);
-void __unset_parent_dentry (struct shim_dentry * child,
-                            struct shim_dentry * parent);
-
-void __add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr);
-void add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr);
-
+/* Allocate and initialize a new dentry for path name, under
+ * parent.  Return the dentry.  
+ * 
+ * mount is the mountpoint the dentry is under; this is typically
+ * the parent->fs, but is passed explicitly for initializing 
+ * the dentry of a mountpoint.
+ * 
+ * If hashptr is passed (as an optimization), this is a hash
+ * of the name.
+ * 
+ * If parent is non-null, the ref count is 1; else it is zero.
+ * 
+ * This function also sets up both a name and a relative path
+ */
+struct shim_dentry * get_new_dentry (struct shim_mount *mount,
+                                     struct shim_dentry * parent,
+                                     const char * name, int namelen,
+                                     HASHTYPE * hashptr);
+
+/* This function searches for name/namelen (as the relative path; 
+ * path/pathlen is the fully-qualified path), 
+ * under parent dentry (start).
+ * 
+ * If requested, the expected hash of the dentry is returned in hashptr,
+ * primarily so that the hashing can be reused to add the dentry later.
+ * 
+ * The reference count on the found dentry is incremented by one.
+ *
+ * Used only by shim_namei.c 
+ */
 struct shim_dentry *
 __lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
                  const char * path, int pathlen, HASHTYPE * hashptr);
-struct shim_dentry *
-lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
-               const char * path, int pathlen, HASHTYPE * hashptr);
 
+/* This function recursively deletes and frees all dentries under root 
+ * 
+ * XXX: Current code doesn't do a free..
+ */
 int __del_dentry_tree(struct shim_dentry * root);
 
+/* XXX: Future work: current dcache never shrinks.  Would be nice 
+ * to be able to do something like LRU under space pressure, although
+ * for a single app, this may be over-kill. */
+
 /* hashing utilities */
 #define MOUNT_HASH_BYTE     1
 #define MOUNT_HASH_WIDTH    8

+ 14 - 7
LibOS/shim/src/bookkeep/shim_handle.c

@@ -53,8 +53,13 @@ static inline int init_tty_handle (struct shim_handle * hdl, bool write)
 {
     struct shim_dentry * dent = NULL;
     int ret;
-
-    if ((ret = path_lookupat(NULL, "/dev/tty", LOOKUP_OPEN, &dent)) < 0)
+    struct shim_thread * cur_thread = get_cur_thread();
+    
+    /* XXX: Try getting the root FS from current thread? */
+    assert(cur_thread);
+    assert(cur_thread->root);
+    if ((ret = path_lookupat(cur_thread->root, "/dev/tty", LOOKUP_OPEN, &dent,
+                             cur_thread->root->fs)) < 0)
         return ret;
 
     int flags = (write ? O_WRONLY : O_RDONLY)|O_APPEND;
@@ -94,7 +99,7 @@ static inline int init_exec_handle (struct shim_thread * thread)
     struct shim_mount * fs = find_mount_from_uri(PAL_CB(executable));
     if (fs) {
         path_lookupat(fs->root, PAL_CB(executable) + fs->uri.len, 0,
-                      &exec->dentry);
+                      &exec->dentry, fs);
         set_handle_fs(exec, fs);
         if (exec->dentry) {
             int len;
@@ -480,10 +485,12 @@ void close_handle (struct shim_handle * hdl)
                 dir->dotdot = NULL;
             }
 
-            while (dir->ptr && *dir->ptr) {
-                struct shim_dentry * dent = *dir->ptr;
-                put_dentry(dent);
-                *(dir->ptr++) = NULL;
+            if (dir->ptr != (void *) -1) {
+                while (dir->ptr && *dir->ptr) {
+                    struct shim_dentry * dent = *dir->ptr;
+                    put_dentry(dent);
+                    *(dir->ptr++) = NULL;
+                }
             }
         } else {
             if (hdl->fs && hdl->fs->fs_ops &&

+ 4 - 2
LibOS/shim/src/bookkeep/shim_thread.c

@@ -220,11 +220,13 @@ struct shim_thread * get_new_thread (IDTYPE new_tid)
     } else {
         /* default pid and pgid equals to tid */
         thread->ppid = thread->pgid = thread->tgid = new_tid;
-        path_lookupat(NULL, "/", 0, &thread->root);
+        /* This case should fall back to the global root of the file system.
+         */
+        path_lookupat(NULL, "/", 0, &thread->root, NULL);
         char dir_cfg[CONFIG_MAX];
         if (root_config &&
             get_config(root_config, "fs.start_dir", dir_cfg, CONFIG_MAX) > 0) {
-            path_lookupat(NULL, dir_cfg, 0, &thread->cwd);
+            path_lookupat(NULL, dir_cfg, 0, &thread->cwd, NULL);
         } else if (thread->root) {
             get_dentry(thread->root);
             thread->cwd = thread->root;

+ 0 - 1
LibOS/shim/src/bookkeep/shim_vma.c

@@ -893,7 +893,6 @@ static struct shim_vma * __lookup_supervma (const void * addr, uint64_t length,
     struct shim_vma * tmp, * prev = NULL;
     
     listp_for_each_entry(tmp, &vma_list, list) {
-
         if (test_vma_contain(tmp, addr, length)) {
             if (pprev)
                 *pprev = prev;

+ 1 - 1
LibOS/shim/src/elf/shim_rtld.c

@@ -1400,7 +1400,7 @@ static int __load_interp_object (struct link_map * exec_map)
         struct shim_dentry * dent = NULL;
         int ret = 0;
 
-        if ((ret = path_lookupat(NULL, interp_path, LOOKUP_OPEN, &dent)) < 0 ||
+        if ((ret = path_lookupat(NULL, interp_path, LOOKUP_OPEN, &dent, NULL)) < 0 ||
             dent->state & DENTRY_NEGATIVE)
             continue;
 

+ 0 - 2
LibOS/shim/src/fs/chroot/fs.c

@@ -387,8 +387,6 @@ static int chroot_stat (struct shim_dentry * dent, struct stat * statbuf)
 
 static int chroot_lookup (struct shim_dentry * dent, bool force)
 {
-    if (!force)
-        return -ESKIPPED;
 
     return query_dentry(dent, NULL, NULL, NULL);
 }

+ 1 - 0
LibOS/shim/src/fs/dev/fs.c

@@ -240,6 +240,7 @@ static int dev_open (struct shim_handle * hdl, struct shim_dentry * dent,
 static int dev_lookup (struct shim_dentry * dent, bool force)
 {
     if (qstrempty(&dent->rel_path)) {
+        dent->state |= DENTRY_ISDIRECTORY;
         dent->ino = DEV_INO_BASE;
         return 0;
     }

+ 2 - 2
LibOS/shim/src/fs/proc/fs.c

@@ -177,13 +177,13 @@ static int proc_lookup (struct shim_dentry * dent, bool force)
     }
 
     /* don't care about forced or not */
-    const struct proc_ent * ent;
+    const struct proc_ent * ent = NULL;
     int ret = proc_match_name(qstrgetstr(&dent->rel_path), &ent);
 
     if (!ret && ent->dir)
         dent->state |= DENTRY_ISDIRECTORY;
 
-    if (ent->fs_ops && ent->fs_ops->follow_link)
+    if (ent && ent->fs_ops && ent->fs_ops->follow_link)
         dent->state |= DENTRY_ISLINK;
 
      return ret;

+ 3 - 1
LibOS/shim/src/fs/proc/ipc-thread.c

@@ -101,7 +101,9 @@ do_ipc:
         qstrsetstr(link, (char *) ipc_data, strlen((char *) ipc_data));
 
     if (dentptr) {
-        ret = path_lookupat(NULL, (char *) ipc_data, 0, &dent);
+        /* XXX: Not sure how to handle this case yet */
+        assert (0);
+        ret = path_lookupat(NULL, (char *) ipc_data, 0, &dent, NULL);
         if (ret < 0)
             goto out;
 

+ 6 - 3
LibOS/shim/src/fs/proc/thread.c

@@ -117,7 +117,7 @@ static int find_thread_link (const char * name, struct shim_qstr * link,
     if (nextnext) {
         struct shim_dentry * next_dent = NULL;
 
-        ret = path_lookupat(dent, nextnext, 0, &next_dent);
+        ret = path_lookupat(dent, nextnext, 0, &next_dent, dent->fs);
         if (ret < 0)
             goto out;
 
@@ -221,6 +221,7 @@ static const struct proc_fs_ops fs_thread_link = {
             .follow_link    = &proc_thread_link_follow_link,
         };
 
+/* If *phdl is returned on success, the ref count is incremented */
 static int parse_thread_fd (const char * name, const char ** rest,
                             struct shim_handle ** phdl)
 {
@@ -262,8 +263,10 @@ static int parse_thread_fd (const char * name, const char ** rest,
         return -ENOENT;
     }
 
-    if (phdl)
+    if (phdl) {
         *phdl = handle_map->map[fd]->handle;
+        get_handle(*phdl);
+    }
 
     unlock(handle_map->lock);
 
@@ -368,7 +371,7 @@ static int find_thread_each_fd (const char * name, struct shim_qstr * link,
     if (rest) {
         struct shim_dentry * next_dent = NULL;
 
-        ret = path_lookupat(dent, rest, 0, &next_dent);
+        ret = path_lookupat(dent, rest, 0, &next_dent, dent->fs);
         if (ret < 0)
             goto out;
 

+ 196 - 332
LibOS/shim/src/fs/shim_dcache.c

@@ -1,7 +1,8 @@
 /* -*- mode:c; c-file-style:"k&r"; c-basic-offset: 4; tab-width:4; indent-tabs-mode:nil; mode:auto-fill; fill-column:78; -*- */
 /* vim: set ts=4 sw=4 et tw=78 fo=cqt wm=0: */
 
-/* Copyright (C) 2014 OSCAR lab, Stony Brook University
+/* Copyright (C) 2014 Stony Brook University, 
+   2017 University of North Carolina at Chapel Hill and Fortanix, Inc.
    This file is part of Graphene Library OS.
 
    Graphene Library OS is free software: you can redistribute it and/or
@@ -21,8 +22,6 @@
  * shim_dcache.c
  *
  * This file contains codes for maintaining directory cache in library OS.
- * The source codes are imported from Linux kernel, but simplified according
- * to the characteristic of library OS.
  */
 
 #include <shim_types.h>
@@ -33,34 +32,8 @@
 
 #include <list.h>
 
-/* As best I can tell, dentries are added to this list and then never touched
- * again */
-/* Links to shim_dentry->list */
-static LISTP_TYPE(shim_dentry) dentry_list = LISTP_INIT;
-
-/* Attaches to shim_dentry->hlist */
-static LISTP_TYPE(shim_dentry) dcache_htable[DCACHE_HASH_SIZE] = { LISTP_INIT };
-
 LOCKTYPE dcache_lock;
 
-struct shim_dcache_stats {
-    long memsize;
-    long nentries;
-};
-
-static struct shim_dcache_stats dcache_stats;
-
-long get_dcache_stats (const char * name)
-{
-    if (strcmp_static(name, "memsize"))
-        return dcache_stats.memsize;
-
-    if (strcmp_static(name, "nentries"))
-        return dcache_stats.nentries;
-
-    return 0;
-}
-
 #define DCACHE_MGR_ALLOC    64
 #define PAGE_SIZE           allocsize
 
@@ -71,8 +44,12 @@ static MEM_MGR dentry_mgr = NULL;
 
 struct shim_dentry * dentry_root = NULL;
 
-//#define DEBUG_DCACHE
-//#define DEBUG_REF
+static inline
+HASHTYPE hash_dentry (struct shim_dentry * start, const char * path, int len)
+{
+    return rehash_path(start ? start->rel_path.hash : 0,
+                       path, len, NULL);
+}
 
 static struct shim_dentry * alloc_dentry (void)
 {
@@ -82,9 +59,6 @@ static struct shim_dentry * alloc_dentry (void)
     if (!dent)
         return NULL;
 
-    dcache_stats.memsize += sizeof(struct shim_dentry);
-    dcache_stats.nentries++;
-
     memset(dent, 0, sizeof(struct shim_dentry));
 
     dent->mode = NO_MODE;
@@ -94,139 +68,37 @@ static struct shim_dentry * alloc_dentry (void)
     INIT_LISTP(&dent->children);
     INIT_LIST_HEAD(dent, siblings);
 
-    if (locked(dcache_lock)) {
-        listp_add(dent, &dentry_list, list);
-    } else {
-        lock(dcache_lock);
-        listp_add(dent, &dentry_list, list);
-        unlock(dcache_lock);
-    }
-
     return dent;
 }
 
-DEFINE_PROFILE_CATAGORY(dcache, );
-DEFINE_PROFILE_INTERVAL(total_init_dcache, dcache);
-DEFINE_PROFILE_CATAGORY(within_init_dcache, dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_memory, within_init_dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_lock, within_init_dcache);
-DEFINE_PROFILE_INTERVAL(dcache_init_root_entry, within_init_dcache);
 
 int init_dcache (void)
 {
-#ifdef PROFILE
-    unsigned long begin_time = GET_PROFILE_INTERVAL();
-    BEGIN_PROFILE_INTERVAL_SET(begin_time);
-#endif
-
     dentry_mgr = create_mem_mgr(init_align_up(DCACHE_MGR_ALLOC));
-    SAVE_PROFILE_INTERVAL(dcache_init_memory);
 
     create_lock(dcache_lock);
-    SAVE_PROFILE_INTERVAL(dcache_init_lock);
 
     dentry_root = alloc_dentry();
 
-    qstrsetstr(&dentry_root->rel_path, "", 0);
-    qstrsetstr(&dentry_root->name,     "", 0);
-
+    /* The root is special; we assume it won't change or be freed, and 
+     * set its refcount to 1. */
     get_dentry(dentry_root);
-    SAVE_PROFILE_INTERVAL(dcache_init_root_entry);
 
-    SAVE_PROFILE_INTERVAL_SINCE(total_init_dcache, begin_time);
-    return 0;
-}
-
-int reinit_dcache (void)
-{
-    create_lock(dcache_lock);
+    /* Initialize the root to a valid state, as a low-level lookup
+     *  will fail. */
+    dentry_root->state |= DENTRY_VALID;
 
-    return 0;
-}
+    /* The root should be a directory too*/
+    dentry_root->state |= DENTRY_ISDIRECTORY;
 
-/* remove from the hash table, so that a lookup will fail. */
-static void __del_dcache (struct shim_dentry * dent)
-{
-    if (!(dent->state & DENTRY_HASHED))
-        return;
-
-    /* DEP 5/15/17: I believe that, if a dentry is in the DENTRY_HASHED state,
-     * that the hash field is always valid. */
-    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
-    dent->state &= ~DENTRY_HASHED;
-    listp_del_init(dent, head, hlist);
-
-#ifdef DEBUG_DCACHE
-    debug("del dcache %p(%s/%s) (mount = %p)\n",
-          dent, dent->fs ? qstrgetstr(&dent->fs->path) : "",
-          qstrgetstr(&dent->rel_path), dent->fs);
-#endif
-}
-
-static int __internal_put_dentry (struct shim_dentry * dent);
-
-/* Release a dentry whose ref count has gone to zero. */
-static inline void __dput_dentry (struct shim_dentry * dent)
-{
-    while (1) {
-        /* if the dentry is never in the hash table, we are happy to
-           drop it */
-        if (!(dent->state & DENTRY_HASHED))
-            goto kill;
-
-        /* move the node to unused list unless it is persistent */
-        if (!(dent->state & DENTRY_PERSIST)) {
-            dent->state |= DENTRY_RECENTLY;
-            /* DEP: The only reference I see to this field is being placed on 
-             * the unused list. It seems that sometimes the dent is not
-             * on a list; just hack this for now; this code will be reworked
-             * soon anyway.
-             */
-            /* Chia-Che 10/17/17: Originally we place all the freed
-             * dentries on an unused list, now we just maintain a long list
-             * of all dentries. */
-        }
-
-        /* we don't delete the dentry from dcache because it might
-           be acquired and used again, unless it gets recycled due
-           to memory pressure */
-        break;
-
-kill:   {
-            if (dent->fs && dent->fs->d_ops && dent->fs->d_ops->dput)
-                dent->fs->d_ops->dput(dent);
-
-            struct shim_dentry * parent = dent->parent;
-
-            if (!parent)
-                break;
-
-            listp_del(dent, &parent->children, siblings); /* remove from parent's list of children */
-            listp_del(dent, &dentry_list, list);
-            /* we can free this dentry */
-            free_mem_obj_to_mgr(dentry_mgr, dent);
-            dent = parent;
-
-            if (__internal_put_dentry(dent))
-                break;
-        }
-    }
-}
-
-static int __internal_put_dentry (struct shim_dentry * dent)
-{
-    int count = REF_DEC(dent->ref_count);
-
-#ifdef DEBUG_REF
-    debug("put dentry %p(%s/%s) (ref_count = %d)\n", dent,
-          dent->fs ?
-          qstrgetstr(&dent->fs->path) : "",
-          qstrgetstr(&dent->rel_path), count);
-#endif
+    qstrsetstr(&dentry_root->name,     "", 0);
+    qstrsetstr(&dentry_root->rel_path, "", 0);
 
-    return count;
+    get_dentry(dentry_root);
+    return 0;
 }
 
+/* Increment the reference count for a dentry */
 void get_dentry (struct shim_dentry * dent)
 {
 #ifdef DEBUG_REF
@@ -241,219 +113,208 @@ void get_dentry (struct shim_dentry * dent)
 #endif
 }
 
-void put_dentry (struct shim_dentry * dent)
-{
-    if (__internal_put_dentry(dent))
-        return;
+static void free_dentry (struct shim_dentry *dent) {
+    free_mem_obj_to_mgr(dentry_mgr, dent);
+}
 
-    if (locked(dcache_lock)) {
-        __dput_dentry(dent);
-    } else {
-        lock(dcache_lock);
-        __dput_dentry(dent);
-        unlock(dcache_lock);
+/* Decrement the reference count on dent.
+ * 
+ * For now, we don't have an eviction policy, so just
+ * keep everything.  
+ * 
+ * If a dentry is on the children list of a parent, it has 
+ * a refcount of at least 1.  
+ * 
+ * If the ref count ever hits zero, we free the dentry.
+ *
+ */
+void put_dentry (struct shim_dentry * dent) {
+    int count = REF_DEC(dent->ref_count);
+    assert (count >= 0);
+    // We don't expect this to commonly free a dentry, and may represent a
+    // reference counting bug.
+    if (count == 0) {
+        debug("XXX Churn Warning: Freeing dentry %p; may not be expected\n", dent);
+        // Add some assertions that the dentry is properly cleaned up, like it
+        // isn't on a parent's children list 
+        assert(list_empty(dent, siblings));
+        free_dentry(dent);
     }
+
+    return;
 }
 
-struct shim_dentry * get_new_dentry (struct shim_dentry * parent,
-                                     const char * name, int namelen)
+/* Allocate and initialize a new dentry for path name, under
+ * parent.  Return the dentry.  
+ * 
+ * mount is the mountpoint the dentry is under; this is typically
+ * the parent->fs, but is passed explicitly for initializing 
+ * the dentry of a mountpoint.
+ * 
+ * If hashptr is passed (as an optimization), this is a hash
+ * of the name.
+ * 
+ * If parent is non-null, the ref count is 1; else it is zero.
+ * 
+ * This function also sets up both a name and a relative path
+ */
+struct shim_dentry * get_new_dentry (struct shim_mount *mount,
+                                     struct shim_dentry * parent,
+                                     const char * name, int namelen,
+                                     HASHTYPE * hashptr)
 {
     struct shim_dentry * dent = alloc_dentry();
-
+    HASHTYPE hash;
+    
     if (!dent)
         return NULL;
 
-    REF_SET(dent->ref_count, 0);
+    if (hashptr) {
+#ifdef DEBUG
+        // For debug builds, assert that the hash passed in is correct.
+        assert(*hashptr == hash_dentry(parent, name, namelen));
+#endif
+        hash = *hashptr;
+    } else
+        hash = hash_dentry(parent, name, namelen);
+    
     qstrsetstr(&dent->name, name, namelen);
+    dent->rel_path.hash = hash;
+    /* DEP 6/16/17: Not sure this flag is strictly necessary. 
+     * But keeping it for now.
+     */
+    dent->state |= DENTRY_HASHED;
 
-    if (!parent) {
-        qstrsetstr(&dent->rel_path, name, namelen);
-        return dent;
+    if (mount) {
+        get_mount(mount);
+        dent->fs = mount;
     }
-
-    if (!qstrempty(&parent->rel_path)) {
-        const char * strs[] = { qstrgetstr(&parent->rel_path), "/", name };
-        size_t lens[] = { parent->rel_path.len, 1, namelen };
-        qstrsetstrs(&dent->rel_path, 3, strs, lens);
-    } else
+    
+    if (parent) {
+        // Increment both dentries' ref counts once they are linked
+        get_dentry(parent);
+        get_dentry(dent);
+        listp_add_tail(dent, &parent->children, siblings);
+        dent->parent = parent;
+        parent->nchildren++;
+
+        if (!qstrempty(&parent->rel_path)) {
+            const char * strs[] = { qstrgetstr(&parent->rel_path), "/", name };
+            size_t lens[] = { parent->rel_path.len, 1, namelen };
+            qstrsetstrs(&dent->rel_path, 3, strs, lens);
+        } else
+            qstrsetstr(&dent->rel_path, name, namelen);
+    } else {
         qstrsetstr(&dent->rel_path, name, namelen);
-
-    return dent;
-}
-
-void __set_parent_dentry (struct shim_dentry * child,
-                          struct shim_dentry * parent)
-{
-    if (child->parent == parent)
-        return;
-
-    assert(!child->parent);
-    get_dentry(parent);
-    listp_add_tail(child, &parent->children, siblings);
-    child->parent = parent;
-    parent->nchildren++;
-}
-
-void __unset_parent_dentry (struct shim_dentry * child,
-                            struct shim_dentry * parent)
-{
-    if (child->parent != parent)
-        return;
-
-    assert(child->parent);
-    listp_del_init(child, &parent->children, siblings);
-    child->parent = NULL;
-
-    parent->nchildren--;
-    put_dentry(parent);
-}
-
-static inline
-HASHTYPE hash_dentry (struct shim_dentry * start, const char * path, int len)
-{
-    return rehash_path(start ? start->rel_path.hash : 0,
-                       path, len, NULL);
-}
-
-void __add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr)
-{
-    LISTP_TYPE(shim_dentry) * head;
-
-    if (hashptr) {
-        dent->rel_path.hash = *hashptr;
-        goto add_hash;
-    }
-
-    if (!dent->parent) {
-        dent->rel_path.hash = dent->fs ? dent->fs->path.hash : 0;
-        goto add_hash;
     }
 
-    dent->rel_path.hash = hash_dentry(dent->parent, dentry_get_name(dent),
-                                      dent->name.len);
-
-add_hash:
-    head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
-    listp_add(dent, head, hlist);
-    dent->state |= DENTRY_HASHED;
-
-#ifdef DEBUG_DCACHE
-    debug("add dcache %p(%s/%s) (mount = %p)\n",
-          dent, dent->fs ? qstrgetstr(&dent->fs->path) : "",
-          qstrgetstr(&dent->rel_path), dent->fs);
-#endif
-}
-
-void add_dcache (struct shim_dentry * dent, HASHTYPE * hashptr)
-{
-    lock(dcache_lock);
-    __add_dcache(dent, hashptr);
-    unlock(dcache_lock);
+    return dent;
 }
 
+/* This function searches for name/namelen (as the relative path) under 
+ * the parent directory (start).
+ * 
+ * path/pathlen is the fully-qualified path, and an optional (unused)
+ * argument.  XXX: I am not sure what the case is where the full path
+ * would resolve but the relative path would not; consider dropping
+ * this argument, or documenting the reason (after testing).
+ * 
+ * If requested, the expected hash of the dentry is returned in hashptr,
+ * primarily so that the hashing can be reused to add the dentry later.
+ * 
+ * The reference count on the found dentry is incremented by one.
+ * 
+ * Used only by shim_namei.c 
+ */
 struct shim_dentry *
 __lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
-                 const char * path, int pathlen, HASHTYPE * hashptr)
-{
+                 const char * path, int pathlen, HASHTYPE * hashptr) {
+
+    /* In this implementation, we just look at the children 
+     * under the parent and see if there are matches.  It so,
+     * return it; if not, don't.  
+     * 
+     * To minimize disruption (and possibly for future optimization)
+     * we are keeping hashes, so let's start with that for a marginally
+     * faster comparison 
+     */
     HASHTYPE hash = hash_dentry(start, name, namelen);
-    struct shim_dentry * dent, * found = NULL;
-    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(hash)];
-
-    /* walk through all the nodes in the hash bucket, find the droids we're
-       looking for */
-    listp_for_each_entry(dent, head, hlist) {
-        if ((dent->state & DENTRY_MOUNTPOINT) ||
-            dent->rel_path.hash != hash)
+    struct shim_dentry *dent, *found = NULL;
+
+    /* If start is NULL, there will be no hit in the cache.
+     * This mainly happens when boostrapping; in general, we assume the 
+     * caller will use the current root or cwd.
+     */
+    if (!start) return NULL;
+
+    /* If we are looking up an empty string, return start */
+    if (namelen == 0) {
+        found = start;
+        goto out;
+    }
+    
+    listp_for_each_entry(dent, &start->children, siblings) {
+        /* DEP 6/20/XX: The old code skipped mountpoints; I don't see any good
+         * reason for mount point lookup to fail, at least in this code.
+         * Keeping a note just in case.  That is why you always leave a note.
+         */
+        //if (dent->state & DENTRY_MOUNTPOINT)
+        //continue;
+
+        // Check for memory corruption
+        assert(0 == (dent->state & DENTRY_INVALID_FLAGS));
+        
+        /* Compare the hash first */
+        if (dent->rel_path.hash != hash)
             continue;
 
-        /* first we compare the filename */
+        /* I think comparing the relative path is adequate; with a global 
+         * hash table, a full path comparison may be needed, but I think 
+         * we can assume a parent has children with unique names */
         const char * filename = get_file_name(name, namelen);
-        if (memcmp(dentry_get_name(dent), filename, name + namelen - filename))
+        const char * dname = dentry_get_name(dent);
+        int dname_len = strlen(dname);
+        int fname_len = name + namelen - filename;
+        if (dname_len != fname_len || memcmp(dname, filename, fname_len))
             continue;
 
-        if (filename == name) {
-            struct shim_dentry * d = dent;
-            while (d && !d->parent && d->fs)
-                d = d->fs->mount_point;
-            if (d && d->parent && d->parent != start)
-                continue;
-        }
-
-        if (path && pathlen && filename != path) {
-            const char * fullpath;
-            int fullpathlen;
-            fullpath = dentry_get_path(dent, true, &fullpathlen);
-            if (pathlen > fullpathlen)
-                continue;
-            fullpath += fullpathlen - pathlen;
-            if (fullpath[-1] != '/')
-                continue;
-            if (memcmp(fullpath, path, pathlen))
-                continue;
-        }
-
+        /* If we get this far, we have a match */
         get_dentry(dent);
         found = dent;
         break;
     }
 
+out:
     if (hashptr)
         *hashptr = hash;
 
     return found;
 }
 
-/* after lookup_dcache, the dentry is popped to prevent recycling */
-struct shim_dentry *
-lookup_dcache (struct shim_dentry * start, const char * name, int namelen,
-               const char * path, int pathlen, HASHTYPE * hashptr)
-{
-    lock(dcache_lock);
-    struct shim_dentry * dent = __lookup_dcache(start, name, namelen, path,
-                                                pathlen, hashptr);
-    unlock(dcache_lock);
-    return dent;
-}
-
-int __del_dentry_tree (struct shim_dentry * root)
-{
-    struct shim_dentry * this_parent = root;
-    struct shim_dentry * next;
-
-repeat:
-    next = this_parent->children.first;
-
-resume:
-    while (next != this_parent->children.first) {
-        struct shim_dentry *d, * tmp;
-        d = tmp = next;
-        next = tmp->siblings.next;
-        if (d->state & DENTRY_MOUNTPOINT) {
-            this_parent = d->mounted->root;
-            goto repeat;
-        }
-
-        if (!listp_empty(&d->children)) {
-            this_parent = d;
-            goto repeat;
-        }
-
-        __unset_parent_dentry(d, this_parent);
-        __del_dcache(d);
-    }
-
-    if (this_parent != root) {
-        struct shim_dentry * child = this_parent;
-        if (!this_parent->parent) {
-            this_parent = this_parent->fs->mount_point;
-            __del_dcache(child);
-            child = this_parent;
-        }
-        this_parent = this_parent->parent;
-        next = child->siblings.next;
-        __del_dcache(child);
-        __unset_parent_dentry(child, this_parent);
-        goto resume;
+/* This function recursively removes children and drops the reference count
+ * under root (but not the root itself).
+ *
+ * For memory-constrained systems (arguably SGX enclaves), there is a
+ * legitimate concern that this could overflow the stack, as a path can have
+ * as many as 4096 characters, leading to as many as 2048 stack frames.  It
+ * may be preferable to rewrite this using tail recursion or allocating a
+ * structure on the heap to track progress.
+ */
+int __del_dentry_tree(struct shim_dentry * root) {
+    struct shim_dentry *cursor, *n;
+
+    listp_for_each_entry_safe(cursor, n, &root->children, siblings) {
+        // Recur if this is a non-empty directory 
+        if (!listp_empty(&cursor->children))
+            __del_dentry_tree(cursor);
+
+        listp_del_init(cursor, &root->children, siblings);
+        cursor->parent = NULL;
+        root->nchildren--;
+        // Clear the hashed flag, in case there is any vestigial code based
+        //  on this state machine (where hased == valid).
+        cursor->state &= ~DENTRY_HASHED;
+        put_dentry(cursor);
     }
 
     return 0;
@@ -509,7 +370,6 @@ END_CP_FUNC(dentry)
 BEGIN_RS_FUNC(dentry)
 {
     struct shim_dentry * dent = (void *) (base + GET_CP_FUNC_ENTRY());
-    BEGIN_PROFILE_INTERVAL();
 
     CP_REBASE(dent->hlist);
     CP_REBASE(dent->list);
@@ -521,15 +381,19 @@ BEGIN_RS_FUNC(dentry)
 
     create_lock(dent->lock);
 
-    if (dent->parent)
-        __set_parent_dentry(dent, dent->parent);
-
-    LISTP_TYPE(shim_dentry) * head = &dcache_htable[DCACHE_HASH(dent->rel_path.hash)];
-    listp_add(dent, head, hlist);
-    dent->state |= DENTRY_HASHED;
+    /* DEP 6/16/17: I believe the point of this line is to 
+     * fix up the children linked list.  Presumably the ref count and 
+     * child count is already correct in the checkpoint. */   
+    if (dent->parent) {
+        get_dentry(dent->parent);
+        get_dentry(dent);
+        listp_add_tail(dent, &dent->parent->children, siblings);
+    }
 
     DEBUG_RS("hash=%08x,path=%s,fs=%s", dent->rel_path.hash,
              dentry_get_path(dent, true, NULL),
              dent->fs ? qstrgetstr(&dent->fs->path) : NULL);
 }
 END_RS_FUNC(dentry)
+
+

+ 158 - 36
LibOS/shim/src/fs/shim_fs.c

@@ -94,38 +94,55 @@ static struct shim_mount * alloc_mount (void)
 
 static bool mount_migrated = false;
 
-static int __mount_root (void)
+static int __mount_root (struct shim_dentry ** root)
 {
-    int ret;
-    if ((ret = mount_fs("chroot", "file:", "/")) < 0) {
-        debug("mounting root filesystem failed (%e)\n", ret);
-        return ret;
+    char type[CONFIG_MAX], uri[CONFIG_MAX];
+    int ret = 0;
+
+    if (root_config &&
+            get_config(root_config, "fs.root.type", type, CONFIG_MAX) > 0 &&
+            get_config(root_config, "fs.root.uri", uri, CONFIG_MAX) > 0) {
+        debug("mounting root filesystem: %s from %s\n", type, uri);
+        if ((ret = mount_fs(type, uri, "/", NULL, root, 0)) < 0) {
+            debug("mounting root filesystem failed (%d)\n", ret);
+            goto out;
+        }
+        goto out;
     }
-    return 0;
+
+    debug("mounting default root filesystem\n");
+    if ((ret = mount_fs("chroot", "file:", "/", NULL, root, 0)) < 0) {
+        debug("mounting root filesystem failed (%d)\n", ret);
+        goto out;
+    }
+
+out:
+    return ret;
 }
 
-static int __mount_sys (void)
+static int __mount_sys (struct shim_dentry *root)
 {
     int ret;
 
     debug("mounting as proc filesystem: /proc\n");
 
-    if ((ret = mount_fs("proc", NULL, "/proc")) < 0) {
-        debug("mounting proc filesystem failed (%e)\n", ret);
+    if ((ret = mount_fs("proc", NULL, "/proc", root, NULL, 0)) < 0) {
+        debug("mounting proc filesystem failed (%d)\n", ret);
         return ret;
     }
 
     debug("mounting as dev filesystem: /dev\n");
 
-    if ((ret = mount_fs("dev", NULL, "/dev")) < 0) {
-        debug("mounting dev filesystem failed (%e)\n", ret);
+    struct shim_dentry *dev_dent = NULL;
+    if ((ret = mount_fs("dev", NULL, "/dev", root, &dev_dent, 0)) < 0) {
+        debug("mounting dev filesystem failed (%d)\n", ret);
         return ret;
     }
 
     debug("mounting as chroot filesystem: from dev:tty to /dev\n");
 
-    if ((ret = mount_fs("chroot", "dev:tty", "/dev/tty")) < 0) {
-        debug("mounting terminal device failed (%e)\n", ret);
+    if ((ret = mount_fs("chroot", "dev:tty", "/dev/tty", dev_dent, NULL, 0)) < 0) {
+        debug("mounting terminal device failed (%d)\n", ret);
         return ret;
     }
 
@@ -160,7 +177,7 @@ static int __mount_one_other (const char * key, int keylen)
 
     debug("mounting as %s filesystem: from %s to %s\n", t, uri, p);
 
-    if ((ret = mount_fs(t, uri, p)) < 0) {
+    if ((ret = mount_fs(t, uri, p, NULL, NULL, 1)) < 0) {
         debug("mounting %s on %s (type=%s) failed (%e)\n", uri, p, t,
               -ret);
         return ret;
@@ -200,11 +217,12 @@ int init_mount_root (void)
         return 0;
 
     int ret;
-
-    if ((ret = __mount_root()) < 0)
+    struct shim_dentry *root = NULL;
+    
+    if ((ret = __mount_root(&root)) < 0)
         return ret;
 
-    if ((ret = __mount_sys()) < 0)
+    if ((ret = __mount_sys(root)) < 0)
         return ret;
 
     return 0;
@@ -262,22 +280,34 @@ int __mount_fs (struct shim_mount * mount, struct shim_dentry * dent)
     struct shim_dentry * mount_root = mount->root;
 
     if (!mount_root) {
-        mount_root = get_new_dentry(NULL, "", 0);
-        mount_root->fs = mount;
         /* mount_root->state |= DENTRY_VALID; */
-        qstrsetstr(&mount_root->name, dentry_get_name(dent),
-                   dent->name.len);
-
-        if (mount->d_ops && mount->d_ops->lookup &&
-            (ret = mount->d_ops->lookup(mount_root, 0)) < 0 &&
-            ret != -ESKIPPED)
+        mount_root = get_new_dentry(mount, NULL, "", 0, NULL);
+        assert(mount->d_ops && mount->d_ops->lookup);
+        ret = mount->d_ops->lookup(mount_root, 0);
+        if (ret < 0) {
+            /* Try getting rid of ESKIPPED case */
+            assert (ret != -ESKIPPED);
             return ret;
-
+        }
         mount->root = mount_root;
     }
 
-    mount_root->state |= dent->state & (DENTRY_REACHABLE|DENTRY_UNREACHABLE);
-    __add_dcache(mount_root, &mount->path.hash);
+    /* DEP 7/1/17: If the mount is a directory, make sure the mount
+     * point is marked as a directory */
+    if (mount_root->state & DENTRY_ISDIRECTORY)
+        dent->state |= DENTRY_ISDIRECTORY;
+    
+    /* DEP 6/16/17: In the dcache redesign, we don't use the *REACHABLE flags, but
+     * leaving this commented for documentation, in case there is a problem
+     * I over-simplified */
+    //mount_root->state |= dent->state & (DENTRY_REACHABLE|DENTRY_UNREACHABLE);
+
+    /* DEP 6/16/17: In the dcache redesign, I don't believe we need to manually
+     * rehash the path; this should be handled by get_new_dentry, or already be 
+     * hashed if mount_root exists.  I'm going to leave this line here for now
+     * as documentation in case there is a problem later.
+     */
+    //__add_dcache(mount_root, &mount->path.hash);
 
     if ((ret = __del_dentry_tree(dent)) < 0)
         return ret;
@@ -290,22 +320,32 @@ int __mount_fs (struct shim_mount * mount, struct shim_dentry * dent)
     do {
         struct shim_dentry * parent = dent->parent;
 
-        if (dent->state & DENTRY_ANCESTER) {
+        if (dent->state & DENTRY_ANCESTOR) {
             put_dentry(dent);
             break;
         }
 
-        dent->state |= DENTRY_ANCESTER;
+        dent->state |= DENTRY_ANCESTOR;
         if (parent)
             get_dentry(parent);
         put_dentry(dent);
         dent = parent;
     } while (dent);
 
+    
     return 0;
 }
 
-int mount_fs (const char * type, const char * uri, const char * mount_point)
+/* Parent is optional, but helpful.
+ * dentp (optional) memoizes the dentry of the newly-mounted FS, on success. 
+ *
+ * The make_ancestor flag creates pseudo-dentries for any missing paths (passed to
+ * __path_lookupat).  This is only intended for use to connect mounts specified in the manifest
+ * when an intervening path is missing.
+ */
+int mount_fs (const char * type, const char * uri, const char * mount_point,
+              struct shim_dentry *parent, struct shim_dentry **dentp,
+              int make_ancestor)
 {
     int ret = 0;
     struct shim_fs * fs = find_fs(type);
@@ -315,11 +355,47 @@ int mount_fs (const char * type, const char * uri, const char * mount_point)
         goto out;
     }
 
-    lock(dcache_lock);
+    /* Split the mount point into the prefix and atom */
+    int mount_point_len = strlen(mount_point);
+    const char * last = &mount_point[mount_point_len - 1];
+    int left = mount_point_len;
+    int last_len = 1;
+    // Drop any trailing slashes
+    while (left && *last == '/') {
+        left--;
+        last--;
+        if (last_len != 0)
+            last_len--;
+    }
+    // Skip the atom
+    while (left && *last != '/') {
+        left--;
+        last--;
+        last_len++;
+    }
+    if (*last == '/') {
+        // Move forward one
+        last++;
+        last_len--;
+    }
 
-    struct shim_dentry * dent;
-    if ((ret = __path_lookupat(NULL, mount_point, 0, &dent)) < 0)
-        goto out;
+    if (!parent) {
+        // See if we are not at the root mount
+        if (mount_point_len != 1 || mount_point[0] != '/') {
+            // Look up the parent
+            char * parent_path = __alloca(mount_point_len);
+            memset(parent_path, 0, mount_point_len);
+            assert(last_len >= 1 && (mount_point_len - last_len) >= 0);
+            memcpy(parent_path, mount_point, mount_point_len - last_len);
+            if ((ret = __path_lookupat(dentry_root, parent_path, 0, &parent, 0,
+                                       dentry_root->fs, make_ancestor)) < 0) {
+                debug("Path lookup failed %d\n", ret);
+                goto out;
+            }
+        }
+    }
+    
+    lock(dcache_lock);
 
     struct shim_mount * mount = alloc_mount();
     void * mount_data = NULL;
@@ -328,16 +404,62 @@ int mount_fs (const char * type, const char * uri, const char * mount_point)
     if ((ret = fs->fs_ops->mount(uri, mount_point, &mount_data)) < 0)
         goto out;
 
+
     int uri_len = uri ? strlen(uri) : 0;
-    qstrsetstr(&mount->path, mount_point, strlen(mount_point));
+    qstrsetstr(&mount->path, mount_point, mount_point_len);
     qstrsetstr(&mount->uri, uri, uri_len);
     memcpy(mount->type, fs->name, sizeof(fs->name));
     mount->fs_ops    = fs->fs_ops;
     mount->d_ops     = fs->d_ops;
     mount->data      = mount_data;
+
+    /* Get the negative dentry from the cache, if one exists */
+    struct shim_dentry * dent, *dent2;
+    /* Special case the root */
+    if (mount_point_len == 1 && mount_point[0] == '/')
+        dent = dentry_root;
+    else {
+        dent = __lookup_dcache(parent, last,
+                               last_len,
+                               NULL, 0, NULL);
+
+        if(!dent) {
+            dent = get_new_dentry(mount, parent, last, last_len, NULL);
+            get_dentry(dent);
+        }
+    }
+    
+    assert(dent == dentry_root || !(dent->state & DENTRY_VALID));    
+
+    // We need to fix up the relative path to this mount, but only for
+    // directories.  
+    qstrsetstr(&dent->rel_path, "", 0);
     mount->path.hash = dent->rel_path.hash;
 
+    /*Now go ahead and do a lookup so the dentry is valid */
+    if ((ret = __path_lookupat(dentry_root, mount_point, 0, &dent2, 0,
+                               parent ? parent->fs : mount, make_ancestor)) < 0) 
+        goto out;
+
+    assert(dent == dent2);
+
+    /* We want the net impact of mounting to increment the ref count on the
+     * entry (until the unmount).  But we shouldn't also hold the reference on
+     * dent from the validation step.  Drop it here */
+    put_dentry(dent2);
+    
     ret = __mount_fs(mount, dent);
+
+    // If we made it this far and the dentry is still negative, clear
+    // the negative flag from the denry. 
+    if ((!ret) && (dent->state & DENTRY_NEGATIVE)) 
+        dent->state &= ~DENTRY_NEGATIVE;
+    
+    /* Set the file system at the mount point properly */
+    dent->fs = mount;
+    
+    if (dentp && !ret)
+        *dentp = dent;
 out:
     unlock(dcache_lock);
     return ret;

File diff suppressed because it is too large
+ 429 - 781
LibOS/shim/src/fs/shim_namei.c


+ 2 - 0
LibOS/shim/src/ipc/shim_ipc_nsimpl.h

@@ -544,6 +544,7 @@ int CONCAT3(del, NS, range) (IDTYPE idx)
     // Re-acquire the head; kind of ugly
     LISTP_TYPE(range) * head = range_table + RANGE_HASH(off);
     listp_del(r, head, hlist);
+
     /* Chia-Che Tsai 10/17/17: only when r->owner is non-NULL,
      * and r->owner->vmid == cur_process.vmid, r is on the
      * owned list, otherwise it is an offered. */
@@ -551,6 +552,7 @@ int CONCAT3(del, NS, range) (IDTYPE idx)
         listp_del(r, &owned_ranges, list);
     else
         listp_del(r, &offered_ranges, list);
+
     put_ipc_info(r->owner);
     free(r);
 

+ 4 - 2
LibOS/shim/src/shim_checkpoint.c

@@ -634,7 +634,9 @@ int init_from_checkpoint_file (const char * filename,
     struct shim_dentry * dir = NULL;
     int ret;
 
-    ret = path_lookupat(NULL, filename, LOOKUP_ACCESS|LOOKUP_DIRECTORY, &dir);
+    /* XXX: Not sure what to do here yet */
+    assert(0);
+    ret = path_lookupat(NULL, filename, LOOKUP_ACCESS|LOOKUP_DIRECTORY, &dir, NULL);
     if (ret < 0)
         return ret;
 
@@ -654,7 +656,7 @@ int init_from_checkpoint_file (const char * filename,
     for ( ; d ; d = d->next) {
         struct shim_dentry * file;
         if ((ret = lookup_dentry(dir, d->name, strlen(d->name), false,
-                                 &file)) < 0)
+                                 &file, dir->fs)) < 0)
             continue;
         if (file->state & DENTRY_NEGATIVE)
             continue;

+ 2 - 2
LibOS/shim/src/sys/shim_access.c

@@ -43,7 +43,7 @@ int shim_do_access (const char * file, mode_t mode)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    ret = path_lookupat(NULL, file, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent);
+    ret = path_lookupat(NULL, file, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent, NULL);
     if (!ret)
         ret = permission(dent, mode, 1);
 
@@ -64,7 +64,7 @@ int shim_do_faccessat (int dfd, const char * filename, mode_t mode)
     if ((ret = path_startat(dfd, &dir)) < 0)
         return ret;
 
-    ret = path_lookupat(dir, filename, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent);
+    ret = path_lookupat(dir, filename, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent, NULL);
     if (ret < 0)
         goto out;
 

+ 3 - 1
LibOS/shim/src/sys/shim_exec.c

@@ -234,7 +234,9 @@ int shim_do_execve (const char * file, const char ** argv,
 
 reopen:
 
-    if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent)) < 0)
+    /* XXX: Not sure what to do here yet */
+    assert(cur_thread);
+    if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     struct shim_mount * fs = dent->fs;

+ 22 - 13
LibOS/shim/src/sys/shim_fs.c

@@ -52,7 +52,7 @@ int shim_do_unlink (const char * file)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, file, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     if (!dent->parent)
@@ -88,7 +88,7 @@ int shim_do_unlinkat (int dfd, const char * pathname, int flag)
     if ((ret = path_startat(dfd, &dir)) < 0)
         return ret;
 
-    if ((ret = path_lookupat(dir, pathname, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(dir, pathname, LOOKUP_OPEN, &dent, NULL)) < 0)
         goto out;
 
     if (!dent->parent) {
@@ -155,7 +155,7 @@ int shim_do_rmdir (const char * pathname)
     struct shim_dentry * dent = NULL;
 
     if ((ret = path_lookupat(NULL, pathname, LOOKUP_OPEN|LOOKUP_DIRECTORY,
-                             &dent)) < 0)
+                             &dent, NULL)) < 0)
         return ret;
 
     if (!dent->parent) {
@@ -197,7 +197,7 @@ int shim_do_chmod (const char * path, mode_t mode)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     if (dent->fs && dent->fs->d_ops &&
@@ -227,7 +227,7 @@ int shim_do_fchmodat (int dfd, const char * filename, mode_t mode)
     if ((ret = path_startat(dfd, &dir)) < 0)
         return ret;
 
-    if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent, NULL)) < 0)
         goto out;
 
     if (dent->fs && dent->fs->d_ops &&
@@ -272,7 +272,7 @@ int shim_do_chown (const char * path, uid_t uid, gid_t gid)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     /* XXX: do nothing now */
@@ -295,7 +295,7 @@ int shim_do_fchownat (int dfd, const char * filename, uid_t uid, gid_t gid,
     if ((ret = path_startat(dfd, &dir)) < 0)
         return ret;
 
-    if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(dir, filename, LOOKUP_OPEN, &dent, NULL)) < 0)
         goto out;
 
     /* XXX: do nothing now */
@@ -666,7 +666,7 @@ int shim_do_rename (const char * oldname, const char * newname)
     struct shim_dentry * old_dent = NULL, * new_dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, oldname, LOOKUP_OPEN, &old_dent)) < 0)
+    if ((ret = path_lookupat(NULL, oldname, LOOKUP_OPEN, &old_dent, NULL)) < 0) 
         goto out;
 
     if (old_dent->state & DENTRY_NEGATIVE) {
@@ -675,9 +675,17 @@ int shim_do_rename (const char * oldname, const char * newname)
     }
 
     if ((ret = path_lookupat(NULL, newname, LOOKUP_OPEN|LOOKUP_CREATE,
-                             &new_dent)) < 0)
-        goto out;
+                             &new_dent, NULL)) < 0) {
+        // It is now ok for pathlookupat to return ENOENT with a negative DETRY
+        if (!(ret == -ENOENT && new_dent
+              && (new_dent->state & (DENTRY_NEGATIVE|DENTRY_VALID))))
+            goto out;
+    }
 
+    // Both dentries should have a ref count of at least 2 at this point
+    assert(REF_GET(old_dent->ref_count) >= 2);
+    assert(REF_GET(new_dent->ref_count) >= 2);
+    
     ret = do_rename(old_dent, new_dent);
 
 out:
@@ -685,6 +693,7 @@ out:
         put_dentry(old_dent);
     if (new_dent)
         put_dentry(new_dent);
+
     return ret;
 }
 
@@ -699,7 +708,7 @@ int shim_do_renameat (int olddfd, const char * pathname, int newdfd,
         goto out;
 
 
-    if ((ret = path_lookupat(old_dir, pathname, LOOKUP_OPEN, &old_dent)) < 0)
+    if ((ret = path_lookupat(old_dir, pathname, LOOKUP_OPEN, &old_dent, NULL)) < 0)
         goto out;
 
     if (old_dent->state & DENTRY_NEGATIVE) {
@@ -711,7 +720,7 @@ int shim_do_renameat (int olddfd, const char * pathname, int newdfd,
         goto out;
 
     if ((ret = path_lookupat(new_dir, newname, LOOKUP_OPEN|LOOKUP_CREATE,
-                             &new_dent)) < 0)
+                             &new_dent, NULL)) < 0)
         goto out;
 
     ret = do_rename(old_dent, new_dent);
@@ -767,7 +776,7 @@ int shim_do_chroot (const char * filename)
 {
     int ret = 0;
     struct shim_dentry * dent = NULL;
-    if ((ret = path_lookupat(NULL, filename, 0 , &dent)) < 0)
+    if ((ret = path_lookupat(NULL, filename, 0 , &dent, NULL)) < 0)
         goto out;
 
     if (!dent) {

+ 1 - 1
LibOS/shim/src/sys/shim_getcwd.c

@@ -70,7 +70,7 @@ int shim_do_chdir (const char * filename)
     struct shim_dentry * dent = NULL;
     int ret;
 
-    if ((ret = path_lookupat(NULL, filename, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, filename, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     if (!dent)

+ 27 - 5
LibOS/shim/src/sys/shim_open.c

@@ -336,6 +336,12 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
     struct linux_dirent * b = buf;
     int bytes = 0;
 
+    /* If we haven't listed the directory, do this first */
+    if (!(dent->state & DENTRY_LISTED)) {
+        ret = list_directory_dentry(dent);
+        if (ret) goto out;
+    }
+
 #define DIRENT_SIZE(len)  (sizeof(struct linux_dirent) +                \
                            sizeof(struct linux_dirent_tail) + (len) + 1)
 
@@ -374,6 +380,11 @@ size_t shim_do_getdents (int fd, struct linux_dirent * buf, size_t count)
         dirhdl->dotdot = NULL;
     }
 
+    if (dirhdl->ptr == (void *) -1) {
+        ret = list_directory_handle(dent, hdl);
+        if (ret) goto out;
+    }
+    
     while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
         /* DEP 3/3/17: We need to filter negative dentries */
@@ -390,8 +401,8 @@ done:
     ret = bytes;
     /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to
      * hold anything */
-    if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr)
-                       || dirhdl->dotdot || dirhdl->dot))
+    if (bytes == 0 && (dirhdl->dot || dirhdl->dotdot || 
+                       (dirhdl->ptr && *dirhdl->ptr)))
         ret = -EINVAL;
     unlock(hdl->lock);
 out:
@@ -425,6 +436,12 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
     struct linux_dirent64 * b = buf;
     int bytes = 0;
 
+    /* If we haven't listed the directory, do this first */
+    if (!(dent->state & DENTRY_LISTED)) {
+        ret = list_directory_dentry(dent);
+        if (ret) goto out;
+    }
+    
 #define DIRENT_SIZE(len)  (sizeof(struct linux_dirent64) + (len) + 1)
 
 #define ASSIGN_DIRENT(dent, name, type)                                 \
@@ -456,6 +473,11 @@ size_t shim_do_getdents64 (int fd, struct linux_dirent64 * buf, size_t count)
         dirhdl->dotdot = NULL;
     }
 
+    if (dirhdl->ptr == (void *) -1) {
+        ret = list_directory_handle(dent, hdl);
+        if (ret) goto out;
+    }
+    
     while (dirhdl->ptr && *dirhdl->ptr) {
         dent = *dirhdl->ptr;
         /* DEP 3/3/17: We need to filter negative dentries */
@@ -472,8 +494,8 @@ done:
     ret = bytes;
     /* DEP 3/3/17: Properly detect EINVAL case, where buffer is too small to
      * hold anything */
-    if (bytes == 0 && ((dirhdl->ptr && *dirhdl->ptr)
-                       || dirhdl->dotdot || dirhdl->dot))
+    if (bytes == 0 && (dirhdl->dot || dirhdl->dotdot || 
+                       (dirhdl->ptr && *dirhdl->ptr)))
         ret = -EINVAL;
     unlock(hdl->lock);
 out:
@@ -521,7 +543,7 @@ int shim_do_truncate (const char * path, loff_t length)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, path, 0, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, path, 0, &dent, NULL)) < 0)
         return ret;
 
     struct shim_mount * fs = dent->fs;

+ 1 - 1
LibOS/shim/src/sys/shim_sandbox.c

@@ -60,7 +60,7 @@ static int isolate_fs (struct config_store * cfg, const char * path)
     struct shim_dentry * dent = NULL;
     int ret = 0;
 
-    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, path, LOOKUP_OPEN, &dent, NULL)) < 0)
         return ret;
 
     if (!(dent->state & DENTRY_ISDIRECTORY)) {

+ 8 - 4
LibOS/shim/src/sys/shim_socket.c

@@ -470,9 +470,13 @@ int shim_do_bind (int sockfd, struct sockaddr * addr, socklen_t addrlen)
         char * spath = saddr->sun_path;
         struct shim_dentry * dent = NULL;
 
-        if ((ret = path_lookupat(NULL, spath, LOOKUP_CREATE, &dent)) < 0) 
-            goto out;
-
+        if ((ret = path_lookupat(NULL, spath, LOOKUP_CREATE, &dent, NULL)) < 0) {
+            // DEP 7/3/17: We actually want either 0 or -ENOENT, as the
+            // expected case is that the name is free (and we get the dent to
+            // populate the name)
+            if (ret != -ENOENT || !dent)
+                goto out;
+        }
 
         if (dent->state & DENTRY_VALID &&
             !(dent->state & DENTRY_NEGATIVE)) {
@@ -720,7 +724,7 @@ int shim_do_connect (int sockfd, struct sockaddr * addr, int addrlen)
         char * spath = saddr->sun_path;
         struct shim_dentry * dent;
 
-        if ((ret = path_lookupat(NULL, spath, LOOKUP_CREATE, &dent)) < 0)
+        if ((ret = path_lookupat(NULL, spath, LOOKUP_CREATE, &dent, NULL)) < 0)
             goto out;
 
         struct shim_unix_data * data = dent->data;

+ 48 - 3
LibOS/shim/src/sys/shim_stat.c

@@ -42,7 +42,7 @@ int shim_do_stat (const char * file, struct stat * stat)
     int ret;
     struct shim_dentry * dent = NULL;
 
-    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent, NULL)) < 0)
         goto out;
 
     struct shim_mount * fs = dent->fs;
@@ -67,7 +67,7 @@ int shim_do_lstat (const char * file, struct stat * stat)
     int ret;
     struct shim_dentry * dent = NULL;
 
-    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent, NULL)) < 0)
         goto out;
 
     struct shim_mount * fs = dent->fs;
@@ -117,7 +117,7 @@ int shim_do_readlink (const char * file, char * buf, int bufsize)
     struct shim_dentry * dent = NULL;
     struct shim_qstr qstr = QSTR_INIT;
 
-    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent)) < 0)
+    if ((ret = path_lookupat(NULL, file, LOOKUP_ACCESS, &dent, NULL)) < 0)
         return ret;
 
     ret = -EINVAL;
@@ -143,3 +143,48 @@ out:
     put_dentry(dent);
     return ret;
 }
+
+static int __do_statfs (struct shim_mount * fs, struct statfs * buf)
+{
+    if (!buf)
+        return -EFAULT;
+
+    memset(buf, 0, sizeof(*buf));
+
+    buf->f_bsize = 4096;
+    buf->f_blocks = 20000000;
+    buf->f_bfree = 10000000;
+    buf->f_bavail = 10000000;
+
+    debug("statfs: %ld %ld %ld\n", buf->f_blocks, buf->f_bfree,
+            buf->f_bavail);
+
+    return 0;
+}
+
+int shim_do_statfs (const char * path, struct statfs * buf)
+{
+    if (!path)
+        return -EFAULT;
+
+    int ret;
+    struct shim_dentry * dent = NULL;
+
+    if ((ret = path_lookupat(NULL, path, LOOKUP_ACCESS|LOOKUP_FOLLOW, &dent, NULL)) < 0)
+        return ret;
+
+    struct shim_mount * fs = dent->fs;
+    put_dentry(dent);
+    return __do_statfs (fs, buf);
+}
+
+int shim_do_fstatfs (int fd, struct statfs * buf)
+{
+    struct shim_handle * hdl = get_fd_handle(fd, NULL, NULL);
+    if (!hdl)
+        return -EBADF;
+
+    struct shim_mount * fs = hdl->fs;
+    put_handle(hdl);
+    return __do_statfs (fs, buf);
+}

+ 1 - 1
LibOS/shim/test/apps/lmbench/Makefile

@@ -70,7 +70,7 @@ regression: all
 	cp -f lmbench-regression $(LMBENCHDIR)/bin/linux
 	cd $(LMBENCHDIR)/bin/linux && \
 		env LOADER=./pal_loader OS=linux \
-		./lmbench-regression
+		./lmbench-regression 
 
 clean-lmbench:
 	$(MAKE) -C $(LMBENCHDIR) clean

+ 0 - 1
LibOS/shim/test/apps/ltp/BLOCKED

@@ -1,4 +1,3 @@
-chdir01
 chdir04
 epoll_wait01
 fcntl15

+ 12 - 0
LibOS/shim/test/apps/ltp/PASSED

@@ -16,6 +16,7 @@ asyncio02,4
 asyncio02,5
 asyncio02,6
 brk01,1
+chdir01,1
 chmod01,1
 chmod01,2
 chmod01,3
@@ -33,6 +34,7 @@ chmod02,6
 chmod02,7
 chmod02,8
 chmod03,1
+chmod04,1
 chown01,1
 chroot02,1
 clock_getres01,2
@@ -177,6 +179,10 @@ fstat01,1
 fstat01_64,1
 fstat03,1
 fstat03_64,1
+fstatat01,2
+fstatat01,4
+fstatat01,5
+fstatat01,6
 fsync01,1
 fsync03,1
 ftruncate01,1
@@ -277,6 +283,11 @@ memcpy01,3
 memset01,1
 memset01,2
 mkdir08,1
+mkdirat01,1
+mkdirat01,2
+mkdirat01,3
+mkdirat01,4
+mkdirat01,5
 mlock03,1
 mmap001,1
 mmap001,2
@@ -306,6 +317,7 @@ munmap02,1
 nanosleep01,1
 nanosleep03,1
 newuname01,1
+open01,2
 open03,1
 open09,1
 open09,2

+ 4 - 1
LibOS/shim/test/apps/ltp/TIMEOUTS

@@ -2,6 +2,7 @@ testcase,timeout
 alarm01,5
 alarm06,16
 clone05,30
+exit01,40
 faccessat01,80
 fchdir02,40
 fchmod07,40
@@ -22,15 +23,17 @@ pread01,40
 pread02,40
 preadv01,40
 read01,40
+readdir01,40
 readv01,40
 sendfile03_64,40
 setuid02,40
+sockioctl01,40
 sigaltstack02,40
 socket01,40
 socket02,40
 stat05_64,40
 syscall01,80
 wait401,40
-waitpid03,40
+waitpid03,80
 waitpid05,160
 write03,40

+ 14 - 4
LibOS/shim/test/regression/30_mmap.py

@@ -4,20 +4,30 @@ import os, sys, mmap
 from regression import Regression
 
 loader = sys.argv[1]
+try:
+    sgx = os.environ['SGX_RUN']
+except KeyError:
+    sgx = False
 
 # Running Bootstrap
 regression = Regression(loader, "mmap-file", None, 60000)
 
 regression.add_check(name="Private mmap beyond file range",
     check=lambda res: "mmap test 6 passed" in res[0].out and \
-                      "mmap test 7 passed" in res[0].out and \
-                      "mmap test 8 passed" in res[0].out)
+                      "mmap test 7 passed" in res[0].out)
 
 regression.add_check(name="Private mmap beyond file range (after fork)",
     check=lambda res: "mmap test 1 passed" in res[0].out and \
                       "mmap test 2 passed" in res[0].out and \
                       "mmap test 3 passed" in res[0].out and \
-                      "mmap test 4 passed" in res[0].out and \
-                      "mmap test 5 passed" in res[0].out)
+                      "mmap test 4 passed" in res[0].out)
 
+# On SGX, SIGBUS isn't always implemented correctly, for lack
+# of memory protection.  For now, some of these cases won't work.
+if not sgx:
+    regression.add_check(name="SIGBUS test",
+                         check=lambda res: "mmap test 5 passed" in res[0].out and \
+                         "mmap test 8 passed" in res[0].out)
+
+                         
 regression.run_checks()

+ 0 - 1
Pal/lib/crypto/adapters/mbedtls_adapter.c

@@ -195,4 +195,3 @@ int lib_RSAFreeKey(LIB_RSA_KEY *key)
     mbedtls_rsa_free(key);
     return 0;
 }
-

Some files were not shown because too many files changed in this diff