Commit 5eec54fcde7e065eb3d8a6e70e61d90673ca706b

Authored by Ian Abbott
Committed by Jan Kara
1 parent 3f6bba8237

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>

Showing 3 changed files with 46 additions and 17 deletions Side-by-side Diff

arch/um/os-Linux/time.c
... ... @@ -114,7 +114,7 @@
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  
... ... @@ -118,11 +118,20 @@
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,
... ... @@ -95,6 +95,22 @@
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);
101 117  
102 118  
... ... @@ -124,21 +140,24 @@
124 140 int ret;
125 141  
126 142 ret = block_write_begin(mapping, pos, len, flags, pagep, udf_get_block);
127   - if (unlikely(ret)) {
128   - struct inode *inode = mapping->host;
129   - struct udf_inode_info *iinfo = UDF_I(inode);
130   - loff_t isize = inode->i_size;
  143 + if (unlikely(ret))
  144 + udf_write_failed(mapping, pos + len);
  145 + return ret;
  146 +}
131 147  
132   - if (pos + len > isize) {
133   - truncate_pagecache(inode, pos + len, isize);
134   - if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
135   - down_write(&iinfo->i_data_sem);
136   - udf_truncate_extents(inode);
137   - up_write(&iinfo->i_data_sem);
138   - }
139   - }
140   - }
  148 +static ssize_t udf_direct_IO(int rw, struct kiocb *iocb,
  149 + const struct iovec *iov,
  150 + loff_t offset, unsigned long nr_segs)
  151 +{
  152 + struct file *file = iocb->ki_filp;
  153 + struct address_space *mapping = file->f_mapping;
  154 + struct inode *inode = mapping->host;
  155 + ssize_t ret;
141 156  
  157 + ret = blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs,
  158 + udf_get_block);
  159 + if (unlikely(ret < 0 && (rw & WRITE)))
  160 + udf_write_failed(mapping, offset + iov_length(iov, nr_segs));
142 161 return ret;
143 162 }
144 163  
... ... @@ -152,8 +171,9 @@
152 171 .readpages = udf_readpages,
153 172 .writepage = udf_writepage,
154 173 .writepages = udf_writepages,
155   - .write_begin = udf_write_begin,
156   - .write_end = generic_write_end,
  174 + .write_begin = udf_write_begin,
  175 + .write_end = generic_write_end,
  176 + .direct_IO = udf_direct_IO,
157 177 .bmap = udf_bmap,
158 178 };
159 179