Skip to content

Commit

Permalink
Merge branch 'iomap-4.9-misc-fixes-1' into for-next
Browse files Browse the repository at this point in the history
  • Loading branch information
dchinner committed Oct 2, 2016
2 parents 0d5b0cf + e43c460 commit b036b97
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 0 deletions.
84 changes: 84 additions & 0 deletions fs/iomap.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -430,6 +512,8 @@ static int iomap_to_fiemap(struct fiemap_extent_info *fi,

if (iomap->flags & IOMAP_F_MERGED)
flags |= FIEMAP_EXTENT_MERGED;
if (iomap->flags & IOMAP_F_SHARED)
flags |= FIEMAP_EXTENT_SHARED;

return fiemap_fill_next_extent(fi, iomap->offset,
iomap->blkno != IOMAP_NULL_BLOCK ? iomap->blkno << 9: 0,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/iomap.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct vm_fault;
* Flags for iomap mappings:
*/
#define IOMAP_F_MERGED 0x01 /* contains multiple blocks/extents */
#define IOMAP_F_SHARED 0x02 /* block shared with another file */

/*
* Magic value for blkno:
Expand Down Expand Up @@ -64,6 +65,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,
Expand Down

0 comments on commit b036b97

Please sign in to comment.