Bug 9366 - BFS: Directory entries stored in the last directory block are handled incorrectly.
Summary: BFS: Directory entries stored in the last directory block are handled incorre...
Status: RESOLVED CODE_FIX
Alias: None
Product: File System
Classification: Unclassified
Component: Other (show other bugs)
Hardware: All Linux
: P1 high
Assignee: Dmitri Vorobiev
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-11-13 07:33 UTC by Dmitri Vorobiev
Modified: 2007-11-13 12:01 UTC (History)
1 user (show)

See Also:
Kernel Version: 2.6.24-rc2
Subsystem:
Regression: ---
Bisected commit-id:


Attachments

Description Dmitri Vorobiev 2007-11-13 07:33:09 UTC
Most recent kernel where this bug did not occur: 2.6.6
Distribution: this bug does not depend on distribution.
Hardware Environment: x86
Software Environment:

>>>

# lsmod
Module                  Size  Used by
bfs                    14008  1
#

<<<

Problem Description:

An error in the bfs_add_entry() function leads to inaproppriate handling of directory entries if the latter entries reside in the last block allocated for the directory.

Steps to reproduce:

1. Format a BFS partition allowing 512 directory entries in the root directory. This is the default value for the mkfs utility shipped with the UnixWare 7.1.1 operating system. Two directory entries are thereby occupied by the "." and ".." entries leaving 510 entries for regular files.

2. Use the following command to create 511 files in the BFS root directory:

>>>

debian:/mnt# for i in `seq 1 511`; do echo "$i" > $i; done

<<<

3. Unmount the BFS partition and then mount it again:

>>>

debian:~/bfs# umount /mnt
debian:~/bfs# mount -t bfs /dev/loop0 /mnt/

<<<

4. See that the file with the name `479' disappeared from the filesystem:

debian:~/bfs# cd /mnt
debian:/mnt# cat 479
cat: 479: No such file or directory

>>>
Comment 1 Dmitri Vorobiev 2007-11-13 07:35:11 UTC
If the root directory is full and an attempt is made to create another directory entry, the following code in the bfs_add_entry() function

>>>

if (block==eblock && off>=eoff) {
	/* Do not read/interpret the garbage in the end of eblock. */
	de->ino = 0;
}

<<<

makes the function believe that the directory entry at the offset 0 of the last block allocated for the directory is not used. This code snippet silently deletes the directory entry, which occupies the direntry slot in the beginning of the last directory block and replaces it with another one. The blocks occupied by the "unlinked" inode are thereby lost.

The erroneous code was introduced in the context of the patch submitted in this LKML message:

http://lkml.org/lkml/2004/5/4/205

Not only this code snippet introduces a bug, but also the intention behind it is erroneous: indeed, there can be no "garbage" directory entries, but any directory entry with nonzero `ino' field should be valid.
Comment 2 Dmitri Vorobiev 2007-11-13 07:36:47 UTC
I am working on a fix, and am planning to submit a patch.
Comment 3 Dmitri Vorobiev 2007-11-13 08:48:31 UTC
The patch proposed in the following LKML message

http://lkml.org/lkml/2007/11/13/185

fixes the error reported in the context of this bug. What follows is a console session, which proves that the error is gone:

>>>

debian:~# mount -t bfs /dev/loop0 /mnt
debian:~# cd /mnt/
debian:/mnt# for i in `seq 1 511`; do echo "$i" > $i; done
-bash: 511: No space left on device
debian:/mnt# cd
debian:~# umount /mnt
debian:~# mount -t bfs /dev/loop0 /mnt/
debian:~# cd /mnt
debian:/mnt# cat 479
479
debian:/mnt#

<<<
Comment 4 Dmitri Vorobiev 2007-11-13 12:01:56 UTC
Merged in -mm tree, so I am closing this bug.

Note You need to log in before you can comment on or make changes to this bug.