[Pvfs2-cvs] commit by vilayann in pvfs2-1/src/client/sysint: acache.c acache.h client-state-machine.h fs-add.sm initialize.c lookup-ncache.sm mgmt-create-dirent.sm mgmt-iterate-handles-list.sm ncache.c ncache.h remove.sm sys-create.sm sys-get-eattr.sm sys-getattr.sm sys-io.sm sys-lookup.sm sys-mkdir.sm sys-readdir.sm sys-remove.sm sys-rename.sm sys-setattr.sm sys-small-io.sm sys-symlink.sm

CVS commit program cvs at parl.clemson.edu
Wed Aug 9 16:17:34 EDT 2006


Update of /projects/cvsroot/pvfs2-1/src/client/sysint
In directory parlweb1:/tmp/cvs-serv7687/src/client/sysint

Modified Files:
      Tag: posix-extensions-branch
	acache.c acache.h client-state-machine.h fs-add.sm 
	initialize.c lookup-ncache.sm mgmt-create-dirent.sm 
	mgmt-iterate-handles-list.sm ncache.c ncache.h remove.sm 
	sys-create.sm sys-get-eattr.sm sys-getattr.sm sys-io.sm 
	sys-lookup.sm sys-mkdir.sm sys-readdir.sm sys-remove.sm 
	sys-rename.sm sys-setattr.sm sys-small-io.sm sys-symlink.sm 
Log Message:
Reverse merge changes from HEAD to posix-extensions-branch.



Index: acache.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/acache.c,v
diff -p -u -r1.27 -r1.27.2.1
--- acache.c	4 Apr 2006 04:47:09 -0000	1.27
+++ acache.c	9 Aug 2006 20:17:32 -0000	1.27.2.1
@@ -20,11 +20,13 @@
  */
   
 /* compile time defaults */
-#define ACACHE_DEFAULT_TIMEOUT_MSECS    5000
-#define ACACHE_DEFAULT_SOFT_LIMIT       5120
-#define ACACHE_DEFAULT_HARD_LIMIT      10240
-#define ACACHE_DEFAULT_RECLAIM_PERCENTAGE 25
-#define ACACHE_DEFAULT_REPLACE_ALGORITHM   LEAST_RECENTLY_USED
+enum {
+ACACHE_DEFAULT_TIMEOUT_MSECS = 5000,
+ACACHE_DEFAULT_SOFT_LIMIT    = 5120,
+ACACHE_DEFAULT_HARD_LIMIT    = 10240,
+ACACHE_DEFAULT_RECLAIM_PERCENTAGE = 25,
+ACACHE_DEFAULT_REPLACE_ALGORITHM = LEAST_RECENTLY_USED,
+};
 
 struct PINT_perf_key acache_keys[] = 
 {
@@ -36,6 +38,7 @@ struct PINT_perf_key acache_keys[] = 
    {"ACACHE_UPDATES", PERF_ACACHE_UPDATES, 0},
    {"ACACHE_PURGES", PERF_ACACHE_PURGES, 0},
    {"ACACHE_REPLACEMENTS", PERF_ACACHE_REPLACEMENTS, 0},
+   {"ACACHE_DELETIONS", PERF_ACACHE_DELETIONS, 0},
    {"ACACHE_ENABLED", PERF_ACACHE_ENABLED, PINT_PERF_PRESERVE},
    {NULL, 0, 0},
 };
@@ -305,9 +308,12 @@ void PINT_acache_invalidate(
                              &tmp_status);
     if(ret == 0)
     {
-        PINT_tcache_purge(acache, tmp_entry);
+        PINT_tcache_delete(acache, tmp_entry);
+        PINT_perf_count(acache_pc, PERF_ACACHE_DELETIONS, 1,
+                        PINT_PERF_ADD);
     }
 
+    /* set the new current number of entries */
     PINT_perf_count(acache_pc, PERF_ACACHE_NUM_ENTRIES,
                     acache->num_entries, PINT_PERF_SET);
 
@@ -371,7 +377,7 @@ int PINT_acache_update(
     struct PINT_tcache_entry* tmp_entry;
     struct acache_payload* tmp_payload;
     int status;
-    int removed;
+    int purged;
     unsigned int enabled;
 
     /* skip out immediately if the cache is disabled */
@@ -433,23 +439,31 @@ int PINT_acache_update(
         acache_free_payload(tmp_entry->payload);
         tmp_entry->payload = tmp_payload;
         ret = PINT_tcache_refresh_entry(acache, tmp_entry);
+        /* this counts as an update of an existing entry */
         PINT_perf_count(acache_pc, PERF_ACACHE_UPDATES, 1, PINT_PERF_ADD);
     }
     else
     {
         /* not found in cache; insert new payload*/
-        ret = PINT_tcache_insert_entry(acache, &refn, tmp_payload, &removed);
-        if(removed == 1)
+        ret = PINT_tcache_insert_entry(acache, &refn, tmp_payload, &purged);
+        /* the purged variable indicates how many entries had to be purged
+         * from the tcache to make room for this new one
+         */
+        if(purged == 1)
         {
-            /* assume an entry was replaced */
-            PINT_perf_count(acache_pc, PERF_ACACHE_REPLACEMENTS, removed,
+            /* since only one item was purged, we count this as one item being
+             * replaced rather than as a purge and an insert 
+             */
+            PINT_perf_count(acache_pc, PERF_ACACHE_REPLACEMENTS, purged, 
                 PINT_PERF_ADD);
         }
         else
         {
             /* otherwise we just purged as part of reclaimation */
-            /* NOTE: it is ok if the removed value happens to be zero */
-            PINT_perf_count(acache_pc, PERF_ACACHE_PURGES, removed,
+            /* if we didn't purge anything, then the "purged" variable will
+             * be zero and this counter call won't do anything.
+             */
+            PINT_perf_count(acache_pc, PERF_ACACHE_PURGES, purged,
                 PINT_PERF_ADD);
         }
     }

Index: acache.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/acache.h,v
diff -p -u -r1.11 -r1.11.6.1
--- acache.h	20 Dec 2005 00:08:25 -0000	1.11
+++ acache.h	9 Aug 2006 20:17:33 -0000	1.11.6.1
@@ -30,6 +30,8 @@
  *
  * Notes:
  * - See tcache for policy documentation
+ * - Note that the acache never explicitly deletes an entry.  Instead, it
+ *   will invalidate an entry but leave it in the cache.
  * .
  *
  * Operations that may retrieve items from acache:
@@ -56,7 +58,7 @@
  * - symlink
  * .
  *
- * Operations that may purge items from the cache:
+ * Operations that may invalidate items in the cache:
  * - remove
  * - rename
  * - io (size only)
@@ -74,12 +76,15 @@
 
 /** @see PINT_tcache_options */
 #define PINT_acache_options PINT_tcache_options
-#define ACACHE_TIMEOUT_MSECS TCACHE_TIMEOUT_MSECS 
-#define ACACHE_NUM_ENTRIES TCACHE_NUM_ENTRIES
-#define ACACHE_HARD_LIMIT TCACHE_HARD_LIMIT
-#define ACACHE_SOFT_LIMIT TCACHE_SOFT_LIMIT
-#define ACACHE_ENABLE TCACHE_ENABLE
-#define ACACHE_RECLAIM_PERCENTAGE TCACHE_RECLAIM_PERCENTAGE
+
+enum {
+ACACHE_TIMEOUT_MSECS = TCACHE_TIMEOUT_MSECS,
+ACACHE_NUM_ENTRIES = TCACHE_NUM_ENTRIES,
+ACACHE_HARD_LIMIT = TCACHE_HARD_LIMIT,
+ACACHE_SOFT_LIMIT = TCACHE_SOFT_LIMIT,
+ACACHE_ENABLE = TCACHE_ENABLE,
+ACACHE_RECLAIM_PERCENTAGE = TCACHE_RECLAIM_PERCENTAGE,
+};
 
 enum 
 {
@@ -91,7 +96,8 @@ enum 
    PERF_ACACHE_UPDATES = 5,
    PERF_ACACHE_PURGES = 6,
    PERF_ACACHE_REPLACEMENTS = 7,
-   PERF_ACACHE_ENABLED = 8,
+   PERF_ACACHE_DELETIONS = 8,
+   PERF_ACACHE_ENABLED = 9,
 };
 
 /** acache performance counter keys */

Index: client-state-machine.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/client-state-machine.h,v
diff -p -u -r1.158.2.4 -r1.158.2.5
--- client-state-machine.h	7 Jun 2006 03:20:38 -0000	1.158.2.4
+++ client-state-machine.h	9 Aug 2006 20:17:33 -0000	1.158.2.5
@@ -95,6 +95,8 @@ struct PINT_client_mkdir_sm
     PVFS_sysresp_mkdir *mkdir_resp; /* in/out parameter */
     PVFS_sys_attr sys_attr;         /* input parameter  */
 
+    PVFS_ds_keyval *key_array;
+    PVFS_ds_keyval *val_array;
     int retry_count;
     int stored_error_code;
     PVFS_handle metafile_handle;

Index: fs-add.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/fs-add.sm,v
diff -p -u -r1.1.2.1 -r1.1.2.2
--- fs-add.sm	7 Jun 2006 03:20:38 -0000	1.1.2.1
+++ fs-add.sm	9 Aug 2006 20:17:33 -0000	1.1.2.2
@@ -222,6 +222,7 @@ static int fs_add_parent_cleanup(
     PINT_client_sm *sm_p, job_status_s *js_p)
 {
     int ret = -PVFS_EINVAL;
+    PVFS_BMI_addr_t addr;
 
     if(js_p->error_code != 0)
     {
@@ -243,6 +244,16 @@ static int fs_add_parent_cleanup(
                  (void *)&sm_p->u.get_config.config->tcp_buffer_size_send);
     BMI_set_info(0, BMI_TCP_BUFFER_RECEIVE_SIZE, 
                  (void *)&sm_p->u.get_config.config->tcp_buffer_size_receive);
+    /*
+     * Force the connection to the config server down so future transfers
+     * will get the new buffer size.
+     */
+    ret = BMI_addr_lookup(&addr,
+                          sm_p->u.get_config.mntent->the_pvfs_config_server);
+    if (ret == 0 && 
+        sm_p->u.get_config.config->tcp_buffer_size_send != 0 &&
+        sm_p->u.get_config.config->tcp_buffer_size_receive != 0)
+        BMI_set_info(addr, BMI_TCP_CLOSE_SOCKET, NULL);
 
     /* 
       clear out all configuration information about file systems that
@@ -316,5 +327,5 @@ static int fs_add_parent_cleanup(
  *  c-basic-offset: 4
  * End:
  *
- * vim: ts=8 sts=4 sw=4 expandtab
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
  */

Index: initialize.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/initialize.c,v
diff -p -u -r1.99 -r1.99.6.1
--- initialize.c	20 Dec 2005 00:08:25 -0000	1.99
+++ initialize.c	9 Aug 2006 20:17:33 -0000	1.99.6.1
@@ -181,7 +181,6 @@ int PVFS_sys_initialize(uint64_t default
         gossip_lerr("Error initializing name lookup cache\n");
         goto error_exit;        
     }        
-    PINT_ncache_set_timeout(PINT_NCACHE_TIMEOUT_MS);
     client_status_flag |= CLIENT_NCACHE_INIT;
 
     /* initialize the server configuration manager */

Index: lookup-ncache.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/lookup-ncache.sm,v
diff -p -u -r1.13 -r1.13.8.1
--- lookup-ncache.sm	11 Nov 2005 21:30:59 -0000	1.13
+++ lookup-ncache.sm	9 Aug 2006 20:17:33 -0000	1.13.8.1
@@ -34,6 +34,13 @@
  *
  * TODO: sometimes we will get new attributes back with the lookup
  * response.  we should add these into the pcache as appropriate.
+ *
+ * TODO: This state machine does not handle resolving multiple segments.
+ * It simply tries to resolve the first segment of the path in the msgpair or
+ * sends the whole path to the msgpairarray_sm. This sm relies on sys-lookup 
+ * to handle its responses and server responses and keep up with how much of 
+ * the path has been resolved. That funcitonality might be better placed here 
+ * since all sys-lookup cares about is the final resolved handle.
  */
 
 #include <string.h>
@@ -85,7 +92,9 @@ static int lookup_ncache_lookup(PINT_cli
 {
     int ret = -PVFS_EINVAL;
     PVFS_object_ref parent_ref, object_ref;
-
+    char segment[PVFS_NAME_MAX + 1] = {0};
+    char* temp;
+    
     gossip_debug(GOSSIP_CLIENT_DEBUG, "lookup_ncache state: lookup\n");
 
     assert(js_p->error_code == 0);
@@ -95,10 +104,28 @@ static int lookup_ncache_lookup(PINT_cli
 
     assert(parent_ref.handle != PVFS_HANDLE_NULL);
     assert(parent_ref.fs_id != PVFS_FS_ID_NULL);
+    
+    /* Stripping out first segment for ncache lookup */
+    strncpy(segment,sm_p->msgpair.req.u.lookup_path.path,PVFS_NAME_MAX);
+
+    assert(segment[0] != '/');
+    temp = index(segment,'/');
+    if(temp != NULL)
+    {
+        temp[0] = '\0';
+    }
 
-    ret = PINT_ncache_lookup(
-        sm_p->u.lookup.orig_pathname, 0 /* sm_p->u.lookup.follow_link */,
-        parent_ref, &object_ref);
+    gossip_debug(GOSSIP_CLIENT_DEBUG, 
+                 "lookup_ncache state: "
+                 "lookup_ncache_lookup on segment [%s]\n",
+                 segment);
+
+    sm_p->ncache_hit = 0;
+
+    ret = PINT_ncache_get_cached_entry(
+                (const char*)segment, 
+                &object_ref,
+                (const PVFS_object_ref*) &parent_ref);
 
     if (ret == 0)
     {

Index: mgmt-create-dirent.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/mgmt-create-dirent.sm,v
diff -p -u -r1.10.8.1 -r1.10.8.2
--- mgmt-create-dirent.sm	7 Jun 2006 03:20:38 -0000	1.10.8.1
+++ mgmt-create-dirent.sm	9 Aug 2006 20:17:33 -0000	1.10.8.2
@@ -188,10 +188,7 @@ static int mgmt_create_dirent_setup_msgp
         sm_p->u.mgmt_create_dirent.entry,
         sm_p->u.mgmt_create_dirent.entry_handle,
         sm_p->parent_ref.handle,
-        sm_p->parent_ref.fs_id,
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->parent_ref.fs_id);
 
     msg_p->fs_id = sm_p->parent_ref.fs_id;
     msg_p->handle = sm_p->u.mgmt_create_dirent.entry_handle;

Index: mgmt-iterate-handles-list.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/mgmt-iterate-handles-list.sm,v
diff -p -u -r1.24.12.1 -r1.24.12.2
--- mgmt-iterate-handles-list.sm	7 Jun 2006 03:20:38 -0000	1.24.12.1
+++ mgmt-iterate-handles-list.sm	9 Aug 2006 20:17:33 -0000	1.24.12.2
@@ -313,5 +313,5 @@ static int iterate_handles_list_comp_fn(
  *  c-basic-offset: 4
  * End:
  *
- * vim: ts=8 sts=4 sw=4 expandtab
+ * vim: ft=c ts=8 sts=4 sw=4 expandtab
  */

Index: ncache.c
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/ncache.c,v
diff -p -u -r1.11.8.1 -r1.11.8.2
--- ncache.c	7 Jun 2006 03:20:38 -0000	1.11.8.1
+++ ncache.c	9 Aug 2006 20:17:33 -0000	1.11.8.2
@@ -1,594 +1,522 @@
 /*
- * (C) 2001 Clemson University and The University of Chicago
+ * Copyright © Acxiom Corporation, 2006
  *
  * See COPYING in top-level directory.
  */
-
-/* PVFS directory cache implementation */
-
+  
 #include <assert.h>
+  
+#include "pvfs2-attr.h"
 #include "ncache.h"
+#include "tcache.h"
+#include "pint-util.h"
+#include "pvfs2-debug.h"
+#include "gossip.h"
 #include "pvfs2-internal.h"
-
-typedef struct
-{
-    PVFS_object_ref parent;       /* parent directory */
-    char name[PVFS_SEGMENT_MAX];  /* segment name */
-    PVFS_object_ref entry;        /* entry in parent */
-    struct timeval tstamp_valid;  /* timestamp of validity period */
-    int abs_resolved;             /* if this entry is a symlink, is it
-                                     the resolved object, or the
-                                     symlink object itself? */
-} ncache_entry;
-
-struct ncache_t
-{
-    ncache_entry dentry;
-    int prev;
-    int next;
-    int status;        /*whether the entry is in use or not*/
+#include <string.h>
+  
+/** \file
+ *  \ingroup ncache
+ * Implementation of the Name Cache (ncache) component.
+ */
+  
+/* compile time defaults */
+enum {
+NCACHE_DEFAULT_TIMEOUT_MSECS  =  3000,
+NCACHE_DEFAULT_SOFT_LIMIT     =  5120,
+NCACHE_DEFAULT_HARD_LIMIT     = 10240,
+NCACHE_DEFAULT_RECLAIM_PERCENTAGE = 25,
+NCACHE_DEFAULT_REPLACE_ALGORITHM = LEAST_RECENTLY_USED,
 };
 
-/* Cache Management structure */
-typedef struct
+struct PINT_perf_key ncache_keys[] = 
 {
-    struct ncache_t element[PINT_NCACHE_MAX_ENTRIES];
-    int count;
-    int top;
-    int bottom;
-    gen_mutex_t *mt_lock;
-} ncache;
-
-#define BAD_LINK -1
-#define STATUS_UNUSED 0
-#define STATUS_USED 1
-
-/* uncomment to enable ncache */
-/* #define ENABLE_NCACHE 1 */
-
-#ifdef ENABLE_NCACHE
-static void ncache_remove_dentry(int item);
-static void ncache_rotate_dentry(int item);
-static int ncache_get_lru(void);
-static int ncache_update_dentry_timestamp(
-    ncache_entry* entry); 
-static int ncache_add_dentry(
-    char *name,
-    int abs_resolved,
-    PVFS_object_ref parent,
-    PVFS_object_ref entry);
-
-static ncache *cache = NULL;
-#endif
-
-static int s_pint_ncache_timeout_ms = PINT_NCACHE_TIMEOUT_MS;
+   {"NCACHE_NUM_ENTRIES", PERF_NCACHE_NUM_ENTRIES, PINT_PERF_PRESERVE},
+   {"NCACHE_SOFT_LIMIT", PERF_NCACHE_SOFT_LIMIT, PINT_PERF_PRESERVE},
+   {"NCACHE_HARD_LIMIT", PERF_NCACHE_HARD_LIMIT, PINT_PERF_PRESERVE},
+   {"NCACHE_HITS", PERF_NCACHE_HITS, 0},
+   {"NCACHE_MISSES", PERF_NCACHE_MISSES, 0},
+   {"NCACHE_UPDATES", PERF_NCACHE_UPDATES, 0},
+   {"NCACHE_PURGES", PERF_NCACHE_PURGES, 0},
+   {"NCACHE_REPLACEMENTS", PERF_NCACHE_REPLACEMENTS, 0},
+   {"NCACHE_DELETIONS", PERF_NCACHE_DELETIONS, 0},
+   {"NCACHE_ENABLED", PERF_NCACHE_ENABLED, PINT_PERF_PRESERVE},
+   {NULL, 0, 0},
+};
 
-#ifdef ENABLE_NCACHE
-/* compare
- *
- * compares a ncache entry to the search key
- *
- * returns 1 on an equal comparison (match), 0 otherwise
- */
-static inline int compare(
-    struct ncache_t element,
-    char *name,
-    int abs_resolved,
-    PVFS_object_ref refn)
+/* data to be stored in a cached entry */
+struct ncache_payload
 {
-    int ret = 0, len = 0;
-
-    if ((element.dentry.parent.handle == refn.handle) &&
-        (element.dentry.parent.fs_id == refn.fs_id) &&
-        (element.dentry.abs_resolved == abs_resolved))
-    {
-        int len1 = strlen(name);
-        int len2 = strlen(element.dentry.name);
-
-        if (len1 == len2)
-        {
-            len = ((len1 < len2) ? len1 : len2);
-            ret = (strncmp(name, element.dentry.name, len) == 0);
-        }
-    }
-    return ret;
-}
-
-/* check_dentry_expiry
- *
- * need to validate the dentry against the timestamp
- *
- * returns 0 if dentry timestamp is valid, -PVFS_errno if dentry is
- * expired
- */
-static inline int check_dentry_expiry(struct timeval time_stamp)
-{
-    int ret = 0;
-    struct timeval cur_time;
-
-    ret = gettimeofday(&cur_time,NULL);
-    if (ret == 0)
-    {
-        /* does timestamp exceed current time?  if so, entry is valid */
-        ret = (((time_stamp.tv_sec > cur_time.tv_sec) ||
-                ((time_stamp.tv_sec == cur_time.tv_sec) &&
-                 (time_stamp.tv_usec > cur_time.tv_usec))) ? 0 : -1);
-    }
-    return ret;
-}
-#endif  /* ENABLE_NCACHE */
+    PVFS_object_ref entry_ref;      /* PVFS2 object reference to entry */
+    PVFS_object_ref parent_ref;     /* PVFS2 object reference to parent */
+    int entry_status;               /* is the entry valid? */
+    char* entry_name;
+};
 
-/* ncache_lookup
- *
- * search PVFS directory cache for specific entry
- *
- * returns 0 on success, -PVFS_errno on failure,
- * -PVFS_ENOENT if entry is not present.
- */
-int PINT_ncache_lookup(
-    char *name,
-    int want_resolved,
-    PVFS_object_ref parent,
-    PVFS_object_ref *entry)
+struct ncache_key
 {
-#ifdef ENABLE_NCACHE
-    int ret = -PVFS_EINVAL, i = 0;
-
-    if (!name || !entry)
-    {
-        return ret;
-    }
-
-    gossip_debug(GOSSIP_NCACHE_DEBUG, "PINT_ncache_lookup called on "
-                 "segment %s\n\tunder %llu,%d [%d]\n", name,
-                 llu(parent.handle), parent.fs_id, want_resolved);
-
-    gen_mutex_lock(cache->mt_lock);
-    entry->handle = PINT_NCACHE_HANDLE_INVALID;
-
-    for(i = cache->top; i != BAD_LINK; i = cache->element[i].next)
-    {
-        if (compare(cache->element[i],name,want_resolved,parent))
-        {
-            /* match found; check to see if it is still valid */
-            ret = check_dentry_expiry(
-                cache->element[i].dentry.tstamp_valid);
-
-            if (ret < 0)
-            {
-                /* entry is stale, remove from cache */
-                gossip_debug(GOSSIP_NCACHE_DEBUG,
-                             "ncache entry expired.\n");
-                ncache_remove_dentry(i);
-
-                /* we never have more than one entry for the same
-                 * object in the cache, so we can assume we have no
-                 * up-to-date one at this point.
-                 */
-                gen_mutex_unlock(cache->mt_lock);
-                return -PVFS_ENOENT;
-            }
-            gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache entry valid.\n");
-
-            /*
-              update links so that this dentry is at the top of our
-              list; update the time stamp on the ncache entry
-            */
-            ncache_rotate_dentry(i);
-            ret = ncache_update_dentry_timestamp(
-                &cache->element[i].dentry);
-            if (ret < 0)
-            {
-                gen_mutex_unlock(cache->mt_lock);
-                return -PVFS_ENOENT;
-            }
-
-            entry->handle = cache->element[i].dentry.entry.handle;
-            entry->fs_id = cache->element[i].dentry.entry.fs_id;        
-            gen_mutex_unlock(cache->mt_lock);
-            return 0;
-        }
-    }
-
-    /* passed through entire cache with no matches */
-    gen_mutex_unlock(cache->mt_lock);
-    return -PVFS_ENOENT;
-#else
-    return -PVFS_ENOENT;
-#endif
-}
-
-/* ncache_rotate_dentry()
- *
- * moves the specified item to the top of the ncache linked list to prevent it
- * from being identified as the least recently used item in the cache.
- *
- * no return value
+    PVFS_object_ref parent_ref;
+    char* entry_name;
+};
+  
+static struct PINT_tcache* ncache = NULL;
+static gen_mutex_t ncache_mutex = GEN_MUTEX_INITIALIZER;
+  
+static int ncache_compare_key_entry(void* key, struct qhash_head* link);
+static int ncache_hash_key(void* key, int table_size);
+static int ncache_free_payload(void* payload);
+static struct PINT_perf_counter* ncache_pc = NULL;
+
+/**
+ * Enables perf counter instrumentation of the ncache
+ */
+void PINT_ncache_enable_perf_counter(
+    struct PINT_perf_counter* pc)     /**< perf counter instance to use */
+{
+    gen_mutex_lock(&ncache_mutex);
+
+    ncache_pc = pc;
+    assert(ncache_pc);
+
+    /* set initial values */
+    PINT_perf_count(ncache_pc, PERF_NCACHE_SOFT_LIMIT,
+        ncache->soft_limit, PINT_PERF_SET);
+    PINT_perf_count(ncache_pc, PERF_NCACHE_HARD_LIMIT,
+        ncache->hard_limit, PINT_PERF_SET);
+    PINT_perf_count(ncache_pc, PERF_NCACHE_ENABLED,
+        ncache->enable, PINT_PERF_SET);
+
+    gen_mutex_unlock(&ncache_mutex);
+
+    return;
+}
+
+/**
+ * Initializes the ncache 
+ * \return pointer to tcache on success, NULL on failure
  */
-#ifdef ENABLE_NCACHE
-static void ncache_rotate_dentry(int item)
+int PINT_ncache_initialize(void)
 {
-    int prev = 0, next = 0, new_bottom;
-
-    if (cache->top != cache->bottom) 
-    {
-        if (cache->top != item)
-        {
-            /*
-              only move links if there's more than one thing in the
-              list
-            */
-            if (cache->bottom == item)
-            {
-                new_bottom = cache->element[cache->bottom].prev;
-
-                cache->element[new_bottom].next = BAD_LINK;
-                cache->bottom = new_bottom;
-            }
-            else
-            {
-                /*somewhere in the middle*/
-                next = cache->element[item].next;
-                prev = cache->element[item].prev;
-
-                cache->element[prev].next = next;
-                cache->element[next].prev = prev;
-            }
-
-            cache->element[cache->top].prev = item;
-
-            cache->element[item].next = cache->top;
-            cache->element[item].prev = BAD_LINK;
-            cache->top = item;
+    int ret = -1;
+  
+    gen_mutex_lock(&ncache_mutex);
+  
+    /* create tcache instance */
+    ncache = PINT_tcache_initialize(ncache_compare_key_entry,
+                                    ncache_hash_key,
+                                    ncache_free_payload,
+                                    -1 /* default tcache table size */);
+    if(!ncache)
+    {
+        gen_mutex_unlock(&ncache_mutex);
+        return(-PVFS_ENOMEM);
+    }
+  
+    /* fill in defaults that are specific to ncache */
+    ret = PINT_tcache_set_info(ncache, TCACHE_TIMEOUT_MSECS,
+                               NCACHE_DEFAULT_TIMEOUT_MSECS);
+    if(ret < 0)
+    {
+        PINT_tcache_finalize(ncache);
+        gen_mutex_unlock(&ncache_mutex);
+        return(ret);
+    }
+    ret = PINT_tcache_set_info(ncache, TCACHE_HARD_LIMIT, 
+                               NCACHE_DEFAULT_HARD_LIMIT);
+    if(ret < 0)
+    {
+        PINT_tcache_finalize(ncache);
+        gen_mutex_unlock(&ncache_mutex);
+        return(ret);
+    }
+    ret = PINT_tcache_set_info(ncache, TCACHE_SOFT_LIMIT, 
+                               NCACHE_DEFAULT_SOFT_LIMIT);
+    if(ret < 0)
+    {
+        PINT_tcache_finalize(ncache);
+        gen_mutex_unlock(&ncache_mutex);
+        return(ret);
+    }
+    ret = PINT_tcache_set_info(ncache, TCACHE_RECLAIM_PERCENTAGE,
+                               NCACHE_DEFAULT_RECLAIM_PERCENTAGE);
+    if(ret < 0)
+    {
+        PINT_tcache_finalize(ncache);
+        gen_mutex_unlock(&ncache_mutex);
+        return(ret);
+    }
+  
+    gen_mutex_unlock(&ncache_mutex);
+    return(0);
+}
+  
+/** Finalizes and destroys the ncache, frees all cached entries */
+void PINT_ncache_finalize(void)
+{
+    gen_mutex_lock(&ncache_mutex);
+
+    assert(ncache != NULL);
+    PINT_tcache_finalize(ncache);
+    ncache = NULL;
+
+    gen_mutex_unlock(&ncache_mutex);
+    return;
+}
+  
+/**
+ * Retrieves parameters from the ncache 
+ * @see PINT_tcache_options
+ * \return 0 on success, -PVFS_error on failure
+ */
+int PINT_ncache_get_info(
+    enum PINT_ncache_options option, /**< option to read */
+    unsigned int* arg)               /**< output value */
+{
+    int ret = -1;
+  
+    gen_mutex_lock(&ncache_mutex);
+    ret = PINT_tcache_get_info(ncache, option, arg);
+    gen_mutex_unlock(&ncache_mutex);
+  
+    return(ret);
+}
+  
+/**
+ * Sets optional parameters in the ncache
+ * @see PINT_tcache_options
+ * @return 0 on success, -PVFS_error on failure
+ */
+int PINT_ncache_set_info(
+    enum PINT_ncache_options option, /**< option to modify */
+    unsigned int arg)                /**< input value */
+{
+    int ret = -1;
+  
+    gen_mutex_lock(&ncache_mutex);
+    ret = PINT_tcache_set_info(ncache, option, arg);
+
+    /* record any resulting parameter changes */
+    PINT_perf_count(ncache_pc, PERF_NCACHE_SOFT_LIMIT,
+        ncache->soft_limit, PINT_PERF_SET);
+    PINT_perf_count(ncache_pc, PERF_NCACHE_HARD_LIMIT,
+        ncache->hard_limit, PINT_PERF_SET);
+    PINT_perf_count(ncache_pc, PERF_NCACHE_ENABLED,
+        ncache->enable, PINT_PERF_SET);
+    PINT_perf_count(ncache_pc, PERF_NCACHE_NUM_ENTRIES,
+        ncache->num_entries, PINT_PERF_SET);
+
+    gen_mutex_unlock(&ncache_mutex);
+
+    return(ret);
+}
+  
+/** 
+ * Retrieves a _copy_ of a cached object reference, and reports the
+ * status to indicate if they are valid or  not
+ * @return 0 on success, -PVFS_error on failure
+ */
+int PINT_ncache_get_cached_entry(
+    const char* entry,                 /**< path of obect to look up*/
+    PVFS_object_ref* entry_ref,        /**< PVFS2 object looked up */
+    const PVFS_object_ref* parent_ref) /**< Parent of PVFS2 object */
+{
+    int ret = -1;
+    struct PINT_tcache_entry* tmp_entry;
+    struct ncache_payload* tmp_payload;
+    struct ncache_key entry_key;
+    int status;
+
+    gossip_debug(GOSSIP_NCACHE_DEBUG, 
+                 "ncache: get_cached_entry(): [%s]\n",entry);
+  
+    entry_key.entry_name = (char *) entry;
+    entry_key.parent_ref.handle = parent_ref->handle;
+    entry_key.parent_ref.fs_id = parent_ref->fs_id;
+
+    gen_mutex_lock(&ncache_mutex);
+
+    /* lookup entry */
+    ret = PINT_tcache_lookup(ncache, (void *) &entry_key, &tmp_entry, &status);
+    if(ret < 0 || status != 0)
+    {
+        gossip_debug(GOSSIP_NCACHE_DEBUG, 
+            "ncache: miss: name=[%s]\n", entry_key.entry_name);
+        PINT_perf_count(ncache_pc, PERF_NCACHE_MISSES, 1, PINT_PERF_ADD);
+        gen_mutex_unlock(&ncache_mutex);
+        /* Return -PVFS_ENOENT if the entry has expired */
+        if(status != 0)
+        {   
+            return(-PVFS_ENOENT);
         }
+        return(ret);
     }
-}
-#endif
-
-/* ncache_insert
- *
- * insert an entry into PVFS directory cache
- *
- * returns 0 on success, -1 on failure
- */
-int PINT_ncache_insert(
-    char *name,
-    int abs_resolved,
-    PVFS_object_ref entry,
-    PVFS_object_ref parent)
-{
-#ifdef ENABLE_NCACHE
-    int i = 0, index = 0, ret = 0;
-    unsigned char entry_found = 0;
-        
-    gen_mutex_lock(cache->mt_lock);
-
-    gossip_debug(
-        GOSSIP_NCACHE_DEBUG, "PINT_ncache_insert: inserting segment "
-        "%s\n\t(%llu,%d) under parent (%llu,%d) [%d]\n", name,
-        llu(entry.handle), entry.fs_id, llu(parent.handle),
-        parent.fs_id, abs_resolved);
-
-    for (i = cache->top; i != BAD_LINK; i = cache->element[i].next)
-    {
-        if (compare(cache->element[i],name,abs_resolved,parent))
-        {
-            entry_found = 1;
-            index = i;
-            break;
-        }
-    }
-        
-    /* add/merge element to the cache */
-    if (entry_found == 0)
-    {
-        /* Element not in cache, add it */
-        ncache_add_dentry(name,abs_resolved,parent,entry);
+    tmp_payload = tmp_entry->payload;
+  
+    gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: status=%d, entry_status=%d\n",
+                 status, tmp_payload->entry_status);
+
+    /* copy out entry ref if valid */
+    if(tmp_payload->entry_status == 0 && 
+       tmp_payload->parent_ref.handle == parent_ref->handle)
+    {
+        gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: copying out ref.\n");
+        *entry_ref = tmp_payload->entry_ref;
+    }
+  
+    if(tmp_payload->entry_status == 0) 
+    {
+        /* return success if we got _anything_ out of the cache */
+        PINT_perf_count(ncache_pc, PERF_NCACHE_HITS, 1, PINT_PERF_ADD);
+        gen_mutex_unlock(&ncache_mutex);
+        return(0);
+    }
+
+    gen_mutex_unlock(&ncache_mutex);
+  
+    PINT_perf_count(ncache_pc, PERF_NCACHE_MISSES, 1, PINT_PERF_ADD);
+    return(-PVFS_ETIME);
+}
+  
+/**
+ * Invalidates a cache entry (if present)
+ */
+void PINT_ncache_invalidate(
+    const char* entry,                  /**< path of obect */
+    const PVFS_object_ref* parent_ref)  /**< Parent of PVFS2 object */
+{
+    int ret = -1;
+    struct PINT_tcache_entry* tmp_entry;
+    struct ncache_key entry_key;
+    int tmp_status;
+  
+    gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: invalidate(): entry=%s\n",
+                 entry);
+  
+    gen_mutex_lock(&ncache_mutex);
+  
+    entry_key.entry_name = (char *) entry;
+    entry_key.parent_ref.handle = parent_ref->handle;
+    entry_key.parent_ref.fs_id = parent_ref->fs_id;
+
+    /* find out if the entry is in the cache */
+    ret = PINT_tcache_lookup(ncache, 
+                             &entry_key,
+                             &tmp_entry,
+                             &tmp_status);
+    if(ret == 0)
+    {
+        PINT_tcache_delete(ncache, tmp_entry);
+        PINT_perf_count(ncache_pc, PERF_NCACHE_DELETIONS, 1,
+                        PINT_PERF_ADD);
+    }
+
+    PINT_perf_count(ncache_pc, PERF_NCACHE_NUM_ENTRIES,
+                    ncache->num_entries, PINT_PERF_SET);
+
+    gen_mutex_unlock(&ncache_mutex);
+    return;
+}
+  
+/** 
+ * Adds a name to the cache, or updates it if already present.  
+ * The given name is _copied_ into the cache.   
+ *
+ * \note NOTE: All previous information for the object will be discarded,
+ * even if there is still time remaining before it expires.
+ *
+ * \return 0 on success, -PVFS_error on failure
+ */
+int PINT_ncache_update(
+    const char* entry,                     /**< entry to update */
+    const PVFS_object_ref* entry_ref,      /**< entry ref to update */
+    const PVFS_object_ref* parent_ref)     /**< parent ref to update */
+{
+    int ret = -1;
+    struct PINT_tcache_entry* tmp_entry;
+    struct ncache_payload* tmp_payload;
+    struct ncache_key entry_key;
+    int status;
+    int purged;
+    unsigned int enabled;
+
+    /* skip out immediately if the cache is disabled */
+    PINT_tcache_get_info(ncache, TCACHE_ENABLE, &enabled);
+    if(!enabled)
+    {
+        return(0);
+    }
+    
+    gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: update(): name [%s]\n",entry);
+  
+    if(!entry_ref->handle)
+    {
+        return(-PVFS_EINVAL);
+    }
+  
+    /* create new payload with updated information */
+    tmp_payload = (struct ncache_payload*) 
+                        calloc(1,sizeof(struct ncache_payload));
+    if(tmp_payload == NULL)
+    {
+        return(-PVFS_ENOMEM);
+    }
+
+    tmp_payload->parent_ref.handle = parent_ref->handle;
+    tmp_payload->parent_ref.fs_id = parent_ref->fs_id;
+    tmp_payload->entry_ref.handle = entry_ref->handle;
+    tmp_payload->entry_ref.fs_id = entry_ref->fs_id;
+
+    tmp_payload->entry_status = 0;
+    tmp_payload->entry_name = (char*) calloc(1, strlen(entry) + 1);
+    if(tmp_payload->entry_name == NULL)
+    {
+        free(tmp_payload);
+        return(-PVFS_ENOMEM);
+    }
+    memcpy(tmp_payload->entry_name, entry, strlen(entry) + 1);
+
+    gen_mutex_lock(&ncache_mutex);
+
+    entry_key.entry_name = (char *) entry;
+    entry_key.parent_ref.handle = parent_ref->handle;
+    entry_key.parent_ref.fs_id = parent_ref->fs_id;
+
+    /* find out if the entry is already in the cache */
+    ret = PINT_tcache_lookup(ncache, 
+                             &entry_key,
+                             &tmp_entry,
+                             &status);
+    if(ret == 0)
+    {
+        /* found match in cache; destroy old payload, replace, and
+         * refresh time stamp
+         */
+        ncache_free_payload(tmp_entry->payload);
+        tmp_entry->payload = tmp_payload;
+        ret = PINT_tcache_refresh_entry(ncache, tmp_entry);
+        PINT_perf_count(ncache_pc, PERF_NCACHE_UPDATES, 1, PINT_PERF_ADD);
     }
     else
     {
-        /* move entry to the top of the list and update its timestamp */
-        gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: inserting entry "
-                     "already present; timestamp update.\n");
-
-        ncache_rotate_dentry(index);
-        ret = ncache_update_dentry_timestamp(
-            &cache->element[index].dentry); 
-        if (ret < 0)
-        {
-            gen_mutex_unlock(cache->mt_lock);
-            return(ret);
-        }
-    }
-    gen_mutex_unlock(cache->mt_lock);
-#endif
-    return 0;
-}
-
-/* ncache_remove
- *
- * remove a particular entry from the PVFS directory cache
- *
- * returns 0 on success, -1 on failure
- */
-int PINT_ncache_remove(
-    char *name,
-    int abs_resolved,
-    PVFS_object_ref parent,
-    int *item_found)
-{
-#ifdef ENABLE_NCACHE
-    int i = 0;
-
-    if (!name)
-    {
-        return -PVFS_EINVAL;
-    }
-
-    if (item_found)
-    {
-        *item_found = 0;
-    }
-
-    gen_mutex_lock(cache->mt_lock);
-    for(i = cache->top; i != BAD_LINK; i = cache->element[i].next)
-    {
-        if (compare(cache->element[i],name,abs_resolved,parent))
+        /* not found in cache; insert new payload*/
+        ret = PINT_tcache_insert_entry(ncache, 
+                                       &entry_key,
+                                       tmp_payload, 
+                                       &purged);
+        /* the purged variable indicates how many entries had to be purged
+         * from the tcache to make room for this new one
+         */
+        if(purged == 1)
         {
-            ncache_remove_dentry(i);
-
-            if (item_found)
-            {
-                *item_found = 1;
-            }
-            break;
+            /* since only one item was purged, we count this as one item being
+             * replaced rather than as a purge and an insert
+             */
+            PINT_perf_count(ncache_pc, PERF_NCACHE_REPLACEMENTS,purged,
+                PINT_PERF_ADD);
         }
-    }
-    gen_mutex_unlock(cache->mt_lock);
-#endif
-    return 0;
-}
-
-/* ncache_flush
- * 
- * remove all entries from the PVFS directory cache
- *
- * returns 0 on success, -1 on failure
- */
-int PINT_ncache_flush(void)
-{
-    return -PVFS_ENOSYS;
-}
-
-/* pint_ncache_initialize
- *
- * initialize the PVFS directory cache
- *
- * returns 0 on success, -1 on failure
- */
-int PINT_ncache_initialize(void)
-{
-#ifdef ENABLE_NCACHE
-    int ret = 0, i = 0;
-
-    if (cache == NULL)
-    {
-        cache = (ncache*)malloc(sizeof(ncache));
-        if (cache)
+        else
         {
-            cache->mt_lock = gen_mutex_build();
-            cache->top = BAD_LINK;
-            cache->bottom = 0;
-            cache->count = 0;
-
-            for(i = 0;i < PINT_NCACHE_MAX_ENTRIES; i++)
-            {
-                cache->element[i].prev = BAD_LINK;
-                cache->element[i].next = BAD_LINK;
-                cache->element[i].status = STATUS_UNUSED;
-            }
+            /* otherwise we just purged as part of reclaimation */
+            /* if we didn't purge anything, then the "purged" variable will
+             * be zero and this counter call won't do anything.
+             */
+            PINT_perf_count(ncache_pc, PERF_NCACHE_PURGES, purged,
+                PINT_PERF_ADD);
         }
-        ret = (cache ? 0 : -PVFS_ENOMEM);
-    }
-
-    gossip_debug(GOSSIP_NCACHE_DEBUG,
-                 "PINT_ncache_initialize returning %d\n", ret);
-    return ret;
-#else
-    return 0;
-#endif
-}
-
-/* pint_ncache_finalize
- *
- * close down the PVFS directory cache framework
- *
- * returns 0
- */
-int PINT_ncache_finalize(void)
-{
-#ifdef ENABLE_NCACHE
-
-    if (cache)
-    {
-        gen_mutex_destroy(cache->mt_lock);
-        free(cache);
-        cache = NULL;
-    }
-
-    gossip_debug(GOSSIP_NCACHE_DEBUG, "PINT_ncache_finalize complete\n");
-#endif
-    return 0;
-}
-
-int PINT_ncache_get_timeout(void)
-{
-    return s_pint_ncache_timeout_ms;
-}
-
-void PINT_ncache_set_timeout(int max_timeout_ms)
-{
-    s_pint_ncache_timeout_ms = max_timeout_ms;
-}
-
-
-/* ncache_add_dentry
- *
- * add a dentry to the ncache
- *
- * returns 0 on success, -PVFS_errno on failure
- */
-#ifdef ENABLE_NCACHE
-static int ncache_add_dentry(
-    char *name,
-    int abs_resolved,
-    PVFS_object_ref parent,
-    PVFS_object_ref entry)
-{
-    int new = 0, ret = 0;
-    int size = strlen(name) + 1; /* size includes null terminator*/
-
-    new = ncache_get_lru();
-
-    /* add element to cache */
-    cache->element[new].status = STATUS_USED;
-    cache->element[new].dentry.parent = parent;
-    cache->element[new].dentry.entry = entry;
-    cache->element[new].dentry.abs_resolved = abs_resolved;
-    memcpy(cache->element[new].dentry.name,name,size);
-
-    /* set timestamp */
-    ret = ncache_update_dentry_timestamp(
-        &cache->element[new].dentry);
-
-    if (ret < 0)
-    {
-        return ret;
     }
-    cache->element[new].prev = BAD_LINK;
-    cache->element[new].next = cache->top;
-
-    /* make previous element point to new entry */
-    if (cache->top != BAD_LINK)
+    
+    PINT_perf_count(ncache_pc, PERF_NCACHE_NUM_ENTRIES,
+        ncache->num_entries, PINT_PERF_SET);
+
+    gen_mutex_unlock(&ncache_mutex);
+  
+    /* cleanup if we did not succeed for some reason */
+    if(ret < 0)
+    {
+        ncache_free_payload(tmp_payload);
+    }
+  
+    gossip_debug(GOSSIP_NCACHE_DEBUG, "ncache: update(): return=%d\n", ret);
+    return(ret);
+}
+  
+/* ncache_compare_key_entry()
+ *
+ * compares an opaque key (char* in this case) against a payload to see
+ * if there is a match
+ *
+ * returns 1 on match, 0 otherwise
+ */
+static int ncache_compare_key_entry(void* key, struct qhash_head* link)
+{
+    struct ncache_key* real_key = (struct ncache_key*)key;
+    struct ncache_payload* tmp_payload = NULL;
+    struct PINT_tcache_entry* tmp_entry = NULL;
+  
+    tmp_entry = qhash_entry(link, struct PINT_tcache_entry, hash_link);
+    assert(tmp_entry);
+
+    tmp_payload = (struct ncache_payload*)tmp_entry->payload;
+     /* If the following aren't equal, we know we don't have a match... Maybe
+     * these integer comparisons will be quicker than a strcmp each time?
+     *   - parent_ref.handle 
+     *   - parent_ref.fs_id
+     *   - entry_name length
+     */
+    if( real_key->parent_ref.handle  != tmp_payload->parent_ref.handle ||
+        real_key->parent_ref.fs_id   != tmp_payload->parent_ref.fs_id  ||
+        strlen(real_key->entry_name) != strlen(tmp_payload->entry_name) )
     {
-        cache->element[cache->top].prev = new;
+        /* One of the above cases failed, so we know these aren't a match */
+        return(0);
     }
-    cache->top = new;
-    return 0;
-}
-
-/* ncache_get_lru
- *
- * this function gets the least recently used cache entry (assuming a
- * full cache) or searches through the cache for the first unused slot
- * (if there are some free slots)
- *
- * returns 0 on success, -PVFS_errno on failure
- */
-static int ncache_get_lru(void)
-{
-    int new = 0, i = 0;
-
-    if (cache->count == PINT_NCACHE_MAX_ENTRIES)
+    
+    if( strcmp(real_key->entry_name, tmp_payload->entry_name) == 0 )
     {
-        new = cache->bottom;
-        cache->bottom = cache->element[new].prev;
-        cache->element[cache->bottom].next = BAD_LINK;
-        return new;
+        /* The strings matches */
+        return(1);
     }
-    else
-    {
-        for(i = 0; i < PINT_NCACHE_MAX_ENTRIES; i++)
-        {
-            if (cache->element[i].status == STATUS_UNUSED)
-            {
-                cache->count++;
-                return i;
-            }
-        }
-    }
-
-    gossip_debug(GOSSIP_NCACHE_DEBUG,
-                  "error getting least recently used dentry.\n");
-    gossip_debug(GOSSIP_NCACHE_DEBUG,
-                  "cache->count = %d max_entries = %d.\n",
-                  cache->count, PINT_NCACHE_MAX_ENTRIES);
 
-    return -PVFS_ENOENT;
+    return(0);
 }
-
-/* ncache_remove_dentry
+  
+/* ncache_hash_key()
  *
- * Handles the actual manipulation of the cache to handle removal
+ * hash function for character pointers
  *
- * returns nothing
+ * returns hash index 
  */
-static void ncache_remove_dentry(int item)
+static int ncache_hash_key(void* key, int table_size)
 {
-    int prev = 0,next = 0;
-
-    cache->element[item].status = STATUS_UNUSED;
-    memset(&cache->element[item].dentry.name, 0, PVFS_SEGMENT_MAX);
-    cache->count--;
-
-    /* if there's exactly one item in the list, just get rid of it*/
-    if (cache->top == cache->bottom)
-    {
-        cache->top = 0;
-        cache->bottom = 0;
-        cache->element[item].prev = BAD_LINK;
-        cache->element[item].next = BAD_LINK;
-        return;
-    }
+    struct ncache_key* real_key = (struct ncache_key*) key;
+    int tmp_ret = 0;
+    unsigned int sum = 0, i = 0;
 
-    /* depending on where the dentry is in the list, we have to do
-     * different things if its the first, last, or somewhere in the
-     * middle.
-     */
-    if (item == cache->top)
-    {
-        /* Adjust top */
-        cache->top = cache->element[item].next;
-        cache->element[cache->top].prev = BAD_LINK;
-    }
-    else if (item == cache->bottom)
+    while(real_key->entry_name[i] != '\0')
     {
-        /* Adjust bottom */
-        cache->bottom = cache->element[item].prev;
-        cache->element[cache->bottom].next = -1;
-    }
-    else
-    {
-        /* Item in the middle */
-        prev = cache->element[item].prev;
-        next = cache->element[item].next;
-        cache->element[prev].next = next;
-        cache->element[next].prev = prev;
+        sum += (unsigned int) real_key->entry_name[i];
+        i++;
     }
+    sum += real_key->parent_ref.handle + real_key->parent_ref.fs_id;
+    tmp_ret =  sum % table_size;
+    return(tmp_ret);
 }
-
-/* ncache_update_dentry_timestamp
+  
+/* ncache_free_payload()
  *
- * updates the timestamp of the ncache entry
+ * frees payload that has been stored in the ncache 
  *
- * returns 0 on success, -PVFS_errno on failure
+ * returns 0 on success, -PVFS_error on failure
  */
-static int ncache_update_dentry_timestamp(ncache_entry* entry) 
+static int ncache_free_payload(void* payload)
 {
-    int ret = 0;
-
-    ret = gettimeofday(&entry->tstamp_valid,NULL);
-    if (ret == 0)
-    {
-        entry->tstamp_valid.tv_sec +=
-            (int)(s_pint_ncache_timeout_ms / 1000);
-        entry->tstamp_valid.tv_usec +=
-            (int)((s_pint_ncache_timeout_ms % 1000) * 1000);
-    }
-    return ret;
+    struct ncache_payload* tmp_payload = (struct ncache_payload*)payload;
+  
+    free(tmp_payload->entry_name);
+    free(tmp_payload);
+    return(0);
 }
-#endif /* ENABLE_NCACHE */
-
+  
 /*
  * Local variables:
  *  c-indent-level: 4
@@ -597,3 +525,4 @@ static int ncache_update_dentry_timestam
  *
  * vim: ts=8 sts=4 sw=4 expandtab
  */
+

Index: ncache.h
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/ncache.h,v
diff -p -u -r1.5 -r1.5.28.1
--- ncache.h	13 Oct 2004 21:02:59 -0000	1.5
+++ ncache.h	9 Aug 2006 20:17:33 -0000	1.5.28.1
@@ -1,60 +1,134 @@
 /*
- * (C) 2001 Clemson University and The University of Chicago
+ * Copyright © Acxiom Corporation, 2006
  *
  * See COPYING in top-level directory.
+ */
+
+#ifndef __NCACHE_H
+#define __NCACHE_H
+
+#include "pvfs2-types.h"
+#include "pvfs2-attr.h"
+#include "gen-locks.h"
+#include "quicklist.h"
+#include "quickhash.h"
+#include "tcache.h"
+#include "pint-perf-counter.h"
+
+/** \defgroup ncache Name Cache (ncache)
+ *
+ * The ncache implements a simple client side cache for PVFS2 files.
+ * A timeout is associated with each entry to dictate when it will expire. 
+ * The ncache is built on top of the generic tcache caching component. The NCACHE
+ * component will cache the following:
+ * - parent handle
+ * - entry for a specific file OR directory within the parent directory
+ * - entry handle
+ * .
+ *
+ * The tcache implements a simple component for caching data structures that
+ * can be referenced by unique, opaque keys.  A timeout is associated with each 
+ * entry to dictate when it will expire.  Specific caches such as the
+ * attribute or name cache may be built on top of this one.
+ *
+ * Notes:
+ * - See tcache for policy documentation
+ * .
+ *
+ * Operations that may retrieve items from ncache:
+ * - lookup
+ * - rename  (Current implementation does not yet use ncache)
+ * .
  *
+ * Operations that may insert items into the cache:
+ * - pvfs2-lookup
+ * - pvfs2-rename  (Current implementation does not yet use ncache)
+ * - pvfs2-symlink
+ * - pvfs2-readdir
+ * - pvfs2-mkdir
+ * - pvfs2-create
+ * .
+ *
+ * Operations that may DELETE items from the cache:
+ * - pvfs2-remove
+ * - pvfs2-rename
+ * - any failed sysint operation from the list of operations that retrieve
+ *   items from NCACHE
+ * .
+ *
+ * @{
  */
 
-#ifndef _PINT_NCACHE_H
-#define _PINT_NCACHE_H
+/** \file
+ * Declarations for the Name Cache (ncache) component.
+ */
 
-#include "pint-sysint-utils.h"
+/** @see PINT_tcache_options */
+#define PINT_ncache_options PINT_tcache_options
+enum {
+NCACHE_TIMEOUT_MSECS = TCACHE_TIMEOUT_MSECS,
+NCACHE_NUM_ENTRIES = TCACHE_NUM_ENTRIES,
+NCACHE_HARD_LIMIT = TCACHE_HARD_LIMIT,
+NCACHE_SOFT_LIMIT = TCACHE_SOFT_LIMIT,
+NCACHE_ENABLE = TCACHE_ENABLE,
+NCACHE_RECLAIM_PERCENTAGE = TCACHE_RECLAIM_PERCENTAGE,
+};
+
+enum 
+{
+   PERF_NCACHE_NUM_ENTRIES = 0,
+   PERF_NCACHE_SOFT_LIMIT = 1,
+   PERF_NCACHE_HARD_LIMIT = 2,
+   PERF_NCACHE_HITS = 3,
+   PERF_NCACHE_MISSES = 4,
+   PERF_NCACHE_UPDATES = 5,
+   PERF_NCACHE_PURGES = 6,
+   PERF_NCACHE_REPLACEMENTS = 7,
+   PERF_NCACHE_DELETIONS = 8, 
+   PERF_NCACHE_ENABLED = 9,
+};
 
-/* number of entries allowed in the cache */
-#define PINT_NCACHE_MAX_ENTRIES 1024
+/** ncache performance counter keys */
+extern struct PINT_perf_key ncache_keys[];
 
-/* number of milliseconds that cache entries will remain valid */
-#define PINT_NCACHE_TIMEOUT_MS 30000
-
-/* value passed out to indicate lookups that didn't find a match */
-#define PINT_NCACHE_HANDLE_INVALID 0
-
-int PINT_ncache_lookup(
-        char *name,
-        int want_resolved,
-        PVFS_object_ref parent,
-        PVFS_object_ref *entry);
-
-int PINT_ncache_insert(
-        char *name, 
-        int abs_resolved,
-        PVFS_object_ref entry,
-        PVFS_object_ref parent);
-
-int PINT_ncache_flush(void);
-
-int PINT_ncache_remove(
-        char *name, 
-        int abs_resolved,
-        PVFS_object_ref parent,
-        int *item_found);
+void PINT_ncache_enable_perf_counter(struct PINT_perf_counter* pc);
 
 int PINT_ncache_initialize(void);
 
-int PINT_ncache_finalize(void);
+void PINT_ncache_finalize(void);
+
+int PINT_ncache_get_info(
+    enum PINT_ncache_options option,
+    unsigned int* arg);
 
-int PINT_ncache_get_timeout(void);
+int PINT_ncache_set_info(
+    enum PINT_ncache_options option,
+    unsigned int arg);
 
-void PINT_ncache_set_timeout(int max_timeout_ms);
+int PINT_ncache_get_cached_entry(
+    const char* entry, 
+    PVFS_object_ref* entry_ref,
+    const PVFS_object_ref* parent_ref); 
 
-#endif 
+int PINT_ncache_update(
+    const char* entry, 
+    const PVFS_object_ref* entry_ref, 
+    const PVFS_object_ref* parent_ref); 
+
+void PINT_ncache_invalidate(
+    const char* entry, 
+    const PVFS_object_ref* parent_ref); 
+
+#endif /* __NCACHE_H */
+
+/* @} */
 
 /*
  * Local variables:
- *  mode: c
  *  c-indent-level: 4
  *  c-basic-offset: 4
  * End:
  *
- * vim: ft=c ts=8 sts=4 sw=4 expandtab
+ * vim: ts=8 sts=4 sw=4 expandtab
  */
+

Index: remove.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/remove.sm,v
diff -p -u -r1.19.2.1 -r1.19.2.2
--- remove.sm	7 Jun 2006 03:20:39 -0000	1.19.2.1
+++ remove.sm	9 Aug 2006 20:17:33 -0000	1.19.2.2
@@ -23,7 +23,6 @@ extern job_context_id pint_client_sm_con
 enum
 {
     REMOVE_MUST_REMOVE_DATAFILES = 1,
-    MSGPAIR_RETURN_SUCCESS
 };
 
 static int remove_getattr_init(PINT_client_sm *sm_p,
@@ -119,7 +118,6 @@ nested machine pvfs2_client_remove_helpe
     {
         jump pvfs2_msgpairarray_sm;
         success => remove_helper_cleanup;
-        MSGPAIR_RETURN_SUCCESS => remove_helper_cleanup;
         default => object_remove_failure;
     }
 

Index: sys-create.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-create.sm,v
diff -p -u -r1.90.2.1 -r1.90.2.2
--- sys-create.sm	7 Jun 2006 03:20:39 -0000	1.90.2.1
+++ sys-create.sm	9 Aug 2006 20:17:33 -0000	1.90.2.2
@@ -24,6 +24,7 @@
 #include "pint-distribution.h"
 #include "PINT-reqproto-encode.h"
 #include "pint-util.h"
+#include "pint-dist-utils.h"
 #include "ncache.h"
 #include "pvfs2-internal.h"
 
@@ -417,7 +418,7 @@ static int create_init(PINT_client_sm *s
     PINT_SM_GETATTR_STATE_FILL(
         sm_p->getattr,
         sm_p->object_ref,
-        PVFS_ATTR_COMMON_ALL, 
+        PVFS_ATTR_COMMON_ALL|PVFS_ATTR_DIR_HINT, 
         PVFS_TYPE_DIRECTORY,
         0);
 
@@ -753,7 +754,7 @@ static int create_setattr_setup_msgpair(
         sm_p->u.create.metafile_handle,
         PVFS_TYPE_METAFILE,
         sm_p->u.create.sys_attr,
-        (PVFS_ATTR_COMMON_TYPE | PVFS_ATTR_META_ALL));
+        PVFS_ATTR_META_ALL);
 
     msg_p->req.u.setattr.attr.u.meta.dfile_array =
         sm_p->u.create.datafile_handles;
@@ -811,10 +812,7 @@ static int create_crdirent_setup_msgpair
         sm_p->u.create.object_name,
         sm_p->u.create.metafile_handle,
         sm_p->object_ref.handle,
-        sm_p->object_ref.fs_id,
-        sm_p->u.create.sys_attr.atime,
-        sm_p->u.create.sys_attr.mtime,
-        sm_p->u.create.sys_attr.ctime);
+        sm_p->object_ref.fs_id);
 
     msg_p->fs_id = sm_p->object_ref.fs_id;
     msg_p->handle = sm_p->object_ref.handle;
@@ -980,9 +978,9 @@ static int create_cleanup(PINT_client_sm
         sm_p->u.create.create_resp->ref = metafile_ref;
 
         /* insert newly created metafile into the ncache */
-        PINT_ncache_insert(sm_p->u.create.object_name,
-                           0 /* PVFS2_LOOKUP_LINK_NO_FOLLOW */,
-                           metafile_ref, sm_p->object_ref);
+        PINT_ncache_update((const char*) sm_p->u.create.object_name, 
+                           (const PVFS_object_ref*) &metafile_ref, 
+                           (const PVFS_object_ref*) &(sm_p->object_ref));
     }
     else if ((PVFS_ERROR_CLASS(-sm_p->error_code) == PVFS_ERROR_BMI) &&
              (sm_p->u.create.retry_count < sm_p->msgarray_params.retry_limit))
@@ -1042,6 +1040,9 @@ static int create_parent_getattr_inspect
     PINT_client_sm *sm_p, job_status_s *js_p)
 {
     PVFS_object_attr *attr = NULL;
+    int num_dfiles_requested_override = 0;
+    PINT_dist *current_dist; 
+    int ret = 0;
 
     gossip_debug(GOSSIP_CLIENT_DEBUG, "create state: parent_getattr_inspect\n");
 
@@ -1060,7 +1061,108 @@ static int create_parent_getattr_inspect
         sm_p->u.create.sys_attr.group = attr->group;
         /* note that permission checking is left to server even in this case */
     }
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "create_parent_getattr: [%p] "
+        "dfile_count     = %d "
+        "dist_name_len   = %d "
+        "dist_params_len = %d\n",
+        attr,
+        attr->u.dir.hint.dfile_count,
+        attr->u.dir.hint.dist_name_len,
+        attr->u.dir.hint.dist_params_len);
+
+    num_dfiles_requested_override = attr->u.dir.hint.dfile_count;
+    /* override the # of data files for this create */
+    if (num_dfiles_requested_override > 0)
+    {
+        /* Determine the number of dfiles */
+        PINT_cached_config_get_num_dfiles(sm_p->object_ref.fs_id,
+                sm_p->u.create.dist,
+                num_dfiles_requested_override,
+                &sm_p->u.create.num_data_files);
+    }
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "Setting number of datafiles to %d [requested %d]\n", 
+        sm_p->u.create.num_data_files, num_dfiles_requested_override);
+    current_dist = sm_p->u.create.dist;
+    /* We have an overriding distribution name for this directory.. honor that */
+    if (attr->u.dir.hint.dist_name_len > 0)
+    {
+        /* switch it only if it is different! */
+        if (strcmp(attr->u.dir.hint.dist_name, current_dist->dist_name))
+        {
+            PINT_dist *new_dist = NULL;
+            new_dist = PINT_dist_create(attr->u.dir.hint.dist_name);
+            if (new_dist)
+            {
+                gossip_debug(GOSSIP_CLIENT_DEBUG, "Overridding distribution name to %s instead of %s\n",
+                    attr->u.dir.hint.dist_name,
+                    current_dist->dist_name);
+                PINT_dist_free(current_dist);
+                sm_p->u.create.dist = new_dist;
+                current_dist = new_dist;
+            }
+            else
+            {
+                gossip_debug(GOSSIP_CLIENT_DEBUG, "Could not override distribution name with %s instead of %s\n",
+                    attr->u.dir.hint.dist_name,
+                    current_dist->dist_name);
+            }
+        }
+        else {
+            gossip_debug(GOSSIP_CLIENT_DEBUG, "retaining current distribution name %s\n",
+                current_dist->dist_name);
+        }
+    }
 
+    /* okay, we might need to override some dist params as well */
+    if (attr->u.dir.hint.dist_params_len > 0)
+    {
+        /* We have a series of comma separated key:val strings */
+        char **key, **val;
+        int64_t tmp_val;
+        int nparams = 0;
+
+        /* ignore parse errors! */
+        if (PINT_split_keyvals(attr->u.dir.hint.dist_params,
+            &nparams, &key, &val) == 0)
+        {
+            int i;
+            for (i = 0; i < nparams; i++)
+            {
+                gossip_debug(GOSSIP_CLIENT_DEBUG, "distribution parameter %s, value %s\n",
+                    key[i], val[i]);
+                /* NOTE: just as in server-config.c when parsing "Param" and
+                 * "Value" fields, we will assume that all values are 64 bit
+                 * integers.  The only difference here is that we scan
+                 * directly into a 64 bit integer, rather than converting
+                 * from the int format that dotconf supports.
+                 */
+                ret = sscanf(val[i], SCANF_lld, &tmp_val);
+                if(ret != 1)
+                {
+                    gossip_err("Error: unsupported type for distribution parameter %s, value %s found in directory hints.\n", 
+                        key[i], val[i]);
+                    gossip_err("Error: continuing anyway.\n");
+                }
+                else
+                {
+                    if(current_dist->methods->set_param(current_dist->dist_name,
+                        current_dist->params,
+                        key[i],
+                        &tmp_val))
+                    {
+
+                        gossip_err("Error: could not override hinted distribution parameter %s, value %s found in directory hints\n",
+                            key[i],
+                            val[i]);
+                    }
+                 }
+                 free(key[i]);
+                 free(val[i]);
+            }
+            free(key);
+            free(val);
+        }
+    }
     return(1);
 }
 

Index: sys-get-eattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-get-eattr.sm,v
diff -p -u -r1.4.6.1 -r1.4.6.2
--- sys-get-eattr.sm	7 Jun 2006 03:20:39 -0000	1.4.6.1
+++ sys-get-eattr.sm	9 Aug 2006 20:17:33 -0000	1.4.6.2
@@ -139,7 +139,9 @@ PVFS_error PVFS_sys_geteattr(
         PVFS_ds_keyval *val_p)
 {
     PVFS_sysresp_geteattr resp_p;
+    PVFS_error tmp_err;
     resp_p.val_array = val_p;
+    resp_p.err_array = &tmp_err;
     return PVFS_sys_geteattr_list(ref, credentials, 1, key_p, &resp_p);
 }
 
@@ -263,22 +265,27 @@ static int get_eattr_comp_fn(
             /* out the actual read_sz in its place */
             sm_p->u.geteattr.resp_p->val_array[k].read_sz =
                     resp_p->u.geteattr.val[k].buffer_sz;
+            sm_p->u.geteattr.resp_p->err_array[k] =
+                    resp_p->u.geteattr.err[k];
             /* check for too big a return message */
-            if (sm_p->u.geteattr.resp_p->val_array[k].read_sz <=
-                    sm_p->u.geteattr.resp_p->val_array[k].buffer_sz)
+            if(resp_p->u.geteattr.err[k] == 0)
             {
-                gossip_debug(GOSSIP_GETEATTR_DEBUG,"copying\n");
-                memcpy(sm_p->u.geteattr.resp_p->val_array[k].buffer,
-                        resp_p->u.geteattr.val[k].buffer,
-                        sm_p->u.geteattr.resp_p->val_array[k].read_sz);
-            }
-            else /* oops, error! returned too much data */
-            {
-                gossip_debug(GOSSIP_GETEATTR_DEBUG,"clearing on error\n");
-                memset(sm_p->u.geteattr.resp_p->val_array[k].buffer,0,
-                        sm_p->u.geteattr.resp_p->val_array[k].buffer_sz);
-                /* record an error, but keep going */
-                ret = -PVFS_EMSGSIZE;
+                if (sm_p->u.geteattr.resp_p->val_array[k].read_sz <=
+                        sm_p->u.geteattr.resp_p->val_array[k].buffer_sz)
+                {
+                    gossip_debug(GOSSIP_GETEATTR_DEBUG,"copying\n");
+                    memcpy(sm_p->u.geteattr.resp_p->val_array[k].buffer,
+                            resp_p->u.geteattr.val[k].buffer,
+                            sm_p->u.geteattr.resp_p->val_array[k].read_sz);
+                }
+                else /* oops, error! returned too much data */
+                {
+                    gossip_debug(GOSSIP_GETEATTR_DEBUG,"clearing on error\n");
+                    memset(sm_p->u.geteattr.resp_p->val_array[k].buffer,0,
+                            sm_p->u.geteattr.resp_p->val_array[k].buffer_sz);
+                    /* record an error, but keep going */
+                    ret = -PVFS_EMSGSIZE;
+                }
             }
         }
     }

Index: sys-getattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-getattr.sm,v
diff -p -u -r1.97.2.2 -r1.97.2.3
--- sys-getattr.sm	7 Jun 2006 03:20:39 -0000	1.97.2.2
+++ sys-getattr.sm	9 Aug 2006 20:17:33 -0000	1.97.2.3
@@ -538,7 +538,6 @@ static int getattr_object_getattr_comp_f
                           &resp_p->u.getattr.attr);
 
     attr =  &sm_p->getattr.attr;
-    assert(attr);
 
     /* if the ref_type mask is set to a non-zero value (!PVFS_TYPE_NONE)
      * a -PVFS_error will be triggered if the
@@ -617,7 +616,18 @@ static int getattr_object_getattr_comp_f
             }
             return 0;
         case PVFS_TYPE_DIRECTORY:
+        {
+            gossip_debug(GOSSIP_CLIENT_DEBUG,
+                "getattr comp_fn [%p] "
+                "dfile_count = %d "
+                "dist_name_len = %d "
+                "dist_params_len = %d\n",
+                attr,
+                attr->u.dir.hint.dfile_count,
+                attr->u.dir.hint.dist_name_len,
+                attr->u.dir.hint.dist_params_len);
             return 0;
+        }
         case PVFS_TYPE_SYMLINK:
             return 0;
         case PVFS_TYPE_DATAFILE:
@@ -843,6 +853,42 @@ static int getattr_set_sys_response(PINT
        sm_p->getattr.req_attrmask & PVFS_ATTR_META_DFILES)
     {
         sysresp->attr.dfile_count = attr->u.meta.dfile_count;
+    }
+    if (attr->objtype == PVFS_TYPE_DIRECTORY)
+    {
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "dfile_count: %d\n", 
+            attr->u.dir.hint.dfile_count);
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_len = %d, dist_params_len = %d\n",
+            attr->u.dir.hint.dist_name_len, attr->u.dir.hint.dist_params_len);
+        sysresp->attr.dfile_count = attr->u.dir.hint.dfile_count;
+        /* 
+         * If we retrieved any extended attributes for the directory
+         * in question, the caller's responsibility to free it up
+         */
+        if (attr->u.dir.hint.dist_name_len > 0 && 
+            (sm_p->getattr.req_attrmask & PVFS_ATTR_DIR_HINT))
+        {
+            sysresp->attr.dist_name = strdup(attr->u.dir.hint.dist_name);
+            if (!sysresp->attr.dist_name)
+            {
+                js_p->error_code = -PVFS_ENOMEM;
+                return 0;
+            }
+            gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_hint: %s\n", sysresp->attr.dist_name);
+        }
+        if (attr->u.dir.hint.dist_params_len > 0 &&
+            (sm_p->getattr.req_attrmask & PVFS_ATTR_DIR_HINT))
+        {
+            sysresp->attr.dist_params = strdup(attr->u.dir.hint.dist_params);
+            if (!sysresp->attr.dist_params)
+            {
+                free(sysresp->attr.dist_name);
+                sysresp->attr.dist_name = NULL;
+                js_p->error_code = -PVFS_ENOMEM;
+                return 0;
+            }
+            gossip_debug(GOSSIP_CLIENT_DEBUG, "dist_name_params: %s\n", sysresp->attr.dist_params);
+        }
     }
 
     /* copy outgoing sys_attr fields from returned object_attr */

