Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

UDF: Add support for O_DIRECT

Add support for the O_DIRECT flag. There are two cases to deal with:

1. Small files stored in the ICB (inode control block?): just return 0
from the new udf_adinicb_direct_IO() handler to fall back to buffered
I/O.

2. Larger files, not stored in the ICB: nothing special here. Just call
blockdev_direct_IO() from our new udf_direct_IO() handler and tidy up
any blocks instantiated outside i_size on error. This is pretty
standard. Factor error handling code out of udf_write_begin() into new
function udf_write_failed() so it can also be called by udf_direct_IO().

Also change the whitespace in udf_aops to make it a bit neater.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Signed-off-by: Jan Kara <jack@suse.cz>

authored by

Ian Abbott and committed by
Jan Kara
5eec54fc 3f6bba82

+45 -16
+1 -1
arch/um/os-Linux/time.c
··· 114 114 skew += this_tick - last_tick; 115 115 116 116 while (skew >= one_tick) { 117 - alarm_handler(SIGVTALRM, NULL); 117 + alarm_handler(SIGVTALRM, NULL, NULL); 118 118 skew -= one_tick; 119 119 } 120 120
+9
fs/udf/file.c
··· 118 118 return simple_write_end(file, mapping, pos, len, copied, page, fsdata); 119 119 } 120 120 121 + static ssize_t udf_adinicb_direct_IO(int rw, struct kiocb *iocb, 122 + const struct iovec *iov, 123 + loff_t offset, unsigned long nr_segs) 124 + { 125 + /* Fallback to buffered I/O. */ 126 + return 0; 127 + } 128 + 121 129 const struct address_space_operations udf_adinicb_aops = { 122 130 .readpage = udf_adinicb_readpage, 123 131 .writepage = udf_adinicb_writepage, 124 132 .write_begin = udf_adinicb_write_begin, 125 133 .write_end = udf_adinicb_write_end, 134 + .direct_IO = udf_adinicb_direct_IO, 126 135 }; 127 136 128 137 static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
+35 -15
fs/udf/inode.c
··· 95 95 } 96 96 } 97 97 98 + static void udf_write_failed(struct address_space *mapping, loff_t to) 99 + { 100 + struct inode *inode = mapping->host; 101 + struct udf_inode_info *iinfo = UDF_I(inode); 102 + loff_t isize = inode->i_size; 103 + 104 + if (to > isize) { 105 + truncate_pagecache(inode, to, isize); 106 + if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 107 + down_write(&iinfo->i_data_sem); 108 + udf_truncate_extents(inode); 109 + up_write(&iinfo->i_data_sem); 110 + } 111 + } 112 + } 113 + 98 114 static int udf_writepage(struct page *page, struct writeback_control *wbc) 99 115 { 100 116 return block_write_full_page(page, udf_get_block, wbc); ··· 140 124 int ret; 141 125 142 126 ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block); 143 - if (unlikely(ret)) { 144 - struct inode *inode = mapping->host; 145 - struct udf_inode_info *iinfo = UDF_I(inode); 146 - loff_t isize = inode->i_size; 127 + if (unlikely(ret)) 128 + udf_write_failed(mapping, pos + len); 129 + return ret; 130 + } 147 131 148 - if (pos + len > isize) { 149 - truncate_pagecache(inode, pos + len, isize); 150 - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { 151 - down_write(&iinfo->i_data_sem); 152 - udf_truncate_extents(inode); 153 - up_write(&iinfo->i_data_sem); 154 - } 155 - } 156 - } 132 + static ssize_t udf_direct_IO(int rw, struct kiocb *iocb, 133 + const struct iovec *iov, 134 + loff_t offset, unsigned long nr_segs) 135 + { 136 + struct file *file = iocb->ki_filp; 137 + struct address_space *mapping = file->f_mapping; 138 + struct inode *inode = mapping->host; 139 + ssize_t ret; 157 140 141 + ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, 142 + udf_get_block); 143 + if (unlikely(ret < 0 && (rw & WRITE))) 144 + udf_write_failed(mapping, offset + iov_length(iov, nr_segs)); 158 145 return ret; 159 146 } 160 147 ··· 171 152 .readpages = udf_readpages, 172 153 .writepage = udf_writepage, 173 154 .writepages = udf_writepages, 174 - .write_begin = udf_write_begin, 175 - .write_end = generic_write_end, 155 + .write_begin = udf_write_begin, 156 + .write_end = generic_write_end, 157 + .direct_IO = udf_direct_IO, 176 158 .bmap = udf_bmap, 177 159 }; 178 160