VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
author: Miklos Szeredi <mszeredi@redhat.com> 2019-01-16 10:27:59 +0100 committer: Miklos Szeredi <mszeredi@redhat.com> 2019-02-13 13:15:12 +0100 commit: 7f305ca1928d8b7db69f428b10988a3aa3e81053 parent: 2fe93bd43264242e4568763d1b183b1cc58066ff
Commit Summary:
fuse: clean up fuse_writepage_in_flight()
Diffstat:
1 file changed, 22 insertions, 16 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 927d40dec376..8342df29815d 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1744,6 +1744,13 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data)
 		end_page_writeback(data->orig_pages[i]);
 }
 
+/*
+ * First recheck under fi->lock if the offending offset is still under
+ * writeback.  If yes, then iterate write requests, to see if there's one
+ * already added for a page at this offset.  If there's none, then insert this
+ * new request onto the auxiliary list, otherwise reuse the existing one by
+ * copying the new page contents over to the old temporary page.
+ */
 static bool fuse_writepage_in_flight(struct fuse_req *new_req,
 				     struct page *page)
 {
@@ -1751,9 +1758,8 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
 	struct fuse_inode *fi = get_fuse_inode(new_req->inode);
 	struct fuse_req *tmp;
 	struct fuse_req *old_req;
-	pgoff_t curr_index;
 
-	BUG_ON(new_req->num_pages != 0);
+	WARN_ON(new_req->num_pages != 0);
 
 	spin_lock(&fc->lock);
 	list_del(&new_req->writepages_entry);
@@ -1766,32 +1772,34 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
 
 	new_req->num_pages = 1;
 	for (tmp = old_req; tmp != NULL; tmp = tmp->misc.write.next) {
-		BUG_ON(tmp->inode != new_req->inode);
+		pgoff_t curr_index;
+
+		WARN_ON(tmp->inode != new_req->inode);
 		curr_index = tmp->misc.write.in.offset >> PAGE_SHIFT;
-		if (tmp->num_pages == 1 &&
-		    curr_index == page->index) {
-			old_req = tmp;
+		if (tmp->num_pages == 1 && curr_index == page->index &&
+		    test_bit(FR_PENDING, &tmp->flags)) {
+			copy_highpage(tmp->pages[0], page);
+			break;
 		}
 	}
 
-	if (old_req->num_pages == 1 && test_bit(FR_PENDING, &old_req->flags)) {
-		struct backing_dev_info *bdi = inode_to_bdi(page->mapping->host);
+	if (!tmp) {
+		new_req->misc.write.next = old_req->misc.write.next;
+		old_req->misc.write.next = new_req;
+	}
 
-		copy_highpage(old_req->pages[0], page);
-		spin_unlock(&fc->lock);
+	spin_unlock(&fc->lock);
+
+	if (tmp) {
+		struct backing_dev_info *bdi = inode_to_bdi(new_req->inode);
 
 		dec_wb_stat(&bdi->wb, WB_WRITEBACK);
 		dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP);
 		wb_writeout_inc(&bdi->wb);
 		fuse_writepage_free(fc, new_req);
 		fuse_request_free(new_req);
-		goto out;
-	} else {
-		new_req->misc.write.next = old_req->misc.write.next;
-		old_req->misc.write.next = new_req;
 	}
-	spin_unlock(&fc->lock);
-out:
+
 	return true;
 }