shithub: lwext4

Download patch

ref: 69e6bc56cee09945f574051fa4df0d63eb1c8625
parent: 191fb80f249b0e82bd77b860d090741e0ace9450
author: root <ngkaho1234@gmail.com>
date: Sun Sep 20 12:00:06 EDT 2015

ext4_dir_dx_reset_parent_inode proposed.

--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -232,30 +232,34 @@
 		parent->dirty = true;
 	} else {
 		if (ext4_inode_is_type(&mp->fs.sb, child->inode,
-				       EXT4_INODE_MODE_DIRECTORY)) {
-			/* FIXME: SO TRICKY. */
-			int has_flag_index = ext4_inode_has_flag(
-			    child->inode, EXT4_INODE_FLAG_INDEX);
+					EXT4_INODE_MODE_DIRECTORY)) {
+			int has_flag_index =
+				ext4_inode_has_flag(child->inode,
+						    EXT4_INODE_FLAG_INDEX);
 			struct ext4_directory_search_result result;
-			if (has_flag_index)
-				ext4_inode_clear_flag(child->inode,
-						      EXT4_INODE_FLAG_INDEX);
+			if (!has_flag_index) {
+				rc = ext4_dir_find_entry(&result,
+							 child, "..",
+							 strlen(".."));
+				if (rc != EOK)
+					return EIO;
 
-			rc = ext4_dir_find_entry(&result, child, "..",
-						 strlen(".."));
-			if (has_flag_index)
-				ext4_inode_set_flag(child->inode,
-						    EXT4_INODE_FLAG_INDEX);
+				ext4_dir_entry_ll_set_inode(result.dentry,
+							    parent->index);
+				result.block.dirty = true;
+				rc = ext4_dir_destroy_result(child, &result);
+				if (rc != EOK)
+					return rc;
 
-			if (rc != EOK)
-				return EIO;
+			} else {
+#if CONFIG_DIR_INDEX_ENABLE
+				rc = ext4_dir_dx_reset_parent_inode(parent,
+						parent->index);
+				if (rc != EOK)
+					return rc;
 
-			ext4_dir_entry_ll_set_inode(result.dentry,
-						    parent->index);
-			result.block.dirty = true;
-			rc = ext4_dir_destroy_result(child, &result);
-			if (rc != EOK)
-				return rc;
+#endif
+			}
 
 			ext4_fs_inode_links_count_inc(parent);
 			parent->dirty = true;
--- a/lwext4/ext4_dir.h
+++ b/lwext4/ext4_dir.h
@@ -69,6 +69,16 @@
 	de->inode = to_le32(inode);
 }
 
+/**@brief Set i-node number to directory entry. (For HTree root)
+ * @param de Directory entry
+ * @param inode I-node number
+ */
+static inline void
+ext4_dx_dot_entry_set_inode(struct ext4_directory_dx_dot_entry *de, uint32_t inode)
+{
+	de->inode = to_le32(inode);
+}
+
 /**@brief Get directory entry length.
  * @param de Directory entry
  * @return Entry length
--- a/lwext4/ext4_dir_idx.c
+++ b/lwext4/ext4_dir_idx.c
@@ -1193,6 +1193,30 @@
 	return rc2;
 }
 
+int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir, uint32_t parent_inode)
+{
+    /* Load block 0, where will be index root located */
+    uint32_t fblock;
+    int rc = ext4_fs_get_inode_data_block_index(dir, 0, &fblock);
+    if (rc != EOK)
+        return rc;
+
+    struct ext4_block block;
+    rc = ext4_block_get(dir->fs->bdev, &block, fblock);
+    if (rc != EOK)
+        return rc;
+
+    /* Initialize pointers to data structures */
+    struct ext4_directory_dx_root *root = (void *)block.data;
+
+    /* Fill the inode field with a new parent ino. */
+    ext4_dx_dot_entry_set_inode(&root->dots[1], parent_inode);
+
+    block.dirty = true;
+
+    return ext4_block_set(dir->fs->bdev, &block);
+}
+
 /**
  * @}
  */
--- a/lwext4/ext4_dir_idx.h
+++ b/lwext4/ext4_dir_idx.h
@@ -75,6 +75,14 @@
 int ext4_dir_dx_add_entry(struct ext4_inode_ref *parent,
 			  struct ext4_inode_ref *child, const char *name);
 
+/**@brief Add new entry to indexed directory
+ * @param dir           Directory i-node
+ * @param parent_inode  parent inode index
+ * @return Error code
+ */
+int ext4_dir_dx_reset_parent_inode(struct ext4_inode_ref *dir,
+                                   uint32_t parent_inode);
+
 #endif /* EXT4_DIR_IDX_H_ */
 
 /**