reiserfs: fix race in readdir
PATCH v2 1/1 reiserfs: fix race in readdir
jdm-20004 reiserfs_delete_xattrs: Couldn't delete all xattrs (-2)
The -ENOENT is due to readdir calling dir_emit on the same entry twice.
If the dir_emit callback sleeps and the tree is changed underneath us, we won't be able to trust deh_offset(deh) anymore. We need to save next_pos before we might sleep so we can find the next entry.
--- fs/reiserfs/dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/reiserfs/dir.c +4 -2
@@ -125,6 +125,7 @@ int reiserfs_readdir_inode(struct inodeint d_reclen;char *d_name;ino_t d_ino; +loff_t cur_pos =deh_offset (deh);if (!de_visible (deh))/* it is hidden entry */
@@ -196,8 +197,9 @@ int reiserfs_readdir_inode(struct inodeif (local_buf != small_buf) {kfree (local_buf); } -// next entry should be looked for with such offset - next_pos =deh_offset (deh) +1 ; + +/* deh_offset(deh) may be invalid now. */ + next_pos = cur_pos +1 ;if (item_moved (&tmp_ih, &path_to_entry)) { set_cpu_key_k_offset(&pos_key,
Signature · 2 lines
Jeff Mahoney SUSE Labs
Quoted 9 lines · Jeff Mahoney
jdm-20004
reiserfs_delete_xattrs: Couldn't delete all xattrs (-2)The
-ENOENTis due to readdir callingdir_emiton the same entry twice.If the
dir_emitcallback sleeps and the tree is changed underneath us, we won't be able to trustdeh_offset(deh)anymore. We need to savenext_posbefore we might sleep so we can find the next entry.Signed-off-by Jeff Mahoney <[email protected]>
Thanks for a quick fix. I've merged the patch to my tree.
Honza
Quoted 30 lines
--- fs/reiserfs/dir.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)fs/reiserfs/dir.c +4
-2@@ -125,6 +125,7 @@ int reiserfs_readdir_inode(struct inodeint d_reclen;char *d_name;ino_t d_ino; +loff_t cur_pos =deh_offset (deh);if (!de_visible (deh))/* it is hidden entry */ @@ -196,8 +197,9 @@ int reiserfs_readdir_inode(struct inodeif (local_buf != small_buf) {kfree (local_buf); } -// next entry should be looked for with such offset - next_pos =deh_offset (deh) +1 ; + +/* deh_offset(deh) may be invalid now. */ + next_pos = cur_pos +1 ;if (item_moved (&tmp_ih, &path_to_entry)) { set_cpu_key_k_offset(&pos_key,Signature · 3 lines
-- Jeff Mahoney SUSE Labs
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR