cache_inode_lookup should not trust cache when icreate is active.

This is exposed with a very slow FSAL create, just after file object
created but before the entry is added to cache. Client's retry create
will fail with EXIST and then lookup will fail due to parent's not
yet invalidated.

A refcnt is added to cache entry and inc before any create happens
and dec after it's added to dentry cache. trust_negative_cache should
evaluate this counter.

Signed-off-by: Rong Zeng <rongzeng@us.ibm.com>
diff --git a/src/Cache_inode/cache_inode_create.c b/src/Cache_inode/cache_inode_create.c
index 202c8a2..4962067 100644
--- a/src/Cache_inode/cache_inode_create.c
+++ b/src/Cache_inode/cache_inode_create.c
@@ -91,6 +91,7 @@
      fsal_attrib_list_t object_attributes;
      cache_inode_fsal_data_t fsal_data;
      cache_inode_create_arg_t zero_create_arg;
+     bool needdec = false;
 
      memset(&zero_create_arg, 0, sizeof(zero_create_arg));
      memset(&fsal_data, 0, sizeof(fsal_data));
@@ -138,6 +139,10 @@
 
      /* The entry doesn't exist, so we can create it. */
 
+     /* increase the refcount to ensure forced lookup in FSAL */
+     atomic_inc_uint32_t(&parent->icreate_refcnt);
+     needdec = true;
+
      object_attributes.asked_attributes = cache_inode_params.attrmask;
      switch (type) {
      case REGULAR_FILE:
@@ -287,6 +292,9 @@
      *status = CACHE_INODE_SUCCESS;
 
 out:
+     if (needdec == true) {
+          atomic_dec_uint32_t(&parent->icreate_refcnt);
+     }
 
      LogFullDebug(COMPONENT_CACHE_INODE,
                   "Returning entry=%p status=%s",
diff --git a/src/Cache_inode/cache_inode_lookup.c b/src/Cache_inode/cache_inode_lookup.c
index 4959d92..0b4b14d 100644
--- a/src/Cache_inode/cache_inode_lookup.c
+++ b/src/Cache_inode/cache_inode_lookup.c
@@ -170,6 +170,7 @@
                     /* If the dirent cache is both fully populated and
                        valid, it can serve negative lookups. */
                     if (!dirent &&
+                        (parent->icreate_refcnt == 0) && 
                         (parent->flags & CACHE_INODE_DIR_POPULATED)) {
                          entry = NULL;
                          *status = CACHE_INODE_NOT_FOUND;
diff --git a/src/Cache_inode/cache_inode_misc.c b/src/Cache_inode/cache_inode_misc.c
index 5f9473f..df76fcc 100644
--- a/src/Cache_inode/cache_inode_misc.c
+++ b/src/Cache_inode/cache_inode_misc.c
@@ -386,6 +386,7 @@
      /* Initialize common fields */
 
      entry->type = type;
+     entry->icreate_refcnt = 0;
      entry->flags = 0;
      init_glist(&entry->state_list);
 
diff --git a/src/include/cache_inode.h b/src/include/cache_inode.h
index 83b9d11..e9697f6 100644
--- a/src/include/cache_inode.h
+++ b/src/include/cache_inode.h
@@ -344,6 +344,7 @@
                           can be easily stashed somewhere. */
   cache_inode_file_type_t type; /*< The type of the entry */
   uint32_t flags; /*< Flags for this entry */
+  int32_t icreate_refcnt; /*< refcount for number of active icreate */
   time_t change_time; /*< The time of the last operation ganesha knows
                           about.  We can ue this for change_info4, but
                           atomic MUST BE SET TO FALSE.  Don't use it