netfs: Fix a few minor bugs in netfs_page_mkwrite()

We can't return with VM_FAULT_SIGBUS | VM_FAULT_LOCKED; the core
code will not unlock the folio in this instance.  Introduce a new
"unlock" error exit to handle this case.  Use it to handle
the "folio is truncated" check, and change the "writeback interrupted
by a fatal signal" to do a NOPAGE exit instead of letting the core
code install the folio currently under writeback before killing the
process.

Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Link: https://lore.kernel.org/r/20241005182307.3190401-3-willy@infradead.org
Signed-off-by: Christian Brauner <brauner@kernel.org>
This commit is contained in:
Matthew Wilcox (Oracle) 2024-10-05 19:23:04 +01:00 committed by Christian Brauner
parent fcd4904e2f
commit c6a90fe7f0
No known key found for this signature in database
GPG Key ID: 91C61BC06578DCA2

View File

@ -491,7 +491,9 @@ EXPORT_SYMBOL(netfs_file_write_iter);
/*
* Notification that a previously read-only page is about to become writable.
* Note that the caller indicates a single page of a multipage folio.
* The caller indicates the precise page that needs to be written to, but
* we only track group on a per-folio basis, so we block more often than
* we might otherwise.
*/
vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_group)
{
@ -501,7 +503,7 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
struct address_space *mapping = file->f_mapping;
struct inode *inode = file_inode(file);
struct netfs_inode *ictx = netfs_inode(inode);
vm_fault_t ret = VM_FAULT_RETRY;
vm_fault_t ret = VM_FAULT_NOPAGE;
int err;
_enter("%lx", folio->index);
@ -510,21 +512,15 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
if (folio_lock_killable(folio) < 0)
goto out;
if (folio->mapping != mapping) {
folio_unlock(folio);
ret = VM_FAULT_NOPAGE;
goto out;
}
if (folio_wait_writeback_killable(folio)) {
ret = VM_FAULT_LOCKED;
goto out;
}
if (folio->mapping != mapping)
goto unlock;
if (folio_wait_writeback_killable(folio) < 0)
goto unlock;
/* Can we see a streaming write here? */
if (WARN_ON(!folio_test_uptodate(folio))) {
ret = VM_FAULT_SIGBUS | VM_FAULT_LOCKED;
goto out;
ret = VM_FAULT_SIGBUS;
goto unlock;
}
group = netfs_folio_group(folio);
@ -559,5 +555,8 @@ vm_fault_t netfs_page_mkwrite(struct vm_fault *vmf, struct netfs_group *netfs_gr
out:
sb_end_pagefault(inode->i_sb);
return ret;
unlock:
folio_unlock(folio);
goto out;
}
EXPORT_SYMBOL(netfs_page_mkwrite);