Message ID | 147216786712.525.5901639662288553230.stgit@birch.djwong.org (mailing list archive) |
---|---|
State | Accepted, archived |
Headers | show |
On Thu, Aug 25, 2016 at 04:31:07PM -0700, Christoph Hellwig wrote: > Originally-from: Christoph Hellwig <hch@lst.de> This should be a From: Christoph Hellwig <hch@lst.de> so that git picks up authorship information correctly. > XXX: might want a bigger name, and possible a better implementation > that doesn't require two lookups in the radix tree. And these need to be looked into. I can take a stab at it, but I need to get a few other things off my plate first.
On Mon, Sep 05, 2016 at 07:57:51AM -0700, Christoph Hellwig wrote: > On Thu, Aug 25, 2016 at 04:31:07PM -0700, Christoph Hellwig wrote: > > Originally-from: Christoph Hellwig <hch@lst.de> > > This should be a > > From: Christoph Hellwig <hch@lst.de> > > so that git picks up authorship information correctly. > > > XXX: might want a bigger name, and possible a better implementation > > that doesn't require two lookups in the radix tree. > > And these need to be looked into. I can take a stab at it, but I need > to get a few other things off my plate first. Yeah. It works well enough for unsharing blocks, if inefficiently. Not sure what "a bigger name" means, though. I tried feeding the function prototype through figlet but gcc didn't like that. ;) --D
On Tue, Sep 06, 2016 at 10:34:28AM -0700, Darrick J. Wong wrote: > > > XXX: might want a bigger name, and possible a better implementation > > > that doesn't require two lookups in the radix tree. > > > > And these need to be looked into. I can take a stab at it, but I need > > to get a few other things off my plate first. > > Yeah. It works well enough for unsharing blocks, if inefficiently. > > Not sure what "a bigger name" means, though. I tried feeding the > function prototype through figlet but gcc didn't like that. ;) That should have been "better", sorry.
On Mon, Sep 05, 2016 at 07:57:51AM -0700, Christoph Hellwig wrote: > On Thu, Aug 25, 2016 at 04:31:07PM -0700, Christoph Hellwig wrote: > > Originally-from: Christoph Hellwig <hch@lst.de> > > This should be a > > From: Christoph Hellwig <hch@lst.de> > > so that git picks up authorship information correctly. > > > XXX: might want a bigger name, and possible a better implementation > > that doesn't require two lookups in the radix tree. > > And these need to be looked into. I can take a stab at it, but I need > to get a few other things off my plate first. Seeing as it works and isn't too ugly to live, I think I'm going to merge this as is. When a better implementation comes along we can replace it with that... Cheers, Dave.
diff --git a/fs/iomap.c b/fs/iomap.c index 0342254..7b295d5 100644 --- a/fs/iomap.c +++ b/fs/iomap.c @@ -252,6 +252,88 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *iter, } EXPORT_SYMBOL_GPL(iomap_file_buffered_write); +static struct page * +__iomap_read_page(struct inode *inode, loff_t offset) +{ + struct address_space *mapping = inode->i_mapping; + struct page *page; + + page = read_mapping_page(mapping, offset >> PAGE_SHIFT, NULL); + if (IS_ERR(page)) + return page; + if (!PageUptodate(page)) { + put_page(page); + return ERR_PTR(-EIO); + } + return page; +} + +static loff_t +iomap_dirty_actor(struct inode *inode, loff_t pos, loff_t length, void *data, + struct iomap *iomap) +{ + long status = 0; + ssize_t written = 0; + + do { + struct page *page, *rpage; + unsigned long offset; /* Offset into pagecache page */ + unsigned long bytes; /* Bytes to write to page */ + + offset = (pos & (PAGE_SIZE - 1)); + bytes = min_t(unsigned long, PAGE_SIZE - offset, length); + + rpage = __iomap_read_page(inode, pos); + if (IS_ERR(rpage)) + return PTR_ERR(rpage); + + status = iomap_write_begin(inode, pos, bytes, + AOP_FLAG_NOFS | AOP_FLAG_UNINTERRUPTIBLE, + &page, iomap); + put_page(rpage); + if (unlikely(status)) + return status; + + WARN_ON_ONCE(!PageUptodate(page)); + + status = iomap_write_end(inode, pos, bytes, bytes, page); + if (unlikely(status <= 0)) { + if (WARN_ON_ONCE(status == 0)) + return -EIO; + return status; + } + + cond_resched(); + + pos += status; + written += status; + length -= status; + + balance_dirty_pages_ratelimited(inode->i_mapping); + } while (length); + + return written; +} + +int +iomap_file_dirty(struct inode *inode, loff_t pos, loff_t len, + struct iomap_ops *ops) +{ + loff_t ret; + + while (len) { + ret = iomap_apply(inode, pos, len, IOMAP_WRITE, ops, NULL, + iomap_dirty_actor); + if (ret <= 0) + return ret; + pos += ret; + len -= ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(iomap_file_dirty); + static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset, unsigned bytes, struct iomap *iomap) { diff --git a/include/linux/iomap.h b/include/linux/iomap.h index 3267df4..b2e30e5 100644 --- a/include/linux/iomap.h +++ b/include/linux/iomap.h @@ -58,6 +58,8 @@ struct iomap_ops { ssize_t iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *from, struct iomap_ops *ops); +int iomap_file_dirty(struct inode *inode, loff_t pos, loff_t len, + struct iomap_ops *ops); int iomap_zero_range(struct inode *inode, loff_t pos, loff_t len, bool *did_zero, struct iomap_ops *ops); int iomap_truncate_page(struct inode *inode, loff_t pos, bool *did_zero,
Originally-from: Christoph Hellwig <hch@lst.de> This function uses the iomap infrastructure to re-write all pages in a given range. This is useful for doing a copy-up of COW ranges, and might be useful for scrubbing in the future. XXX: might want a bigger name, and possible a better implementation that doesn't require two lookups in the radix tree. Signed-off-by: Christoph Hellwig <hch@lst.de> --- fs/iomap.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/iomap.h | 2 + 2 files changed, 84 insertions(+)