@ -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 )
{