btrfs: fix d_off in the first dirent
PATCH 1/1 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 of the wrong constant value.
| # ../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.
--- fs/btrfs/inode.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
fs/btrfs/inode.c +3 -2
@@ -4125,7 +4125,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,/* special case for "." */ if (filp->f_pos ==0 ) { - over =filldir (dirent,"." ,1 ,1 ,btrfs_ino (inode),DT_DIR ); + over =filldir (dirent,"." ,1 , + filp->f_pos, inode->i_ino,DT_DIR );if (over)return 0 ; filp->f_pos =1 ;
@@ -4134,7 +4135,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,if (filp->f_pos ==1 ) {u64 pino =parent_ino (filp->f_path.dentry); over =filldir (dirent,".." ,2 , -2 , pino,DT_DIR ); + filp->f_pos, pino,DT_DIR );if (over)return 0 ; filp->f_pos =2 ;
Signature · 1 line
1.7.6
fs/btrfs/inode.c static int btrfs_real_readdir(struct file *filp, void *dirent, · line 4129
Quoted 11 lines
fs/btrfs/inode.c +2
-1@@ -4125,7 +4125,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,/* special case for "." */ if (filp->f_pos ==0 ) { - over =filldir (dirent,"." ,1 ,1 ,btrfs_ino (inode),DT_DIR ); + over =filldir (dirent,"." ,1 , + filp->f_pos, inode->i_ino,DT_DIR );
please stick to btrfs_ino().
Quoted 3 lines
fs/btrfs/inode.c +0
-0if (over)return 0 ; filp->f_pos =1 ;
Quoted 6 lines · Li Zefan
Quoted 6 lines
fs/btrfs/inode.c +0
-0@@ -4125,7 +4125,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
Quoted 7 lines
fs/btrfs/inode.c static int btrfs_real_readdir(struct file *filp, void *dirent, · line 4129
Quoted 5 lines
fs/btrfs/inode.c +2
-1/* special case for "." */ if (filp->f_pos ==0 ) { - over =filldir (dirent,"." ,1 ,1 ,btrfs_ino (inode),DT_DIR ); + over =filldir (dirent,"." ,1 , + filp->f_pos, inode->i_ino,DT_DIR );please stick to
btrfs_ino().
Wow, I made a misstep on rebase...
Here is the updated one.
Thanks,
H.Seto
=====
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.
--- fs/btrfs/inode.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-)
fs/btrfs/inode.c +3 -2
@@ -4125,7 +4125,8 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,/* special case for "." */ 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)return 0 ; filp->f_pos =1 ;
@@ -4134,7 +4135,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,if (filp->f_pos ==1 ) {u64 pino =parent_ino (filp->f_path.dentry); over =filldir (dirent,".." ,2 , -2 , pino,DT_DIR ); + filp->f_pos, pino,DT_DIR );if (over)return 0 ; filp->f_pos =2 ;
Signature · 1 line
1.7.6