fuse: move rb_erase() before tree_insert()
authorMiklos Szeredi <mszeredi@redhat.com>
Tue, 14 Jul 2020 12:45:41 +0000 (14:45 +0200)
committerMiklos Szeredi <mszeredi@redhat.com>
Tue, 14 Jul 2020 12:45:41 +0000 (14:45 +0200)
In fuse_writepage_end() the old writepages entry needs to be removed from
the rbtree before inserting the new one, otherwise tree_insert() would
fail.  This is a very rare codepath and no reproducer exists.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/file.c

index e573b0c..7247c02 100644 (file)
@@ -1586,7 +1586,6 @@ static void fuse_writepage_finish(struct fuse_conn *fc,
        struct backing_dev_info *bdi = inode_to_bdi(inode);
        int i;
 
-       rb_erase(&wpa->writepages_entry, &fi->writepages);
        for (i = 0; i < ap->num_pages; i++) {
                dec_wb_stat(&bdi->wb, WB_WRITEBACK);
                dec_node_page_state(ap->pages[i], NR_WRITEBACK_TEMP);
@@ -1637,6 +1636,7 @@ __acquires(fi->lock)
 
  out_free:
        fi->writectr--;
+       rb_erase(&wpa->writepages_entry, &fi->writepages);
        fuse_writepage_finish(fc, wpa);
        spin_unlock(&fi->lock);
 
@@ -1714,6 +1714,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
 
        mapping_set_error(inode->i_mapping, error);
        spin_lock(&fi->lock);
+       rb_erase(&wpa->writepages_entry, &fi->writepages);
        while (wpa->next) {
                struct fuse_conn *fc = get_fuse_conn(inode);
                struct fuse_write_in *inarg = &wpa->ia.write.in;