mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
fuse: clean up fuse_writepage_in_flight()
Restructure the function to better separate the locked and the unlocked parts. Use the "old_req" local variable to mean only the queued request, and not any auxiliary requests added onto its misc.write.next list. These changes are in preparation for the following patch. Also turn BUG_ON instances into WARN_ON and add a header comment explaining what the function does. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
2fe93bd432
commit
7f305ca192
1 changed files with 24 additions and 16 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue