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.