Commit 5eec54fcde7e065eb3d8a6e70e61d90673ca706b
Committed by
Jan Kara
1 parent
3f6bba8237
Exists in
master
and in
20 other branches
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
fs/udf/file.c
... | ... | @@ -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, |
fs/udf/inode.c
... | ... | @@ -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 |