shithub: lwext4

Download patch

ref: 5da1e5389cf9e3e02237979df962f7c9aaeb25c6
parent: 86fbd4e7446d606796dc3877aad8cffa9a611846
author: gkostka <kostka.grzegorz@gmail.com>
date: Fri Oct 24 14:30:12 EDT 2014

Support for feature dir_nlink

--- a/lwext4/ext4.c
+++ b/lwext4/ext4.c
@@ -209,6 +209,8 @@
             return rc;
         }
 
+        /*New empty directory. Two links (. and ..) */
+        ext4_inode_set_links_count(child->inode, 2);
 #if CONFIG_DIR_INDEX_ENABLE
         /* Initialize directory index if supported */
         if (ext4_sb_has_feature_compatible(&mp->fs.sb,
@@ -223,21 +225,13 @@
         }
 #endif
 
-        uint16_t parent_links =
-                ext4_inode_get_links_count(parent->inode);
-        parent_links++;
-        ext4_inode_set_links_count(parent->inode, parent_links);
+        ext4_fs_inode_links_count_inc(parent);
 
         parent->dirty = true;
+        child->dirty = true;
+        return EOK;
     }
 
-    uint16_t child_links =
-            ext4_inode_get_links_count(child->inode);
-    child_links++;
-    ext4_inode_set_links_count(child->inode, child_links);
-
-    child->dirty = true;
-
     return EOK;
 }
 
@@ -255,31 +249,17 @@
         return ENOTSUP;
 
     /* Remove entry from parent directory */
-
     rc = ext4_dir_remove_entry(parent, name, name_len);
     if (rc != EOK)
         return rc;
 
-
-    uint32_t lnk_count =
-            ext4_inode_get_links_count(child_inode_ref->inode);
-    lnk_count--;
-
     bool is_dir = ext4_inode_is_type(&mp->fs.sb, child_inode_ref->inode,
             EXT4_INODE_MODE_DIRECTORY);
 
     /* If directory - handle links from parent */
-    if ((lnk_count <= 1) && (is_dir)) {
-        ext4_assert(lnk_count == 1);
-
-        lnk_count--;
-
-        uint32_t parent_lnk_count = ext4_inode_get_links_count(
-                parent->inode);
-
-        parent_lnk_count--;
-        ext4_inode_set_links_count(parent->inode, parent_lnk_count);
-
+    if (is_dir) {
+        ext4_assert(ext4_inode_get_links_count(child_inode_ref->inode) == 1);
+        ext4_fs_inode_links_count_dec(parent);
         parent->dirty = true;
     }
 
@@ -299,7 +279,7 @@
      *     (uint32_t) now);
      */
     ext4_inode_set_deletion_time(child_inode_ref->inode, 0xFFFFFFFF);
-    ext4_inode_set_links_count(child_inode_ref->inode, lnk_count);
+    ext4_inode_set_links_count(child_inode_ref->inode, 0);
     child_inode_ref->dirty = true;
 
     return EOK;
--- a/lwext4/ext4_fs.c
+++ b/lwext4/ext4_fs.c
@@ -691,7 +691,6 @@
         mode = 0777;
         mode |= EXT4_INODE_MODE_DIRECTORY;
         ext4_inode_set_mode(&fs->sb, inode, mode);
-        ext4_inode_set_links_count(inode, 1);  /* '.' entry */
 
     } else {
         /*
@@ -702,9 +701,9 @@
         mode = 0666;
         mode |= EXT4_INODE_MODE_FILE;
         ext4_inode_set_mode(&fs->sb, inode, mode);
-        ext4_inode_set_links_count(inode, 0);
     }
 
+    ext4_inode_set_links_count(inode, 0);
     ext4_inode_set_uid(inode, 0);
     ext4_inode_set_gid(inode, 0);
     ext4_inode_set_size(inode, 0);
@@ -1359,6 +1358,52 @@
 
     return EOK;
 }
+
+void ext4_fs_inode_links_count_inc(struct ext4_inode_ref *inode_ref)
+{
+    uint16_t link;
+    if(!ext4_inode_is_type(&inode_ref->fs->sb, inode_ref->inode,
+                EXT4_INODE_MODE_DIRECTORY)){
+        ext4_inode_set_links_count(inode_ref->inode, 0);
+        return;
+    }
+
+    link = ext4_inode_get_links_count(inode_ref->inode);
+    link++;
+    ext4_inode_set_links_count(inode_ref->inode, link);
+
+
+    bool is_dx = ext4_sb_has_feature_compatible(&inode_ref->fs->sb,
+            EXT4_FEATURE_COMPAT_DIR_INDEX) &&
+                 ext4_inode_has_flag(inode_ref->inode, EXT4_INODE_FLAG_INDEX);
+
+    if(is_dx &&  link > 1){
+        if(link >= EXT4_LINK_MAX || link == 2){
+            ext4_inode_set_links_count(inode_ref->inode, 1);
+
+            uint32_t v = ext4_get32(&inode_ref->fs->sb, features_read_only);
+            v |= EXT4_FEATURE_RO_COMPAT_DIR_NLINK;
+            ext4_set32(&inode_ref->fs->sb, features_read_only, v);
+        }
+    }
+}
+
+void ext4_fs_inode_links_count_dec(struct ext4_inode_ref *inode_ref)
+{
+    if(!ext4_inode_is_type(&inode_ref->fs->sb, inode_ref->inode,
+                EXT4_INODE_MODE_DIRECTORY)){
+        ext4_inode_set_links_count(inode_ref->inode, 0);
+        return;
+    }
+
+    uint16_t links = ext4_inode_get_links_count(inode_ref->inode);
+
+
+    if(links > 2)
+        ext4_inode_set_links_count(inode_ref->inode, links - 1);
+
+}
+
 
 /**
  * @}
--- a/lwext4/ext4_fs.h
+++ b/lwext4/ext4_fs.h
@@ -198,6 +198,17 @@
 int ext4_fs_append_inode_block(struct ext4_inode_ref *inode_ref,
     uint32_t *fblock, uint32_t *iblock);
 
+
+/**@brief   Increment inode link count.
+ * @param   inode none handle
+ */
+void ext4_fs_inode_links_count_inc(struct ext4_inode_ref *inode_ref);
+
+/**@brief   Decrement inode link count.
+ * @param   inode none handle
+ */
+void ext4_fs_inode_links_count_dec(struct ext4_inode_ref *inode_ref);
+
 #endif /* EXT4_FS_H_ */
 
 /**
--- a/lwext4/ext4_types.h
+++ b/lwext4/ext4_types.h
@@ -558,6 +558,7 @@
 
 #define EXT4_ERR_BAD_DX_DIR       (-25000)
 
+#define EXT4_LINK_MAX       65000
 
 /*
  * This is the extent on-disk structure.