#define CONFIGFS_USET_DEFAULT  0x0080
 #define CONFIGFS_USET_DROPPING 0x0100
 #define CONFIGFS_USET_IN_MKDIR 0x0200
+#define CONFIGFS_USET_CREATING 0x0400
 #define CONFIGFS_NOT_PINNED    (CONFIGFS_ITEM_ATTR)
 
 extern struct mutex configfs_symlink_mutex;
 extern int configfs_create_file(struct config_item *, const struct configfs_attribute *);
 extern int configfs_make_dirent(struct configfs_dirent *,
                                struct dentry *, void *, umode_t, int);
+extern int configfs_dirent_is_ready(struct configfs_dirent *);
 
 extern int configfs_add_file(struct dentry *, const struct configfs_attribute *, int);
 extern void configfs_hash_and_remove(struct dentry * dir, const char * name);
 
        error = configfs_dirent_exists(p->d_fsdata, d->d_name.name);
        if (!error)
                error = configfs_make_dirent(p->d_fsdata, d, k, mode,
-                                            CONFIGFS_DIR);
+                                            CONFIGFS_DIR | CONFIGFS_USET_CREATING);
        if (!error) {
                error = configfs_create(d, mode, init_dir);
                if (!error) {
  *     configfs_create_dir - create a directory for an config_item.
  *     @item:          config_itemwe're creating directory for.
  *     @dentry:        config_item's dentry.
+ *
+ *     Note: user-created entries won't be allowed under this new directory
+ *     until it is validated by configfs_dir_set_ready()
  */
 
 static int configfs_create_dir(struct config_item * item, struct dentry *dentry)
        return error;
 }
 
+/*
+ * Allow userspace to create new entries under a new directory created with
+ * configfs_create_dir(), and under all of its chidlren directories recursively.
+ * @sd         configfs_dirent of the new directory to validate
+ *
+ * Caller must hold configfs_dirent_lock.
+ */
+static void configfs_dir_set_ready(struct configfs_dirent *sd)
+{
+       struct configfs_dirent *child_sd;
+
+       sd->s_type &= ~CONFIGFS_USET_CREATING;
+       list_for_each_entry(child_sd, &sd->s_children, s_sibling)
+               if (child_sd->s_type & CONFIGFS_USET_CREATING)
+                       configfs_dir_set_ready(child_sd);
+}
+
+/*
+ * Check that a directory does not belong to a directory hierarchy being
+ * attached and not validated yet.
+ * @sd         configfs_dirent of the directory to check
+ *
+ * @return     non-zero iff the directory was validated
+ *
+ * Note: takes configfs_dirent_lock, so the result may change from false to true
+ * in two consecutive calls, but never from true to false.
+ */
+int configfs_dirent_is_ready(struct configfs_dirent *sd)
+{
+       int ret;
+
+       spin_lock(&configfs_dirent_lock);
+       ret = !(sd->s_type & CONFIGFS_USET_CREATING);
+       spin_unlock(&configfs_dirent_lock);
+
+       return ret;
+}
+
 int configfs_create_link(struct configfs_symlink *sl,
                         struct dentry *parent,
                         struct dentry *dentry)
        struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
        struct configfs_dirent * sd;
        int found = 0;
-       int err = 0;
+       int err;
+
+       /*
+        * Fake invisibility if dir belongs to a group/default groups hierarchy
+        * being attached
+        *
+        * This forbids userspace to read/write attributes of items which may
+        * not complete their initialization, since the dentries of the
+        * attributes won't be instantiated.
+        */
+       err = -ENOENT;
+       if (!configfs_dirent_is_ready(parent_sd))
+               goto out;
 
        list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
                if (sd->s_type & CONFIGFS_NOT_PINNED) {
                return simple_lookup(dir, dentry, nd);
        }
 
+out:
        return ERR_PTR(err);
 }
 
        }
 
        sd = dentry->d_parent->d_fsdata;
+
+       /*
+        * Fake invisibility if dir belongs to a group/default groups hierarchy
+        * being attached
+        */
+       if (!configfs_dirent_is_ready(sd)) {
+               ret = -ENOENT;
+               goto out;
+       }
+
        if (!(sd->s_type & CONFIGFS_USET_DIR)) {
                ret = -EPERM;
                goto out;
 
        spin_lock(&configfs_dirent_lock);
        sd->s_type &= ~CONFIGFS_USET_IN_MKDIR;
+       if (!ret)
+               configfs_dir_set_ready(dentry->d_fsdata);
        spin_unlock(&configfs_dirent_lock);
 
 out_unlink:
 {
        struct dentry * dentry = file->f_path.dentry;
        struct configfs_dirent * parent_sd = dentry->d_fsdata;
+       int err;
 
        mutex_lock(&dentry->d_inode->i_mutex);
-       file->private_data = configfs_new_dirent(parent_sd, NULL);
+       /*
+        * Fake invisibility if dir belongs to a group/default groups hierarchy
+        * being attached
+        */
+       err = -ENOENT;
+       if (configfs_dirent_is_ready(parent_sd)) {
+               file->private_data = configfs_new_dirent(parent_sd, NULL);
+               if (IS_ERR(file->private_data))
+                       err = PTR_ERR(file->private_data);
+               else
+                       err = 0;
+       }
        mutex_unlock(&dentry->d_inode->i_mutex);
 
-       return IS_ERR(file->private_data) ? PTR_ERR(file->private_data) : 0;
-
+       return err;
 }
 
 static int configfs_dir_close(struct inode *inode, struct file *file)
                if (err) {
                        d_delete(dentry);
                        dput(dentry);
+               } else {
+                       spin_lock(&configfs_dirent_lock);
+                       configfs_dir_set_ready(dentry->d_fsdata);
+                       spin_unlock(&configfs_dirent_lock);
                }
        }
 
 
        struct configfs_symlink *sl;
        int ret;
 
+       ret = -ENOENT;
+       if (!configfs_dirent_is_ready(target_sd))
+               goto out;
        ret = -ENOMEM;
        sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
        if (sl) {
                }
        }
 
+out:
        return ret;
 }
 
 {
        int ret;
        struct nameidata nd;
+       struct configfs_dirent *sd;
        struct config_item *parent_item;
        struct config_item *target_item;
        struct config_item_type *type;
        if (dentry->d_parent == configfs_sb->s_root)
                goto out;
 
+       sd = dentry->d_parent->d_fsdata;
+       /*
+        * Fake invisibility if dir belongs to a group/default groups hierarchy
+        * being attached
+        */
+       ret = -ENOENT;
+       if (!configfs_dirent_is_ready(sd))
+               goto out;
+
        parent_item = configfs_get_config_item(dentry->d_parent);
        type = parent_item->ci_type;
 
+       ret = -EPERM;
        if (!type || !type->ct_item_ops ||
            !type->ct_item_ops->allow_link)
                goto out_put;