ext3 inode accounting fix
PATCH 1/1 ext3 inode accounting fix
ext3 in the 2.5.46 kernel is double-counting inodes in the per-blockgroup accounting structures. When a blockgroup fills up this triggers a consistency check and the filesystem is remounted read-only.
There is no data loss, but all ext3 filesystems which have been mounted
read/write under the 2.5.46 kernel will have incorrect accounting. They
must be fixed with a fsck. If this is not done, the filesystem will be remounted read-only at some time in the future - when a blockgroup runs out of inodes and the consistency check detects the error.
Step 1: patch the 2.5.46 kernel with the below fix
Step 2: reboot into the new kernel, forcing a fsck against all ext3
filesystems.
Alternatively, wait for 2.5.47 and then fsck all filesystems. The problem only manifests if all of a blockgroup's inodes are consumed, and that is rare.
fs/ext3/ialloc.c renamed from fs/ext3/ialloc.c~ext3-inodes-count-fix +3 -16
@@ -227,11 +227,6 @@ static int find_group_dir(struct super_b }if (!best_desc)return -1 ; - best_desc->bg_free_inodes_count = -cpu_to_le16 (le16_to_cpu (best_desc->bg_free_inodes_count) -1 ); - best_desc->bg_used_dirs_count = -cpu_to_le16 (le16_to_cpu (best_desc->bg_used_dirs_count) +1 ); -mark_buffer_dirty (best_bh);return best_group; }
@@ -355,14 +350,7 @@ fallback: }return -1 ; - found: - desc->bg_free_inodes_count = -cpu_to_le16 (le16_to_cpu (desc->bg_free_inodes_count) -1 ); - desc->bg_used_dirs_count = -cpu_to_le16 (le16_to_cpu (desc->bg_used_dirs_count) +1 ); - sbi->s_dir_count++; -mark_buffer_dirty (bh);return group; }
@@ -410,9 +398,6 @@ static int find_group_other(struct superreturn -1 ; found: - desc->bg_free_inodes_count = -cpu_to_le16 (le16_to_cpu (desc->bg_free_inodes_count) -1 ); -mark_buffer_dirty (bh);return group; }
@@ -521,9 +506,11 @@ repeat:if (err) goto fail; gdp->bg_free_inodes_count =cpu_to_le16 (le16_to_cpu (gdp->bg_free_inodes_count) -1 ); -if (S_ISDIR (mode)) +if (S_ISDIR (mode)) { gdp->bg_used_dirs_count =cpu_to_le16 (le16_to_cpu (gdp->bg_used_dirs_count) +1 ); +EXT3_SB (sb)->s_dir_count++; + }BUFFER_TRACE (bh2,"call ext3_journal_dirty_metadata" ); err =ext3_journal_dirty_metadata (handle, bh2);if (err) goto fail;
_