[Devel] [PATCH RHEL10 COMMIT] fs/fuse: restore fuse_writepages() to mainstream behavior

Konstantin Khorenko khorenko at virtuozzo.com
Fri May 15 18:17:10 MSK 2026


The commit is pushed to "branch-rh10-6.12.0-55.52.1.5.x.vz10-ovz" and will appear at git at bitbucket.org:openvz/vzkernel.git
after rh10-6.12.0-55.52.1.5.25.vz10
------>
commit ec55dfedf369b2510ae2424a147545965b979838
Author: Liu Kui <kui.liu at virtuozzo.com>
Date:   Mon Apr 20 15:13:02 2026 +0800

    fs/fuse: restore fuse_writepages() to mainstream behavior
    
    Revert the fuse_writepages()/fuse_writepages_fill() changes introduced
    by 67d9ccc4cc1d ("fuse: fix writeback/release race"), which should have
    been dropped when 083cb0ac8e38 ("fuse: Wait inflight requests") landed.
    
    The reverted code has several problems:
    
     - It overrides write_cache_pages() errors with err = 0 after
       fuse_writepages_send(), silently swallowing writeback failures.
    
     - It releases and re-acquires the fuse_file reference (data->ff)
       between batches, which is unnecessary - the reference obtained
       at the start of the callback is valid for the entire iteration.
    
     - It uses BUG_ON() for conditions that are not fatal.
    
    Align with the upstream v6.12 behavior: acquire data->ff once at
    the top of fuse_writepages_fill(), keep it for the entire iteration,
    and release it once in fuse_writepages() after all batches are sent.
    
    Signed-off-by: Liu Kui <kui.liu at virtuozzo.com>
    Acked-by: Alexey Kuznetsov <kuznet at virtuozzo.com>
    
    Feature: vStorage
---
 fs/fuse/file.c | 27 +++++++++------------------
 1 file changed, 9 insertions(+), 18 deletions(-)

diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 11fb3996a2ac3..b84aac13bfc91 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1233,7 +1233,7 @@ void fuse_release_ff(struct inode *inode, struct fuse_file *ff)
 			struct fuse_inode *fi = get_fuse_inode(inode);
 			spin_lock(&fi->lock);
 			__fuse_file_put(ff);
-			wake_up(&get_fuse_inode(inode)->page_waitq);
+			wake_up(&fi->page_waitq);
 			spin_unlock(&fi->lock);
 		} else {
 			fuse_file_put(ff, false);
@@ -2724,17 +2724,20 @@ static int fuse_writepages_fill(struct folio *folio,
 	int err;
 	int check_for_blocked = 0;
 
-	BUG_ON(wpa && !data->ff);
-
 	if (!wpa && test_bit(FUSE_I_INVAL_FILES, &fi->state)) {
 		unlock_page(&folio->page);
 		return -EIO;
 	}
 
+	if (!data->ff) {
+		err = -EIO;
+		data->ff = fuse_write_file_get(fi);
+		if (!data->ff)
+			goto out_unlock;
+	}
+
 	if (wpa && fuse_writepage_need_send(fc, &folio->page, ap, data)) {
 		fuse_writepages_send(data);
-		fuse_release_ff(inode, data->ff);
-		data->ff = NULL;
 		data->wpa = NULL;
 	}
 
@@ -2757,13 +2760,6 @@ static int fuse_writepages_fill(struct folio *folio,
 	 * under writeback, so we can release the page lock.
 	 */
 	if (data->wpa == NULL) {
-		/* we can acquire ff here because we do have locked pages here! */
-		BUG_ON(data->ff);
-		err = -EIO;
-		data->ff = fuse_write_file_get(fi);
-		if (!data->ff)
-			goto out_unlock;
-
 		err = -ENOMEM;
 		wpa = fuse_writepage_args_setup(folio, data->ff);
 		if (!wpa) {
@@ -2794,8 +2790,6 @@ static int fuse_writepages_fill(struct folio *folio,
 		data->wpa = wpa;
 	} else {
 		folio_end_writeback(folio);
-		fuse_release_ff(inode, data->ff);
-		data->ff = NULL;
 	}
 out_unlock:
 	folio_unlock(folio);
@@ -2845,11 +2839,8 @@ static int fuse_writepages(struct address_space *mapping,
 	if (data.wpa) {
 		WARN_ON(!data.wpa->ia.ap.num_pages);
 		fuse_writepages_send(&data);
-		fuse_release_ff(inode, data.ff);
-		data.ff = NULL;
-		err = 0;
 	}
-	BUG_ON(data.ff);
+	fuse_release_ff(inode, data.ff);
 
 	kfree(data.orig_pages);
 out:


More information about the Devel mailing list