Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: close race between direct IO and ext4_break_layouts()

If the refcount of a page is lowered between the time that it is returned
by dax_busy_page() and when the refcount is again checked in
ext4_break_layouts() => ___wait_var_event(), the waiting function
ext4_wait_dax_page() will never be called. This means that
ext4_break_layouts() will still have 'retry' set to false, so we'll stop
looping and never check the refcount of other pages in this inode.

Instead, always continue looping as long as dax_layout_busy_page() gives us
a page which it found with an elevated refcount.

Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
Reviewed-by: Jan Kara <jack@suse.cz>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@vger.kernel.org

authored by

Ross Zwisler and committed by
Theodore Ts'o
b1f38217 5f8c1093

+3 -6
+3 -6
fs/ext4/inode.c
··· 4195 4195 return 0; 4196 4196 } 4197 4197 4198 - static void ext4_wait_dax_page(struct ext4_inode_info *ei, bool *did_unlock) 4198 + static void ext4_wait_dax_page(struct ext4_inode_info *ei) 4199 4199 { 4200 - *did_unlock = true; 4201 4200 up_write(&ei->i_mmap_sem); 4202 4201 schedule(); 4203 4202 down_write(&ei->i_mmap_sem); ··· 4206 4207 { 4207 4208 struct ext4_inode_info *ei = EXT4_I(inode); 4208 4209 struct page *page; 4209 - bool retry; 4210 4210 int error; 4211 4211 4212 4212 if (WARN_ON_ONCE(!rwsem_is_locked(&ei->i_mmap_sem))) 4213 4213 return -EINVAL; 4214 4214 4215 4215 do { 4216 - retry = false; 4217 4216 page = dax_layout_busy_page(inode->i_mapping); 4218 4217 if (!page) 4219 4218 return 0; ··· 4219 4222 error = ___wait_var_event(&page->_refcount, 4220 4223 atomic_read(&page->_refcount) == 1, 4221 4224 TASK_INTERRUPTIBLE, 0, 0, 4222 - ext4_wait_dax_page(ei, &retry)); 4223 - } while (error == 0 && retry); 4225 + ext4_wait_dax_page(ei)); 4226 + } while (error == 0); 4224 4227 4225 4228 return error; 4226 4229 }