Index: sys-io.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-io.sm,v
diff -p -u -r1.142.2.1 -r1.142.2.2
--- sys-io.sm	7 Jun 2006 03:20:39 -0000	1.142.2.1
+++ sys-io.sm	9 Aug 2006 20:17:34 -0000	1.142.2.2
@@ -812,37 +812,6 @@ static int io_datafile_post_msgpairs(PIN
             cur_ctx->msg_send_has_been_posted = 1;
             ++sm_p->u.io.msgpair_completion_count;
         }
-
-        if(sm_p->u.io.io_type == PVFS_IO_WRITE)
-        {
-            ret = io_post_flow(sm_p, cur_ctx);
-            if(ret < 0)
-            {
-                char buf[64] = {0};
-                PVFS_strerror_r(ret, buf, 64);
-
-                gossip_debug(GOSSIP_IO_DEBUG,
-                             "%s: io_post_flow failed: "
-                             "%s (%d remaining msgpairs)\n",
-                             __func__, 
-                             buf, 
-                             sm_p->u.io.msgpair_completion_count);
-
-                PVFS_perror_gossip("Flow post failed", ret);
-                cur_ctx->msg_send_has_been_posted = 0;
-                cur_ctx->msg_recv_has_been_posted = 0;
-                js_p->error_code = ret;
-                continue;
-            }
-
-            ret = io_post_write_ack_recv(sm_p, cur_ctx);
-            if(ret < 0)
-            {
-                PVFS_perror_gossip("Post of write-ack recv failed", ret);
-                js_p->error_code = ret;
-                continue;
-            }
-        }
     }
 
     gossip_debug(GOSSIP_IO_DEBUG, "io_datafile_post_msgpairs: "
@@ -969,24 +938,35 @@ static int io_datafile_complete_operatio
             goto check_next_step;
         }
  
-        if(sm_p->u.io.io_type == PVFS_IO_READ)
+        /* for now we wait to post the flow until we get back
+         * the response from the server for both reads and writes
+         */
+        ret = io_post_flow(sm_p, cur_ctx);
+        if(ret < 0)
+        {
+            char buf[64] = {0};
+            PVFS_strerror_r(ret, buf, 64);
+
+            gossip_debug(GOSSIP_IO_DEBUG,
+                         "%s: io_post_flow failed: "
+                         "%s (%d remaining msgpairs)\n",
+                         __func__, 
+                         buf, 
+                         sm_p->u.io.msgpair_completion_count);
+
+            PVFS_perror_gossip("Flow post failed", ret);
+            cur_ctx->msg_send_has_been_posted = 0;
+            cur_ctx->msg_recv_has_been_posted = 0;
+            js_p->error_code = ret;
+            goto check_next_step;
+        }
+
+        if(sm_p->u.io.io_type == PVFS_IO_WRITE)
         {
-            ret = io_post_flow(sm_p, cur_ctx);
+            ret = io_post_write_ack_recv(sm_p, cur_ctx);
             if(ret < 0)
             {
-                char buf[64] = {0};
-                PVFS_strerror_r(ret, buf, 64);
-
-                gossip_debug(GOSSIP_IO_DEBUG,
-                             "%s: io_post_flow failed: "
-                             "%s (%d remaining msgpairs)\n",
-                             __func__, 
-                             buf, 
-                             sm_p->u.io.msgpair_completion_count);
-
-                PVFS_perror_gossip("Flow post failed", ret);
-                cur_ctx->msg_send_has_been_posted = 0;
-                cur_ctx->msg_recv_has_been_posted = 0;
+                PVFS_perror_gossip("Post of write-ack recv failed", ret);
                 js_p->error_code = ret;
                 goto check_next_step;
             }
@@ -2456,6 +2436,8 @@ io_find_offset(
                                    &rfdata, &result, PINT_SERVER);
         if(res < 0)
         {
+            PINT_free_request_state(filereq_state);
+            PINT_free_request_state(memreq_state);
             return res;
         }
 
@@ -2476,6 +2458,9 @@ io_find_offset(
     } while(!PINT_REQUEST_DONE(filereq_state) && result.segs);
 
     *total_return_offset = total_offset;
+
+    PINT_free_request_state(filereq_state);
+    PINT_free_request_state(memreq_state);
     return 0;
 }
 

Index: sys-lookup.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-lookup.sm,v
diff -p -u -r1.61.2.1 -r1.61.2.2
--- sys-lookup.sm	7 Jun 2006 03:20:39 -0000	1.61.2.1
+++ sys-lookup.sm	9 Aug 2006 20:17:34 -0000	1.61.2.2
@@ -592,9 +592,10 @@ static int lookup_init(PINT_client_sm *s
     assert(js_p->error_code == 0);
 
     /* check the ncache to see if we can bypass this entire lookup */
-    if (PINT_ncache_lookup(sm_p->u.lookup.orig_pathname, 0,
-                           sm_p->u.lookup.starting_refn,
-                           &sm_p->u.lookup.lookup_resp->ref) == 0)
+    if (PINT_ncache_get_cached_entry(
+                (const char*)sm_p->u.lookup.orig_pathname, 
+                &sm_p->u.lookup.lookup_resp->ref,
+                (const PVFS_object_ref*) &(sm_p->u.lookup.starting_refn)) == 0)
     {
         gossip_debug(GOSSIP_LOOKUP_DEBUG, "Lookup: ncache fast path!\n");
         js_p->error_code = LOOKUP_NCACHE_HIT_FASTPATH;
@@ -1011,21 +1012,6 @@ static int lookup_cleanup(PINT_client_sm
 
     sm_p->error_code = js_p->error_code;
 
-    /*
-      on success, attempt to insert the resolved segment/object refn
-      into the ncache if it wasn't a cache hit AND we didn't just
-      resolve a symlink object, rather than a truly resolved object
-      (for now)
-    */
-    if ((js_p->error_code == 0) && (!sm_p->ncache_hit) &&
-        (!sm_p->u.lookup.skipped_final_resolution))
-    {
-        PINT_ncache_insert(sm_p->u.lookup.orig_pathname,
-                           0 /*sm_p->u.lookup.follow_link*/,
-                           sm_p->u.lookup.lookup_resp->ref,
-                           sm_p->u.lookup.starting_refn);
-    }
-
     /* clean up all used memory for this lookup */
     for(i = 0; i < MAX_LOOKUP_CONTEXTS; i++)
     {
@@ -1115,6 +1101,24 @@ static int lookup_segment_lookup_comp_fn
             PINT_copy_object_attr(
                 &(cur_seg->seg_attr),
                 &(resp_p->u.lookup_path.attr_array[i]));
+        }
+        
+        if (!sm_p->ncache_hit)
+        {
+            gossip_debug(
+                GOSSIP_NCACHE_DEBUG, "*** ncache update on %s "
+                                     "target (%llu|%d) "
+                                     "parent (%llu|%d)\n",
+                cur_seg->seg_name,
+                llu(last_resolved_refn.handle),
+                last_resolved_refn.fs_id,
+                llu(cur_seg->seg_starting_refn.handle),
+                cur_seg->seg_starting_refn.fs_id);
+
+            PINT_ncache_update(
+                    (const char*) cur_seg->seg_name,
+                    (const PVFS_object_ref*) &(last_resolved_refn),
+                    (const PVFS_object_ref*) &(cur_seg->seg_starting_refn));
         }
     }
     assert(i == resp_p->u.lookup_path.handle_count);

Index: sys-mkdir.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-mkdir.sm,v
diff -p -u -r1.52.2.1 -r1.52.2.2
--- sys-mkdir.sm	7 Jun 2006 03:20:39 -0000	1.52.2.1
+++ sys-mkdir.sm	9 Aug 2006 20:17:34 -0000	1.52.2.2
@@ -32,7 +32,8 @@ extern job_context_id pint_client_sm_con
 
 enum
 {
-    MKDIR_RETRY = 180
+    MKDIR_RETRY = 180,
+    MKDIR_SKIP_EATTR = 181
 };
 
 static int mkdir_init(
@@ -45,6 +46,10 @@ static int mkdir_crdirent_setup_msgpair(
     PINT_client_sm *sm_p, job_status_s *js_p);
 static int mkdir_crdirent_failure(
     PINT_client_sm *sm_p, job_status_s *js_p);
+static int mkdir_seteattr_setup_msgpair(
+    PINT_client_sm *sm_p, job_status_s *js_p);
+static int mkdir_seteattr_failure(
+    PINT_client_sm *sm_p, job_status_s *js_p);
 static int mkdir_delete_handle_setup_msgpair(
     PINT_client_sm *sm_p, job_status_s *js_p);
 static int mkdir_cleanup(
@@ -68,6 +73,9 @@ machine pvfs2_client_mkdir_sm(
     mkdir_msg_setup_msgpair,
     mkdir_msg_xfer_msgpair,
     mkdir_msg_failure,
+    mkdir_seteattr_setup_msgpair,
+    mkdir_seteattr_xfer_msgpair,
+    mkdir_seteattr_failure,
     mkdir_crdirent_setup_msgpair,
     mkdir_crdirent_xfer_msgpair,
     mkdir_crdirent_failure,
@@ -105,7 +113,7 @@ machine pvfs2_client_mkdir_sm(
     state mkdir_msg_xfer_msgpair
     {
         jump pvfs2_msgpairarray_sm;
-        success => mkdir_crdirent_setup_msgpair;
+        success => mkdir_seteattr_setup_msgpair;
         default => mkdir_msg_failure;
     }
 
@@ -115,6 +123,27 @@ machine pvfs2_client_mkdir_sm(
         default => cleanup;
     }
 
+    state mkdir_seteattr_setup_msgpair
+    {
+        run mkdir_seteattr_setup_msgpair;
+        MKDIR_SKIP_EATTR => mkdir_crdirent_setup_msgpair;
+        success => mkdir_seteattr_xfer_msgpair;
+        default => mkdir_seteattr_failure;
+    }
+
+    state mkdir_seteattr_xfer_msgpair
+    {
+        jump pvfs2_msgpairarray_sm;
+        success => mkdir_crdirent_setup_msgpair;
+        default => mkdir_seteattr_failure;
+    }
+
+    state mkdir_seteattr_failure
+    {
+        run mkdir_seteattr_failure;
+        default => delete_handle_setup_msgpair;
+    }
+
     state mkdir_crdirent_setup_msgpair
     {
         run mkdir_crdirent_setup_msgpair;
@@ -277,7 +306,7 @@ static int mkdir_init(PINT_client_sm *sm
     PINT_SM_GETATTR_STATE_FILL(
         sm_p->getattr,
         sm_p->object_ref,
-        PVFS_ATTR_COMMON_ALL, 
+        (PVFS_ATTR_COMMON_ALL|PVFS_ATTR_DIR_HINT), 
         PVFS_TYPE_DIRECTORY,
         0);
 
@@ -304,7 +333,7 @@ static int mkdir_msg_comp_fn(void *v_p,
     sm_p->u.mkdir.metafile_handle = resp_p->u.mkdir.handle;
 
     /* also insert entry into attr cache */
-    PINT_CONVERT_ATTR(&attr, &sm_p->u.mkdir.sys_attr, PVFS_ATTR_COMMON_ALL);
+    PINT_CONVERT_ATTR(&attr, &sm_p->u.mkdir.sys_attr, 0);
     PINT_acache_update(sm_p->object_ref, &attr, NULL);
 
     gossip_debug(
@@ -372,8 +401,7 @@ static int mkdir_msg_setup_msgpair(PINT_
         *sm_p->cred_p,
         sm_p->object_ref.fs_id,
         meta_handle_extent_array,
-        sm_p->u.mkdir.sys_attr,
-        PVFS_ATTR_SYS_ALL_NOSIZE);
+        sm_p->u.mkdir.sys_attr);
 
     msg_p->fs_id = sm_p->object_ref.fs_id;
     msg_p->handle = meta_handle_extent_array.extent_array[0].first;
@@ -418,10 +446,7 @@ static int mkdir_crdirent_setup_msgpair(
         sm_p->u.mkdir.object_name,
         sm_p->u.mkdir.metafile_handle,
         sm_p->object_ref.handle,
-        sm_p->object_ref.fs_id,
-        sm_p->u.mkdir.sys_attr.atime,
-        sm_p->u.mkdir.sys_attr.mtime,
-        sm_p->u.mkdir.sys_attr.ctime);
+        sm_p->object_ref.fs_id);
 
     msg_p->fs_id = sm_p->object_ref.fs_id;
     msg_p->handle = sm_p->object_ref.handle;
@@ -498,6 +523,20 @@ static int mkdir_cleanup(PINT_client_sm 
 {
     gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: cleanup\n");
 
+    if(sm_p->u.mkdir.val_array)
+    {
+        if((sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT) &&
+            (sm_p->getattr.attr.u.dir.hint.dfile_count > 0))
+        {
+            free(sm_p->u.mkdir.val_array[0].buffer);
+        }
+        free(sm_p->u.mkdir.val_array);
+    }
+    if(sm_p->u.mkdir.key_array)
+    {
+        free(sm_p->u.mkdir.key_array);
+    }
+
     PVFS_util_release_sys_attr(&sm_p->u.mkdir.sys_attr);
 
     PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
@@ -517,9 +556,9 @@ static int mkdir_cleanup(PINT_client_sm 
         sm_p->u.mkdir.mkdir_resp->ref.fs_id = directory_ref.fs_id;
 
         /* insert newly created directory handle into the ncache */
-        PINT_ncache_insert(sm_p->u.mkdir.object_name,
-                           0 /* PVFS2_LOOKUP_LINK_NO_FOLLOW */,
-                           directory_ref, sm_p->object_ref);
+        PINT_ncache_update((const char*) sm_p->u.mkdir.object_name, 
+                           (const PVFS_object_ref*) &directory_ref, 
+                           (const PVFS_object_ref*) &(sm_p->object_ref));
     }
     else if ((PVFS_ERROR_CLASS(-sm_p->error_code) == PVFS_ERROR_BMI) &&
              (sm_p->u.mkdir.retry_count < sm_p->msgarray_params.retry_limit))
@@ -570,6 +609,152 @@ static int mkdir_parent_getattr_inspect(
     }
 
     return(1);
+}
+
+static int mkdir_seteattr_setup_msgpair(
+    PINT_client_sm *sm_p, job_status_s *js_p)
+{
+    int eattr_count = 0;
+    int cur_index = 0;
+    PINT_sm_msgpair_state *msg_p = NULL;
+    int ret = -PVFS_EINVAL;
+
+    /* NOTE: any memory allocated here will be free'd in the cleanup function */
+
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: seteattr_setup_msgpair\n");
+    
+    /* don't set any hint attributes if the parent doesn't have them */
+    if(!(sm_p->getattr.attr.mask & PVFS_ATTR_DIR_HINT))
+    {
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: skipping seteattr\n");
+        js_p->error_code = MKDIR_SKIP_EATTR;
+        return(1);
+    }
+
+    /* count how many hints we acquired */
+    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
+        eattr_count++;
+    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
+        eattr_count++;
+    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
+        eattr_count++;
+
+    if(eattr_count == 0)
+    {
+        /* nothing to inherit */
+        js_p->error_code = MKDIR_SKIP_EATTR;
+        return(1);
+    }
+
+    sm_p->u.mkdir.key_array = (PVFS_ds_keyval*)calloc(eattr_count,
+        sizeof(PVFS_ds_keyval));
+    if(!sm_p->u.mkdir.key_array)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
+    }
+
+    sm_p->u.mkdir.val_array = (PVFS_ds_keyval*)calloc(eattr_count,
+        sizeof(PVFS_ds_keyval));
+    if(!sm_p->u.mkdir.val_array)
+    {
+        js_p->error_code = -PVFS_ENOMEM;
+        return(1);
+    }
+
+    if(sm_p->getattr.attr.u.dir.hint.dfile_count > 0)
+    {
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting num_dfiles\n");
+        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.num_dfiles";
+        sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
+            strlen("user.pvfs2.num_dfiles") + 1;
+
+        sm_p->u.mkdir.val_array[cur_index].buffer = calloc(1, 16);
+        if(!sm_p->u.mkdir.val_array[cur_index].buffer)
+        {
+            js_p->error_code = -PVFS_ENOMEM;
+            return(1);
+        }
+        snprintf((char*)sm_p->u.mkdir.val_array[cur_index].buffer,
+            16, "%d", sm_p->getattr.attr.u.dir.hint.dfile_count);
+        sm_p->u.mkdir.val_array[cur_index].buffer_sz = 
+            strlen((char*)sm_p->u.mkdir.val_array[cur_index].buffer) + 1;
+
+        cur_index++;
+    }
+    if(sm_p->getattr.attr.u.dir.hint.dist_name != NULL)
+    {
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_name\n");
+        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_name";
+        sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
+            strlen("user.pvfs2.dist_name") + 1;
+        sm_p->u.mkdir.val_array[cur_index].buffer =
+            sm_p->getattr.attr.u.dir.hint.dist_name;
+        sm_p->u.mkdir.val_array[cur_index].buffer_sz =
+            sm_p->getattr.attr.u.dir.hint.dist_name_len;
+
+        cur_index++;
+    }
+    if(sm_p->getattr.attr.u.dir.hint.dist_params != NULL)
+    {
+        gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir: setting dist_params\n");
+        sm_p->u.mkdir.key_array[cur_index].buffer = "user.pvfs2.dist_params";
+        sm_p->u.mkdir.key_array[cur_index].buffer_sz = 
+            strlen("user.pvfs2.dist_params") + 1;
+
+        sm_p->u.mkdir.val_array[cur_index].buffer = 
+            sm_p->getattr.attr.u.dir.hint.dist_params;
+        sm_p->u.mkdir.val_array[cur_index].buffer_sz = 
+            sm_p->getattr.attr.u.dir.hint.dist_params_len;
+
+        cur_index++;
+    }
+
+    PINT_init_msgpair(sm_p, msg_p);
+
+    PINT_SERVREQ_SETEATTR_FILL(
+            sm_p->msgpair.req,
+            (*sm_p->cred_p),
+            sm_p->object_ref.fs_id,
+            sm_p->u.mkdir.metafile_handle,
+            0,
+            eattr_count,
+            sm_p->u.mkdir.key_array,
+            sm_p->u.mkdir.val_array
+            );
+
+    sm_p->msgarray = &(sm_p->msgpair);
+    sm_p->msgarray_count = 1;
+    sm_p->msgpair.fs_id = sm_p->object_ref.fs_id;
+    sm_p->msgpair.handle = sm_p->u.mkdir.metafile_handle;
+    sm_p->msgpair.retry_flag = PVFS_MSGPAIR_RETRY;
+    /* NOTE: no comp_fn needed. */
+
+    ret = PINT_cached_config_map_to_server(
+            &sm_p->msgpair.svr_addr,
+            sm_p->msgpair.handle,
+            sm_p->msgpair.fs_id);
+    if (ret)
+    {
+        gossip_err("Failed to map meta server address\n");
+        js_p->error_code = ret;
+    }
+    else
+    {
+        js_p->error_code = 0;
+    }
+    return(1);
+}
+
+static int mkdir_seteattr_failure(
+    PINT_client_sm *sm_p, job_status_s *js_p)
+{
+    sm_p->u.mkdir.stored_error_code = js_p->error_code;
+
+    gossip_debug(GOSSIP_CLIENT_DEBUG, "mkdir state: mkdir_seteattr_failure\n");
+
+    PVFS_perror_gossip("mkdir seteattr failed", js_p->error_code);
+    return 1;
 }
 
 /*

Index: sys-readdir.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-readdir.sm,v
diff -p -u -r1.43.2.3 -r1.43.2.4
--- sys-readdir.sm	7 Jun 2006 03:20:39 -0000	1.43.2.3
+++ sys-readdir.sm	9 Aug 2006 20:17:34 -0000	1.43.2.4
@@ -308,10 +308,7 @@ static int readdir_msg_comp_fn(void *v_p
     {
         int dirent_array_len =
             (sizeof(PVFS_dirent) * *(sm_p->readdir.dirent_outcount));
-#if 0
-        int i = 0;
-        PVFS_object_ref tmp_ref;
-#endif
+
         /* this dirent_array MUST be freed by caller */
         *(sm_p->readdir.dirent_array) =
             (PVFS_dirent *) malloc(dirent_array_len);
@@ -319,19 +316,6 @@ static int readdir_msg_comp_fn(void *v_p
 
         memcpy(*(sm_p->readdir.dirent_array),
                resp_p->u.readdir.dirent_array, dirent_array_len);
-#if 0
-        /* insert all handles into the ncache while we have them */
-        tmp_ref.fs_id = sm_p->object_ref.fs_id;
-        for(i = 0;
-            i < *(sm_p->readdir.dirent_outcount); i++)
-        {
-            tmp_ref.handle = resp_p->u.readdir.dirent_array[i].handle;
-            PINT_ncache_insert(
-                resp_p->u.readdir.dirent_array[i].d_name,
-                0 /* PVFS2_LOOKUP_LINK_NO_FOLLOW */, tmp_ref,
-                sm_p->object_ref);
-        }
-#endif
     }
 
     gossip_debug(GOSSIP_READDIR_DEBUG, "*** Got %d directory entries "
@@ -353,7 +337,23 @@ static int readdir_msg_failure(PINT_clie
 static int readdir_cleanup(PINT_client_sm *sm_p,
                            job_status_s *js_p)
 {
+    int i = 0;
+    PVFS_object_ref tmp_ref;
     gossip_debug(GOSSIP_CLIENT_DEBUG, "readdir state: cleanup\n");
+
+    if(js_p->error_code == 0)
+    {
+        /* insert all handles into the ncache while we have them */
+        tmp_ref.fs_id = sm_p->object_ref.fs_id;
+        for(i = 0; i < *(sm_p->readdir.dirent_outcount); i++)
+        {
+            tmp_ref.handle = (*(sm_p->readdir.dirent_array))[i].handle;
+            PINT_ncache_update(
+                (const char *) (*(sm_p->readdir.dirent_array))[i].d_name,
+                (const PVFS_object_ref *) &(tmp_ref),
+                (const PVFS_object_ref *) &(sm_p->object_ref));
+        }
+    }
 
     PINT_SM_GETATTR_STATE_CLEAR(sm_p->getattr);
 

Index: sys-remove.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-remove.sm,v
diff -p -u -r1.93.6.1 -r1.93.6.2
--- sys-remove.sm	7 Jun 2006 03:20:39 -0000	1.93.6.1
+++ sys-remove.sm	9 Aug 2006 20:17:34 -0000	1.93.6.2
@@ -44,8 +44,7 @@ extern job_context_id pint_client_sm_con
 
 enum
 {
-    MSGPAIR_RETURN_SUCCESS = 1,
-    RMDIRENT_RETRY,
+    RMDIRENT_RETRY = 1,
     CRDIRENT_RETRY,
     RETURN_STORED_ERROR_CODE
 };
@@ -112,7 +111,6 @@ machine pvfs2_client_remove_sm(
     {
         jump pvfs2_msgpairarray_sm;
         success => do_remove;
-        MSGPAIR_RETURN_SUCCESS => do_remove;
         default => rmdirent_retry_or_fail;
     }
 
@@ -160,7 +158,6 @@ machine pvfs2_client_remove_sm(
     {
         jump pvfs2_msgpairarray_sm;
         success => cleanup;
-        MSGPAIR_RETURN_SUCCESS => cleanup;
         default => crdirent_retry_or_fail;
     }
 
@@ -295,10 +292,7 @@ static int remove_rmdirent_setup_msgpair
         *sm_p->cred_p,
         sm_p->parent_ref.fs_id,
         sm_p->parent_ref.handle,
-        sm_p->u.remove.object_name,
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->u.remove.object_name);
 
     gossip_debug(GOSSIP_REMOVE_DEBUG, "- doing RMDIRENT on %s "
                  "under %llu,%d\n", sm_p->u.remove.object_name,
@@ -342,10 +336,7 @@ static int remove_crdirent_setup_msgpair
         sm_p->u.remove.object_name,
         sm_p->object_ref.handle,
         sm_p->parent_ref.handle,
-        sm_p->parent_ref.fs_id,
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->parent_ref.fs_id);
 
     gossip_debug(GOSSIP_REMOVE_DEBUG, "- doing CRDIRENT of %s (%llu,%d) "
                  "under %llu,%d\n", sm_p->u.remove.object_name,
@@ -355,7 +346,7 @@ static int remove_crdirent_setup_msgpair
                  sm_p->parent_ref.fs_id);
 
     msg_p->fs_id = sm_p->parent_ref.fs_id;
-    msg_p->handle = sm_p->object_ref.handle;
+    msg_p->handle = sm_p->parent_ref.handle;
     msg_p->retry_flag = PVFS_MSGPAIR_NO_RETRY;
     msg_p->comp_fn = remove_crdirent_comp_fn;
 
@@ -448,10 +439,12 @@ static int remove_cleanup(PINT_client_sm
                         js_p->error_code);
 
     /* NOTE: acache is invalidated by remove_helper now */
-
-    PINT_ncache_remove(sm_p->u.remove.object_name,
-                       0 /* PVFS2_LOOKUP_LINK_NO_FOLLOW */,
-                       sm_p->parent_ref, NULL);
+    
+    /* The ncache invalidate must be done from this function, because the 
+     * remove_helper may not  have all the information needed
+     */
+    PINT_ncache_invalidate((const char*) sm_p->u.remove.object_name,
+                           (const PVFS_object_ref*) &(sm_p->parent_ref));
 
     if (sm_p->msgarray && (sm_p->msgarray != &sm_p->msgpair))
     {
@@ -546,7 +539,7 @@ static int remove_rmdirent_retry_or_fail
             sm_p->u.remove.object_name);
 
         PRINT_REMOVE_WARNING();
-        js_p->error_code = 0;
+        js_p->error_code = -PVFS_ENOENT;
         return 1;
     }
 

Index: sys-rename.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-rename.sm,v
diff -p -u -r1.43.2.1 -r1.43.2.2
--- sys-rename.sm	7 Jun 2006 03:20:40 -0000	1.43.2.1
+++ sys-rename.sm	9 Aug 2006 20:17:34 -0000	1.43.2.2
@@ -27,6 +27,7 @@
 #include "PINT-reqproto-encode.h"
 #include "pint-util.h"
 #include "pvfs2-internal.h"
+#include "ncache.h"
 
 extern job_context_id pint_client_sm_context;
 
@@ -398,6 +399,15 @@ static int rename_init(PINT_client_sm *s
 
     assert(js_p->error_code == 0);
 
+    /* Invalidate the old entry in ncache */
+    PINT_ncache_invalidate(
+            (const char*) sm_p->u.rename.entries[0],
+            (const PVFS_object_ref*) &(sm_p->u.rename.parent_refns[0]));
+    /* Invalidate the new entry in ncache in case it already exists */
+    PINT_ncache_invalidate(
+            (const char*) sm_p->u.rename.entries[1],
+            (const PVFS_object_ref*) &(sm_p->u.rename.parent_refns[1]));
+
     return 1;
 }
 
@@ -641,10 +651,7 @@ static int rename_crdirent_setup_msgpair
         sm_p->u.rename.entries[1],
         sm_p->u.rename.refns[0].handle,
         sm_p->u.rename.parent_refns[1].handle,
-        sm_p->u.rename.parent_refns[1].fs_id,
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->u.rename.parent_refns[1].fs_id);
 
     msg_p->fs_id = sm_p->u.rename.parent_refns[1].fs_id;
     msg_p->handle = sm_p->u.rename.parent_refns[1].handle;
@@ -694,10 +701,7 @@ static int rename_rmdirent_setup_msgpair
         *sm_p->cred_p,
         sm_p->u.rename.parent_refns[sm_p->u.rename.rmdirent_index].fs_id,
         sm_p->u.rename.parent_refns[sm_p->u.rename.rmdirent_index].handle,
-        sm_p->u.rename.entries[sm_p->u.rename.rmdirent_index],
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->u.rename.entries[sm_p->u.rename.rmdirent_index]);
 
     msg_p->fs_id = sm_p->u.rename.parent_refns[
         sm_p->u.rename.rmdirent_index].fs_id;
@@ -826,10 +830,7 @@ static int rename_chdirent_setup_msgpair
         sm_p->u.rename.parent_refns[1].fs_id,
         sm_p->u.rename.parent_refns[1].handle,
         sm_p->u.rename.refns[0].handle,
-        sm_p->u.rename.entries[1],
-        0,
-        PVFS_util_get_current_time(),
-        PVFS_util_get_current_time());
+        sm_p->u.rename.entries[1]);
 
     msg_p->fs_id = sm_p->u.rename.parent_refns[1].fs_id;
     msg_p->handle = sm_p->u.rename.parent_refns[1].handle;

Index: sys-setattr.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-setattr.sm,v
diff -p -u -r1.44.6.1 -r1.44.6.2
--- sys-setattr.sm	7 Jun 2006 03:20:40 -0000	1.44.6.1
+++ sys-setattr.sm	9 Aug 2006 20:17:34 -0000	1.44.6.2
@@ -108,7 +108,7 @@ PVFS_error PVFS_isys_setattr(
      * make sure the caller didn't set invalid mask bits.
      * only common attributes can be set.
      */
-    if ((attr.mask & ~PVFS_ATTR_SYS_ALL_SETABLE) != 0)
+    if ((attr.mask & ~PVFS_ATTR_SYS_ALL_TIMES) != 0)
     {
         gossip_lerr("PVFS_isys_setattr() failure: invalid attributes "
                     "specified\n");
@@ -116,7 +116,7 @@ PVFS_error PVFS_isys_setattr(
     }
 
     /* make sure that the permission bits are acceptable */
-    if ((attr.perms & ~PVFS_PERM_VALID) != 0)
+    if ((attr.mask & PVFS_ATTR_SYS_PERM) && (attr.perms & ~PVFS_PERM_VALID) != 0)
     {
         gossip_lerr("PVFS_isys_setattr() failure: invalid or unsupported" 
                     "permission bits\n");
@@ -208,6 +208,7 @@ static int setattr_msg_setup_msgpair(PIN
 {
     int ret = -PVFS_EINVAL;
     PINT_sm_msgpair_state *msg_p = NULL;
+    PVFS_ds_type objtype;
 
     gossip_debug(GOSSIP_CLIENT_DEBUG, "setattr state: "
                  "setattr_msg_setup_msgpair\n");
@@ -218,15 +219,17 @@ static int setattr_msg_setup_msgpair(PIN
 
     PINT_init_msgpair(sm_p, msg_p);
 
+    objtype = ((sm_p->u.setattr.sys_attr.mask & PVFS_ATTR_SYS_TYPE) ? 
+         sm_p->u.setattr.sys_attr.objtype : PVFS_TYPE_NONE);
+
     PINT_SERVREQ_SETATTR_FILL(
         msg_p->req,
         *sm_p->cred_p,
         sm_p->object_ref.fs_id,
         sm_p->object_ref.handle,
-        ((sm_p->u.setattr.sys_attr.mask & PVFS_ATTR_SYS_TYPE) ? 
-         sm_p->u.setattr.sys_attr.objtype : PVFS_TYPE_NONE),
+        objtype,
         sm_p->u.setattr.sys_attr,
-        PVFS_ATTR_COMMON_TYPE);
+        0);
 
     /* clients should not be able to mess with dfile and distribution
      * information here.  Those parameters should only be set at create time.
@@ -276,8 +279,7 @@ static int setattr_cleanup(PINT_client_s
      */
     if(sm_p->error_code == 0)
     {
-        PINT_CONVERT_ATTR(&attr, &sm_p->u.setattr.sys_attr,
-            PVFS_ATTR_COMMON_ALL);
+        PINT_CONVERT_ATTR(&attr, &sm_p->u.setattr.sys_attr, 0);
         PINT_acache_update(sm_p->object_ref, &attr, NULL);
     }
     else

Index: sys-small-io.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-small-io.sm,v
diff -p -u -r1.7.6.1 -r1.7.6.2
--- sys-small-io.sm	7 Jun 2006 03:20:40 -0000	1.7.6.1
+++ sys-small-io.sm	9 Aug 2006 20:17:34 -0000	1.7.6.2
@@ -25,8 +25,6 @@
 #include "pint-util.h"
 #include "pvfs2-internal.h"
 
-#define SMALL_IO_MAX_REGIONS 64
-
 /* The small-io state machine should only be invoked/jumped-to from the
  * sys-io state machine.  We make this assumption and expect io parameters
  * to be initialized already.
@@ -124,7 +122,7 @@ static int small_io_setup_msgpairs(PINT_
             file_data.dist = attr->u.meta.dist;
             file_data.extend_flag = 1;
 
-            result.segmax = SMALL_IO_MAX_REGIONS;
+            result.segmax = IO_MAX_REGIONS;
             result.bytemax = PINT_REQUEST_TOTAL_BYTES(sm_p->u.io.mem_req);
             file_req_state = PINT_new_request_state(sm_p->u.io.file_req);
             mem_req_state = PINT_new_request_state(sm_p->u.io.mem_req);
@@ -224,8 +222,8 @@ static int small_io_completion_fn(void *
 
     if(resp_p->u.small_io.io_type == PVFS_IO_READ)
     {
-        PVFS_size sizes[SMALL_IO_MAX_REGIONS];
-        PVFS_offset offsets[SMALL_IO_MAX_REGIONS];
+        PVFS_size sizes[IO_MAX_REGIONS];
+        PVFS_offset offsets[IO_MAX_REGIONS];
         PVFS_object_attr * attr = &sm_p->getattr.attr;
         PINT_request_file_data fdata;
         PINT_Request_result result;
@@ -242,7 +240,7 @@ static int small_io_completion_fn(void *
             fdata.dist = attr->u.meta.dist;
             fdata.fsize = resp_p->u.small_io.bstream_size;
 
-            result.segmax = SMALL_IO_MAX_REGIONS;
+            result.segmax = IO_MAX_REGIONS;
             result.bytemax = resp_p->u.small_io.result_size;
             result.size_array = sizes;
             result.offset_array = offsets;

Index: sys-symlink.sm
===================================================================
RCS file: /projects/cvsroot/pvfs2-1/src/client/sysint/sys-symlink.sm,v
diff -p -u -r1.59.2.1 -r1.59.2.2
--- sys-symlink.sm	7 Jun 2006 03:20:40 -0000	1.59.2.1
+++ sys-symlink.sm	9 Aug 2006 20:17:34 -0000	1.59.2.2
@@ -345,8 +345,7 @@ static int symlink_setattr_comp_fn(void 
 
     if(resp_p->status == 0)
     {
-        PINT_CONVERT_ATTR(&attr, &sm_p->u.sym.sys_attr,
-            (PVFS_ATTR_COMMON_ALL|PVFS_ATTR_SYMLNK_ALL));
+        PINT_CONVERT_ATTR(&attr, &sm_p->u.sym.sys_attr, 0);
         PINT_acache_update(tmp_ref, &attr, NULL);
     }
 
@@ -453,10 +452,7 @@ static int symlink_crdirent_setup_msgpai
         sm_p->u.sym.link_name,
         sm_p->u.sym.symlink_handle,
         sm_p->object_ref.handle,
-        sm_p->object_ref.fs_id,
-        sm_p->u.sym.sys_attr.atime,
-        sm_p->u.sym.sys_attr.mtime,
-        sm_p->u.sym.sys_attr.ctime);
+        sm_p->object_ref.fs_id);
 
     msg_p->fs_id = sm_p->object_ref.fs_id;
     msg_p->handle = sm_p->object_ref.handle;
@@ -512,7 +508,7 @@ static int symlink_setattr_setup_msgpair
         sm_p->u.sym.symlink_handle,
         PVFS_TYPE_SYMLINK,
         sm_p->u.sym.sys_attr,
-        (PVFS_ATTR_COMMON_TYPE | PVFS_ATTR_SYMLNK_ALL));
+        PVFS_ATTR_SYMLNK_ALL);
 
     /* fill in symlink specific attributes */
     msg_p->req.u.setattr.attr.u.sym.target_path =
@@ -609,9 +605,9 @@ static int symlink_cleanup(PINT_client_s
         sm_p->u.sym.sym_resp->ref = symlink_ref;
 
         /* insert newly created symlink into the ncache */
-        PINT_ncache_insert(sm_p->u.sym.link_name,
-                           0 /* PVFS2_LOOKUP_LINK_NO_FOLLOW */,
-                           symlink_ref, sm_p->object_ref);
+        PINT_ncache_update((const char*) sm_p->u.sym.link_name, 
+                           (const PVFS_object_ref*) &symlink_ref, 
+                           (const PVFS_object_ref*) &(sm_p->object_ref));
     }
     else if ((PVFS_ERROR_CLASS(-sm_p->error_code) == PVFS_ERROR_BMI) &&
              (sm_p->u.sym.retry_count < sm_p->msgarray_params.retry_limit))



More information about the Pvfs2-cvs mailing list