mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-10.git
synced 2026-09-09 00:07:04 +08:00
netfs, afs: Fix write skipping in dir/link writepages
JIRA: https://issues.redhat.com/browse/RHEL-190706 commit 9871938f99cc6cb266a77265491660e2375271f5 Author: David Howells <dhowells@redhat.com> Date: Tue May 12 13:34:00 2026 +0100 netfs, afs: Fix write skipping in dir/link writepages Fix netfs_write_single() and afs_single_writepages() to better handle a write that would be skipped due to lock contention and WB_SYNC_NONE by returning 1 from netfs_write_single() if it skipped and making afs_single_writepages() skip also. If a skip occurs, the inode must be re-marked as the VFS may have cleared the mark. This is really only theoretical for directories in netfs_write_single() as the only path to that is through afs_single_writepages() that takes the ->validate_lock around it, thereby serialising it. Fixes: 6dd80936618c ("afs: Use netfslib for directories") Signed-off-by: David Howells <dhowells@redhat.com> Link: https://patch.msgid.link/20260512123404.719402-24-dhowells@redhat.com cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org cc: linux-fsdevel@vger.kernel.org Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Paulo Alcantara <paalcant@redhat.com>
This commit is contained in:
+10
-1
@@ -2094,7 +2094,14 @@ int afs_single_writepages(struct address_space *mapping,
|
||||
/* Need to lock to prevent the folio queue and folios from being thrown
|
||||
* away.
|
||||
*/
|
||||
down_read(&dvnode->validate_lock);
|
||||
if (!down_read_trylock(&dvnode->validate_lock)) {
|
||||
if (wbc->sync_mode == WB_SYNC_NONE) {
|
||||
/* The VFS will have undirtied the inode. */
|
||||
netfs_single_mark_inode_dirty(&dvnode->netfs.inode);
|
||||
return 0;
|
||||
}
|
||||
down_read(&dvnode->validate_lock);
|
||||
}
|
||||
|
||||
if (is_dir ?
|
||||
test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) :
|
||||
@@ -2102,6 +2109,8 @@ int afs_single_writepages(struct address_space *mapping,
|
||||
iov_iter_folio_queue(&iter, ITER_SOURCE, dvnode->directory, 0, 0,
|
||||
i_size_read(&dvnode->netfs.inode));
|
||||
ret = netfs_writeback_single(mapping, wbc, &iter);
|
||||
if (ret == 1)
|
||||
ret = 0; /* Skipped write due to lock conflict. */
|
||||
}
|
||||
|
||||
up_read(&dvnode->validate_lock);
|
||||
|
||||
@@ -830,6 +830,9 @@ static int netfs_write_folio_single(struct netfs_io_request *wreq,
|
||||
*
|
||||
* Write a monolithic, non-pagecache object back to the server and/or
|
||||
* the cache.
|
||||
*
|
||||
* Return: 0 if successful; 1 if skipped due to lock conflict and WB_SYNC_NONE;
|
||||
* or a negative error code.
|
||||
*/
|
||||
int netfs_writeback_single(struct address_space *mapping,
|
||||
struct writeback_control *wbc,
|
||||
@@ -846,8 +849,10 @@ int netfs_writeback_single(struct address_space *mapping,
|
||||
|
||||
if (!mutex_trylock(&ictx->wb_lock)) {
|
||||
if (wbc->sync_mode == WB_SYNC_NONE) {
|
||||
/* The VFS will have undirtied the inode. */
|
||||
netfs_single_mark_inode_dirty(&ictx->inode);
|
||||
netfs_stat(&netfs_n_wb_lock_skip);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
netfs_stat(&netfs_n_wb_lock_wait);
|
||||
mutex_lock(&ictx->wb_lock);
|
||||
|
||||
Reference in New Issue
Block a user