Commit 3765fefa authored by Hidetoshi Seto's avatar Hidetoshi Seto Committed by Chris Mason

btrfs: fix d_off in the first dirent

Since the d_off in the first dirent for "." (that originates from
the 4th argument "offset" of filldir() for the 2nd dirent for "..")
is wrongly assigned in btrfs_real_readdir(), telldir returns same
offset for different locations.

 | # mkfs.btrfs /dev/sdb1
 | # mount /dev/sdb1 fs0
 | # cd fs0
 | # touch file0 file1
 | # ../test
 | telldir: 0
 | readdir: d_off = 2, d_name = "."
 | telldir: 2
 | readdir: d_off = 2, d_name = ".."
 | telldir: 2
 | readdir: d_off = 3, d_name = "file0"
 | telldir: 3
 | readdir: d_off = 2147483647, d_name = "file1"
 | telldir: 2147483647

To fix this problem, pass filp->f_pos (which is loff_t) instead.

 | # ../test
 | telldir: 0
 | readdir: d_off = 1, d_name = "."
 | telldir: 1
 | readdir: d_off = 2, d_name = ".."
 | telldir: 2
 | readdir: d_off = 3, d_name = "file0"
 :

At the moment the "offset" for "." is unused because there is no
preceding dirent, however it is better to pass filp->f_pos to follow
grammatical usage.
Signed-off-by: default avatarHidetoshi Seto <seto.hidetoshi@jp.fujitsu.com>
Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
parent d525e8ab
...@@ -4117,7 +4117,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, ...@@ -4117,7 +4117,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
/* special case for "." */ /* special case for "." */
if (filp->f_pos == 0) { if (filp->f_pos == 0) {
over = filldir(dirent, ".", 1, 1, btrfs_ino(inode), DT_DIR); over = filldir(dirent, ".", 1,
filp->f_pos, btrfs_ino(inode), DT_DIR);
if (over) if (over)
return 0; return 0;
filp->f_pos = 1; filp->f_pos = 1;
...@@ -4126,7 +4127,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, ...@@ -4126,7 +4127,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
if (filp->f_pos == 1) { if (filp->f_pos == 1) {
u64 pino = parent_ino(filp->f_path.dentry); u64 pino = parent_ino(filp->f_path.dentry);
over = filldir(dirent, "..", 2, over = filldir(dirent, "..", 2,
2, pino, DT_DIR); filp->f_pos, pino, DT_DIR);
if (over) if (over)
return 0; return 0;
filp->f_pos = 2; filp->f_pos = 2;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment