diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-04 09:14:01 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-04 09:14:01 -0700 | 
| commit | e1cc485262846dcad931bf85ee655cbbb815bfe6 (patch) | |
| tree | 5b3ae42ce41f9fe0149ad49e9811ac8f8e8b2016 /fs/udf | |
| parent | 4d6d367232813af09d9a1d90e3259e3ac42ee8a8 (diff) | |
| parent | 09e05d4805e6c524c1af74e524e5d0528bb3fef3 (diff) | |
| download | linux-e1cc485262846dcad931bf85ee655cbbb815bfe6.tar.bz2 | |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull ext3 & udf fixes from Jan Kara:
 "Shortlog pretty much says it all.
  The interesting bits are UDF support for direct IO and ext3 fix for a
  long standing oops in data=journal mode."
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  jbd: Fix assertion failure in commit code due to lacking transaction credits
  UDF: Add support for O_DIRECT
  ext3: Replace 0 with NULL for pointer in super.c file
  udf: add writepages support for udf
  ext3: don't clear orphan list on ro mount with errors
  reiserfs: Make reiserfs_xattr_handlers static
Diffstat (limited to 'fs/udf')
| -rw-r--r-- | fs/udf/file.c | 9 | ||||
| -rw-r--r-- | fs/udf/inode.c | 59 | 
2 files changed, 52 insertions, 16 deletions
| diff --git a/fs/udf/file.c b/fs/udf/file.c index d1c6093fd3d3..77b5953eaac8 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -118,11 +118,20 @@ static int udf_adinicb_write_end(struct file *file,  	return simple_write_end(file, mapping, pos, len, copied, page, fsdata);  } +static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, +				     const struct iovec *iov, +				     loff_t offset, unsigned long nr_segs) +{ +	/* Fallback to buffered I/O. */ +	return 0; +} +  const struct address_space_operations udf_adinicb_aops = {  	.readpage	= udf_adinicb_readpage,  	.writepage	= udf_adinicb_writepage,  	.write_begin	= udf_adinicb_write_begin,  	.write_end	= udf_adinicb_write_end, +	.direct_IO	= udf_adinicb_direct_IO,  };  static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov, diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 287ef9f587b7..df88b957ccf0 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -95,11 +95,33 @@ 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);  } +static int udf_writepages(struct address_space *mapping, +			struct writeback_control *wbc) +{ +	return mpage_writepages(mapping, wbc, udf_get_block); +} +  static int udf_readpage(struct file *file, struct page *page)  {  	return mpage_readpage(page, udf_get_block); @@ -118,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;  } @@ -145,8 +170,10 @@ const struct address_space_operations udf_aops = {  	.readpage	= udf_readpage,  	.readpages	= udf_readpages,  	.writepage	= udf_writepage, -	.write_begin		= udf_write_begin, -	.write_end		= generic_write_end, +	.writepages	= udf_writepages, +	.write_begin	= udf_write_begin, +	.write_end	= generic_write_end, +	.direct_IO	= udf_direct_IO,  	.bmap		= udf_bmap,  }; |