|
@@ -95,6 +95,22 @@ void udf_evict_inode(struct inode *inode)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static void udf_write_failed(struct address_space *mapping, loff_t to)
|
|
|
+{
|
|
|
+ struct inode *inode = mapping->host;
|
|
|
+ struct udf_inode_info *iinfo = UDF_I(inode);
|
|
|
+ loff_t isize = inode->i_size;
|
|
|
+
|
|
|
+ if (to > isize) {
|
|
|
+ truncate_pagecache(inode, to, isize);
|
|
|
+ if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
|
|
|
+ down_write(&iinfo->i_data_sem);
|
|
|
+ udf_truncate_extents(inode);
|
|
|
+ up_write(&iinfo->i_data_sem);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int udf_writepage(struct page *page, struct writeback_control *wbc)
|
|
|
{
|
|
|
return block_write_full_page(page, udf_get_block, wbc);
|
|
@@ -124,21 +140,24 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,
|
|
|
int ret;
|
|
|
|
|
|
ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block);
|
|
|
- if (unlikely(ret)) {
|
|
|
- struct inode *inode = mapping->host;
|
|
|
- struct udf_inode_info *iinfo = UDF_I(inode);
|
|
|
- loff_t isize = inode->i_size;
|
|
|
-
|
|
|
- if (pos + len > isize) {
|
|
|
- truncate_pagecache(inode, pos + len, isize);
|
|
|
- if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
|
|
|
- down_write(&iinfo->i_data_sem);
|
|
|
- udf_truncate_extents(inode);
|
|
|
- up_write(&iinfo->i_data_sem);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ if (unlikely(ret))
|
|
|
+ udf_write_failed(mapping, pos + len);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
+static ssize_t udf_direct_IO(int rw, struct kiocb *iocb,
|
|
|
+ const struct iovec *iov,
|
|
|
+ loff_t offset, unsigned long nr_segs)
|
|
|
+{
|
|
|
+ struct file *file = iocb->ki_filp;
|
|
|
+ struct address_space *mapping = file->f_mapping;
|
|
|
+ struct inode *inode = mapping->host;
|
|
|
+ ssize_t ret;
|
|
|
+
|
|
|
+ ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
|
|
|
+ udf_get_block);
|
|
|
+ if (unlikely(ret < 0 && (rw & WRITE)))
|
|
|
+ udf_write_failed(mapping, offset + iov_length(iov, nr_segs));
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -152,8 +171,9 @@ const struct address_space_operations udf_aops = {
|
|
|
.readpages = udf_readpages,
|
|
|
.writepage = udf_writepage,
|
|
|
.writepages = udf_writepages,
|
|
|
- .write_begin = udf_write_begin,
|
|
|
- .write_end = generic_write_end,
|
|
|
+ .write_begin = udf_write_begin,
|
|
|
+ .write_end = generic_write_end,
|
|
|
+ .direct_IO = udf_direct_IO,
|
|
|
.bmap = udf_bmap,
|
|
|
};
|
|
|
|