On Thu 11-07-19 08:49:17, Darrick J. Wong wrote:
On Thu, Jul 11, 2019 at 06:28:54PM +0300, Amir Goldstein wrote:
+{
struct xfs_inode *ip = XFS_I(file_inode(file));
int ret;
/* Readahead needs protection from hole punching and similar ops */
if (advice == POSIX_FADV_WILLNEED)
xfs_ilock(ip, XFS_IOLOCK_SHARED);
It's good to fix this race, but at the same time I wonder what's the impact to processes writing to one part of a file waiting on IOLOCK_EXCL while readahead holds IOLOCK_SHARED?
(bluh bluh range locks ftw bluh bluh)
Yeah, with range locks this would have less impact. Also note that we hold the lock only during page setup and IO submission. IO itself will already happen without IOLOCK, only under page lock. But that's enough to stop the race.
Do we need a lock for DONTNEED? I think the answer is that you have to lock the page to drop it and that will protect us from <myriad punch and truncate spaghetti> ... ?
Yeah, DONTNEED is just page writeback + invalidate. So page lock is enough to protect from anything bad. Essentially we need IOLOCK only to protect the places that creates new pages in page cache.
ret = generic_fadvise(file, start, end, advice);
if (advice == POSIX_FADV_WILLNEED)
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
Maybe it'd be better to do:
int lockflags = 0;
if (advice == POSIX_FADV_WILLNEED) { lockflags = XFS_IOLOCK_SHARED; xfs_ilock(ip, lockflags); }
ret = generic_fadvise(file, start, end, advice);
if (lockflags) xfs_iunlock(ip, lockflags);
Just in case we some day want more or different types of inode locks?
OK, will do. Just I'll get to testing this only after I return from vacation.
Honza