On Sun, Oct 06, 2019 at 05:45:59PM +0200, Christoph Hellwig wrote: > Takes the xfs writeback code and copies it to iomap.c. A new structure > with three methods is added as the abstraction from the generic > writeback code to the file system. These methods are used to map > blocks, submit an ioend, and cancel a page that encountered an error > before it was added to an ioend. > > Signed-off-by: Christoph Hellwig <hch@xxxxxx> > [darrick: create the new iomap code, we'll delete the xfs code separately] > Reviewed-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> ..... > +static int > +iomap_ioend_compare(void *priv, struct list_head *a, struct list_head *b) > +{ > + struct iomap_ioend *ia, *ib; > + > + ia = container_of(a, struct iomap_ioend, io_list); > + ib = container_of(b, struct iomap_ioend, io_list); > + if (ia->io_offset < ib->io_offset) > + return -1; > + else if (ia->io_offset > ib->io_offset) > + return 1; > + return 0; No need for the else here. > +/* > + * Test to see if we have an existing ioend structure that we could append to > + * first, otherwise finish off the current ioend and start another. > + */ > +static void > +iomap_add_to_ioend(struct inode *inode, loff_t offset, struct page *page, > + struct iomap_page *iop, struct iomap_writepage_ctx *wpc, > + struct writeback_control *wbc, struct list_head *iolist) > +{ > + sector_t sector = iomap_sector(&wpc->iomap, offset); > + unsigned len = i_blocksize(inode); > + unsigned poff = offset & (PAGE_SIZE - 1); > + bool merged, same_page = false; > + > + if (!wpc->ioend || > + (wpc->iomap.flags & IOMAP_F_SHARED) != > + (wpc->ioend->io_flags & IOMAP_F_SHARED) || This second line of the comparison should be indented further as it is a continuation of the the previous line's log statement, not a unique logic statement by itself. > + wpc->iomap.type != wpc->ioend->io_type || > + sector != bio_end_sector(wpc->ioend->io_bio) || > + offset != wpc->ioend->io_offset + wpc->ioend->io_size) { > + if (wpc->ioend) > + list_add(&wpc->ioend->io_list, iolist); > + wpc->ioend = iomap_alloc_ioend(inode, wpc, offset, sector, wbc); > + } ..... > +static int > +iomap_do_writepage(struct page *page, struct writeback_control *wbc, void *data) > +{ > + struct iomap_writepage_ctx *wpc = data; > + struct inode *inode = page->mapping->host; > + pgoff_t end_index; > + u64 end_offset; > + loff_t offset; > + > + trace_iomap_writepage(inode, page, 0, 0); > + > + /* > + * Refuse to write the page out if we are called from reclaim context. > + * > + * This avoids stack overflows when called from deeply used stacks in > + * random callers for direct reclaim or memcg reclaim. We explicitly > + * allow reclaim from kswapd as the stack usage there is relatively low. > + * > + * This should never happen except in the case of a VM regression so > + * warn about it. > + */ > + if (WARN_ON_ONCE((current->flags & (PF_MEMALLOC|PF_KSWAPD)) == > + PF_MEMALLOC)) > + goto redirty; > + > + /* > + * Given that we do not allow direct reclaim to call us, we should > + * never be called while in a filesystem transaction. > + */ > + if (WARN_ON_ONCE(current->flags & PF_MEMALLOC_NOFS)) > + goto redirty; Is this true for all expected callers of these functions rather than just XFS? i.e. PF_MEMALLOC_NOFS is used by transactions in XFS to prevent transaction context recursion, but other filesystems do not do this.. FWIW, I can also see that this is going to cause us problems if high level code starts using memalloc_nofs_save() and then calling filemap_datawrite() and friends... > +iomap_writepage(struct page *page, struct writeback_control *wbc, > + struct iomap_writepage_ctx *wpc, > + const struct iomap_writeback_ops *ops) > +{ > + int ret; > + > + wpc->ops = ops; > + ret = iomap_do_writepage(page, wbc, wpc); > + if (!wpc->ioend) > + return ret; > + return iomap_submit_ioend(wpc, wpc->ioend, ret); > +} > +EXPORT_SYMBOL_GPL(iomap_writepage); Can we kill ->writepage for iomap users, please? After all, we don't mostly don't allow memory reclaim to do writeback of dirty pages, and that's the only caller of ->writepage. Cheers, Dave. -- Dave Chinner david@xxxxxxxxxxxxx