diff options
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r-- | fs/ext4/page-io.c | 325 |
1 files changed, 183 insertions, 142 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 4acf1f78881b..48786cdb5e6c 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -46,46 +46,121 @@ void ext4_exit_pageio(void) | |||
46 | } | 46 | } |
47 | 47 | ||
48 | /* | 48 | /* |
49 | * This function is called by ext4_evict_inode() to make sure there is | 49 | * Print an buffer I/O error compatible with the fs/buffer.c. This |
50 | * no more pending I/O completion work left to do. | 50 | * provides compatibility with dmesg scrapers that look for a specific |
51 | * buffer I/O error message. We really need a unified error reporting | ||
52 | * structure to userspace ala Digital Unix's uerf system, but it's | ||
53 | * probably not going to happen in my lifetime, due to LKML politics... | ||
51 | */ | 54 | */ |
52 | void ext4_ioend_shutdown(struct inode *inode) | 55 | static void buffer_io_error(struct buffer_head *bh) |
53 | { | 56 | { |
54 | wait_queue_head_t *wq = ext4_ioend_wq(inode); | 57 | char b[BDEVNAME_SIZE]; |
58 | printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", | ||
59 | bdevname(bh->b_bdev, b), | ||
60 | (unsigned long long)bh->b_blocknr); | ||
61 | } | ||
55 | 62 | ||
56 | wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0)); | 63 | static void ext4_finish_bio(struct bio *bio) |
57 | /* | 64 | { |
58 | * We need to make sure the work structure is finished being | 65 | int i; |
59 | * used before we let the inode get destroyed. | 66 | int error = !test_bit(BIO_UPTODATE, &bio->bi_flags); |
60 | */ | 67 | |
61 | if (work_pending(&EXT4_I(inode)->i_unwritten_work)) | 68 | for (i = 0; i < bio->bi_vcnt; i++) { |
62 | cancel_work_sync(&EXT4_I(inode)->i_unwritten_work); | 69 | struct bio_vec *bvec = &bio->bi_io_vec[i]; |
70 | struct page *page = bvec->bv_page; | ||
71 | struct buffer_head *bh, *head; | ||
72 | unsigned bio_start = bvec->bv_offset; | ||
73 | unsigned bio_end = bio_start + bvec->bv_len; | ||
74 | unsigned under_io = 0; | ||
75 | unsigned long flags; | ||
76 | |||
77 | if (!page) | ||
78 | continue; | ||
79 | |||
80 | if (error) { | ||
81 | SetPageError(page); | ||
82 | set_bit(AS_EIO, &page->mapping->flags); | ||
83 | } | ||
84 | bh = head = page_buffers(page); | ||
85 | /* | ||
86 | * We check all buffers in the page under BH_Uptodate_Lock | ||
87 | * to avoid races with other end io clearing async_write flags | ||
88 | */ | ||
89 | local_irq_save(flags); | ||
90 | bit_spin_lock(BH_Uptodate_Lock, &head->b_state); | ||
91 | do { | ||
92 | if (bh_offset(bh) < bio_start || | ||
93 | bh_offset(bh) + bh->b_size > bio_end) { | ||
94 | if (buffer_async_write(bh)) | ||
95 | under_io++; | ||
96 | continue; | ||
97 | } | ||
98 | clear_buffer_async_write(bh); | ||
99 | if (error) | ||
100 | buffer_io_error(bh); | ||
101 | } while ((bh = bh->b_this_page) != head); | ||
102 | bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); | ||
103 | local_irq_restore(flags); | ||
104 | if (!under_io) | ||
105 | end_page_writeback(page); | ||
106 | } | ||
63 | } | 107 | } |
64 | 108 | ||
65 | void ext4_free_io_end(ext4_io_end_t *io) | 109 | static void ext4_release_io_end(ext4_io_end_t *io_end) |
66 | { | 110 | { |
67 | BUG_ON(!io); | 111 | struct bio *bio, *next_bio; |
68 | BUG_ON(!list_empty(&io->list)); | 112 | |
69 | BUG_ON(io->flag & EXT4_IO_END_UNWRITTEN); | 113 | BUG_ON(!list_empty(&io_end->list)); |
114 | BUG_ON(io_end->flag & EXT4_IO_END_UNWRITTEN); | ||
115 | WARN_ON(io_end->handle); | ||
70 | 116 | ||
71 | if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count)) | 117 | if (atomic_dec_and_test(&EXT4_I(io_end->inode)->i_ioend_count)) |
72 | wake_up_all(ext4_ioend_wq(io->inode)); | 118 | wake_up_all(ext4_ioend_wq(io_end->inode)); |
73 | kmem_cache_free(io_end_cachep, io); | 119 | |
120 | for (bio = io_end->bio; bio; bio = next_bio) { | ||
121 | next_bio = bio->bi_private; | ||
122 | ext4_finish_bio(bio); | ||
123 | bio_put(bio); | ||
124 | } | ||
125 | if (io_end->flag & EXT4_IO_END_DIRECT) | ||
126 | inode_dio_done(io_end->inode); | ||
127 | if (io_end->iocb) | ||
128 | aio_complete(io_end->iocb, io_end->result, 0); | ||
129 | kmem_cache_free(io_end_cachep, io_end); | ||
74 | } | 130 | } |
75 | 131 | ||
76 | /* check a range of space and convert unwritten extents to written. */ | 132 | static void ext4_clear_io_unwritten_flag(ext4_io_end_t *io_end) |
133 | { | ||
134 | struct inode *inode = io_end->inode; | ||
135 | |||
136 | io_end->flag &= ~EXT4_IO_END_UNWRITTEN; | ||
137 | /* Wake up anyone waiting on unwritten extent conversion */ | ||
138 | if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) | ||
139 | wake_up_all(ext4_ioend_wq(inode)); | ||
140 | } | ||
141 | |||
142 | /* | ||
143 | * Check a range of space and convert unwritten extents to written. Note that | ||
144 | * we are protected from truncate touching same part of extent tree by the | ||
145 | * fact that truncate code waits for all DIO to finish (thus exclusion from | ||
146 | * direct IO is achieved) and also waits for PageWriteback bits. Thus we | ||
147 | * cannot get to ext4_ext_truncate() before all IOs overlapping that range are | ||
148 | * completed (happens from ext4_free_ioend()). | ||
149 | */ | ||
77 | static int ext4_end_io(ext4_io_end_t *io) | 150 | static int ext4_end_io(ext4_io_end_t *io) |
78 | { | 151 | { |
79 | struct inode *inode = io->inode; | 152 | struct inode *inode = io->inode; |
80 | loff_t offset = io->offset; | 153 | loff_t offset = io->offset; |
81 | ssize_t size = io->size; | 154 | ssize_t size = io->size; |
155 | handle_t *handle = io->handle; | ||
82 | int ret = 0; | 156 | int ret = 0; |
83 | 157 | ||
84 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," | 158 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," |
85 | "list->prev 0x%p\n", | 159 | "list->prev 0x%p\n", |
86 | io, inode->i_ino, io->list.next, io->list.prev); | 160 | io, inode->i_ino, io->list.next, io->list.prev); |
87 | 161 | ||
88 | ret = ext4_convert_unwritten_extents(inode, offset, size); | 162 | io->handle = NULL; /* Following call will use up the handle */ |
163 | ret = ext4_convert_unwritten_extents(handle, inode, offset, size); | ||
89 | if (ret < 0) { | 164 | if (ret < 0) { |
90 | ext4_msg(inode->i_sb, KERN_EMERG, | 165 | ext4_msg(inode->i_sb, KERN_EMERG, |
91 | "failed to convert unwritten extents to written " | 166 | "failed to convert unwritten extents to written " |
@@ -93,30 +168,22 @@ static int ext4_end_io(ext4_io_end_t *io) | |||
93 | "(inode %lu, offset %llu, size %zd, error %d)", | 168 | "(inode %lu, offset %llu, size %zd, error %d)", |
94 | inode->i_ino, offset, size, ret); | 169 | inode->i_ino, offset, size, ret); |
95 | } | 170 | } |
96 | /* Wake up anyone waiting on unwritten extent conversion */ | 171 | ext4_clear_io_unwritten_flag(io); |
97 | if (atomic_dec_and_test(&EXT4_I(inode)->i_unwritten)) | 172 | ext4_release_io_end(io); |
98 | wake_up_all(ext4_ioend_wq(inode)); | ||
99 | if (io->flag & EXT4_IO_END_DIRECT) | ||
100 | inode_dio_done(inode); | ||
101 | if (io->iocb) | ||
102 | aio_complete(io->iocb, io->result, 0); | ||
103 | return ret; | 173 | return ret; |
104 | } | 174 | } |
105 | 175 | ||
106 | static void dump_completed_IO(struct inode *inode) | 176 | static void dump_completed_IO(struct inode *inode, struct list_head *head) |
107 | { | 177 | { |
108 | #ifdef EXT4FS_DEBUG | 178 | #ifdef EXT4FS_DEBUG |
109 | struct list_head *cur, *before, *after; | 179 | struct list_head *cur, *before, *after; |
110 | ext4_io_end_t *io, *io0, *io1; | 180 | ext4_io_end_t *io, *io0, *io1; |
111 | 181 | ||
112 | if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { | 182 | if (list_empty(head)) |
113 | ext4_debug("inode %lu completed_io list is empty\n", | ||
114 | inode->i_ino); | ||
115 | return; | 183 | return; |
116 | } | ||
117 | 184 | ||
118 | ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); | 185 | ext4_debug("Dump inode %lu completed io list\n", inode->i_ino); |
119 | list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { | 186 | list_for_each_entry(io, head, list) { |
120 | cur = &io->list; | 187 | cur = &io->list; |
121 | before = cur->prev; | 188 | before = cur->prev; |
122 | io0 = container_of(before, ext4_io_end_t, list); | 189 | io0 = container_of(before, ext4_io_end_t, list); |
@@ -130,23 +197,30 @@ static void dump_completed_IO(struct inode *inode) | |||
130 | } | 197 | } |
131 | 198 | ||
132 | /* Add the io_end to per-inode completed end_io list. */ | 199 | /* Add the io_end to per-inode completed end_io list. */ |
133 | void ext4_add_complete_io(ext4_io_end_t *io_end) | 200 | static void ext4_add_complete_io(ext4_io_end_t *io_end) |
134 | { | 201 | { |
135 | struct ext4_inode_info *ei = EXT4_I(io_end->inode); | 202 | struct ext4_inode_info *ei = EXT4_I(io_end->inode); |
136 | struct workqueue_struct *wq; | 203 | struct workqueue_struct *wq; |
137 | unsigned long flags; | 204 | unsigned long flags; |
138 | 205 | ||
139 | BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); | 206 | BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); |
140 | wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; | ||
141 | |||
142 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); | 207 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); |
143 | if (list_empty(&ei->i_completed_io_list)) | 208 | if (io_end->handle) { |
144 | queue_work(wq, &ei->i_unwritten_work); | 209 | wq = EXT4_SB(io_end->inode->i_sb)->rsv_conversion_wq; |
145 | list_add_tail(&io_end->list, &ei->i_completed_io_list); | 210 | if (list_empty(&ei->i_rsv_conversion_list)) |
211 | queue_work(wq, &ei->i_rsv_conversion_work); | ||
212 | list_add_tail(&io_end->list, &ei->i_rsv_conversion_list); | ||
213 | } else { | ||
214 | wq = EXT4_SB(io_end->inode->i_sb)->unrsv_conversion_wq; | ||
215 | if (list_empty(&ei->i_unrsv_conversion_list)) | ||
216 | queue_work(wq, &ei->i_unrsv_conversion_work); | ||
217 | list_add_tail(&io_end->list, &ei->i_unrsv_conversion_list); | ||
218 | } | ||
146 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | 219 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); |
147 | } | 220 | } |
148 | 221 | ||
149 | static int ext4_do_flush_completed_IO(struct inode *inode) | 222 | static int ext4_do_flush_completed_IO(struct inode *inode, |
223 | struct list_head *head) | ||
150 | { | 224 | { |
151 | ext4_io_end_t *io; | 225 | ext4_io_end_t *io; |
152 | struct list_head unwritten; | 226 | struct list_head unwritten; |
@@ -155,8 +229,8 @@ static int ext4_do_flush_completed_IO(struct inode *inode) | |||
155 | int err, ret = 0; | 229 | int err, ret = 0; |
156 | 230 | ||
157 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); | 231 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); |
158 | dump_completed_IO(inode); | 232 | dump_completed_IO(inode, head); |
159 | list_replace_init(&ei->i_completed_io_list, &unwritten); | 233 | list_replace_init(head, &unwritten); |
160 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | 234 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); |
161 | 235 | ||
162 | while (!list_empty(&unwritten)) { | 236 | while (!list_empty(&unwritten)) { |
@@ -167,30 +241,25 @@ static int ext4_do_flush_completed_IO(struct inode *inode) | |||
167 | err = ext4_end_io(io); | 241 | err = ext4_end_io(io); |
168 | if (unlikely(!ret && err)) | 242 | if (unlikely(!ret && err)) |
169 | ret = err; | 243 | ret = err; |
170 | io->flag &= ~EXT4_IO_END_UNWRITTEN; | ||
171 | ext4_free_io_end(io); | ||
172 | } | 244 | } |
173 | return ret; | 245 | return ret; |
174 | } | 246 | } |
175 | 247 | ||
176 | /* | 248 | /* |
177 | * work on completed aio dio IO, to convert unwritten extents to extents | 249 | * work on completed IO, to convert unwritten extents to extents |
178 | */ | 250 | */ |
179 | void ext4_end_io_work(struct work_struct *work) | 251 | void ext4_end_io_rsv_work(struct work_struct *work) |
180 | { | 252 | { |
181 | struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info, | 253 | struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info, |
182 | i_unwritten_work); | 254 | i_rsv_conversion_work); |
183 | ext4_do_flush_completed_IO(&ei->vfs_inode); | 255 | ext4_do_flush_completed_IO(&ei->vfs_inode, &ei->i_rsv_conversion_list); |
184 | } | 256 | } |
185 | 257 | ||
186 | int ext4_flush_unwritten_io(struct inode *inode) | 258 | void ext4_end_io_unrsv_work(struct work_struct *work) |
187 | { | 259 | { |
188 | int ret; | 260 | struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info, |
189 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && | 261 | i_unrsv_conversion_work); |
190 | !(inode->i_state & I_FREEING)); | 262 | ext4_do_flush_completed_IO(&ei->vfs_inode, &ei->i_unrsv_conversion_list); |
191 | ret = ext4_do_flush_completed_IO(inode); | ||
192 | ext4_unwritten_wait(inode); | ||
193 | return ret; | ||
194 | } | 263 | } |
195 | 264 | ||
196 | ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) | 265 | ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) |
@@ -200,83 +269,70 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) | |||
200 | atomic_inc(&EXT4_I(inode)->i_ioend_count); | 269 | atomic_inc(&EXT4_I(inode)->i_ioend_count); |
201 | io->inode = inode; | 270 | io->inode = inode; |
202 | INIT_LIST_HEAD(&io->list); | 271 | INIT_LIST_HEAD(&io->list); |
272 | atomic_set(&io->count, 1); | ||
203 | } | 273 | } |
204 | return io; | 274 | return io; |
205 | } | 275 | } |
206 | 276 | ||
207 | /* | 277 | void ext4_put_io_end_defer(ext4_io_end_t *io_end) |
208 | * Print an buffer I/O error compatible with the fs/buffer.c. This | ||
209 | * provides compatibility with dmesg scrapers that look for a specific | ||
210 | * buffer I/O error message. We really need a unified error reporting | ||
211 | * structure to userspace ala Digital Unix's uerf system, but it's | ||
212 | * probably not going to happen in my lifetime, due to LKML politics... | ||
213 | */ | ||
214 | static void buffer_io_error(struct buffer_head *bh) | ||
215 | { | 278 | { |
216 | char b[BDEVNAME_SIZE]; | 279 | if (atomic_dec_and_test(&io_end->count)) { |
217 | printk(KERN_ERR "Buffer I/O error on device %s, logical block %llu\n", | 280 | if (!(io_end->flag & EXT4_IO_END_UNWRITTEN) || !io_end->size) { |
218 | bdevname(bh->b_bdev, b), | 281 | ext4_release_io_end(io_end); |
219 | (unsigned long long)bh->b_blocknr); | 282 | return; |
283 | } | ||
284 | ext4_add_complete_io(io_end); | ||
285 | } | ||
286 | } | ||
287 | |||
288 | int ext4_put_io_end(ext4_io_end_t *io_end) | ||
289 | { | ||
290 | int err = 0; | ||
291 | |||
292 | if (atomic_dec_and_test(&io_end->count)) { | ||
293 | if (io_end->flag & EXT4_IO_END_UNWRITTEN) { | ||
294 | err = ext4_convert_unwritten_extents(io_end->handle, | ||
295 | io_end->inode, io_end->offset, | ||
296 | io_end->size); | ||
297 | io_end->handle = NULL; | ||
298 | ext4_clear_io_unwritten_flag(io_end); | ||
299 | } | ||
300 | ext4_release_io_end(io_end); | ||
301 | } | ||
302 | return err; | ||
303 | } | ||
304 | |||
305 | ext4_io_end_t *ext4_get_io_end(ext4_io_end_t *io_end) | ||
306 | { | ||
307 | atomic_inc(&io_end->count); | ||
308 | return io_end; | ||
220 | } | 309 | } |
221 | 310 | ||
222 | static void ext4_end_bio(struct bio *bio, int error) | 311 | static void ext4_end_bio(struct bio *bio, int error) |
223 | { | 312 | { |
224 | ext4_io_end_t *io_end = bio->bi_private; | 313 | ext4_io_end_t *io_end = bio->bi_private; |
225 | struct inode *inode; | ||
226 | int i; | ||
227 | int blocksize; | ||
228 | sector_t bi_sector = bio->bi_sector; | 314 | sector_t bi_sector = bio->bi_sector; |
229 | 315 | ||
230 | BUG_ON(!io_end); | 316 | BUG_ON(!io_end); |
231 | inode = io_end->inode; | ||
232 | blocksize = 1 << inode->i_blkbits; | ||
233 | bio->bi_private = NULL; | ||
234 | bio->bi_end_io = NULL; | 317 | bio->bi_end_io = NULL; |
235 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) | 318 | if (test_bit(BIO_UPTODATE, &bio->bi_flags)) |
236 | error = 0; | 319 | error = 0; |
237 | for (i = 0; i < bio->bi_vcnt; i++) { | ||
238 | struct bio_vec *bvec = &bio->bi_io_vec[i]; | ||
239 | struct page *page = bvec->bv_page; | ||
240 | struct buffer_head *bh, *head; | ||
241 | unsigned bio_start = bvec->bv_offset; | ||
242 | unsigned bio_end = bio_start + bvec->bv_len; | ||
243 | unsigned under_io = 0; | ||
244 | unsigned long flags; | ||
245 | 320 | ||
246 | if (!page) | 321 | if (io_end->flag & EXT4_IO_END_UNWRITTEN) { |
247 | continue; | ||
248 | |||
249 | if (error) { | ||
250 | SetPageError(page); | ||
251 | set_bit(AS_EIO, &page->mapping->flags); | ||
252 | } | ||
253 | bh = head = page_buffers(page); | ||
254 | /* | 322 | /* |
255 | * We check all buffers in the page under BH_Uptodate_Lock | 323 | * Link bio into list hanging from io_end. We have to do it |
256 | * to avoid races with other end io clearing async_write flags | 324 | * atomically as bio completions can be racing against each |
325 | * other. | ||
257 | */ | 326 | */ |
258 | local_irq_save(flags); | 327 | bio->bi_private = xchg(&io_end->bio, bio); |
259 | bit_spin_lock(BH_Uptodate_Lock, &head->b_state); | 328 | } else { |
260 | do { | 329 | ext4_finish_bio(bio); |
261 | if (bh_offset(bh) < bio_start || | 330 | bio_put(bio); |
262 | bh_offset(bh) + blocksize > bio_end) { | ||
263 | if (buffer_async_write(bh)) | ||
264 | under_io++; | ||
265 | continue; | ||
266 | } | ||
267 | clear_buffer_async_write(bh); | ||
268 | if (error) | ||
269 | buffer_io_error(bh); | ||
270 | } while ((bh = bh->b_this_page) != head); | ||
271 | bit_spin_unlock(BH_Uptodate_Lock, &head->b_state); | ||
272 | local_irq_restore(flags); | ||
273 | if (!under_io) | ||
274 | end_page_writeback(page); | ||
275 | } | 331 | } |
276 | bio_put(bio); | ||
277 | 332 | ||
278 | if (error) { | 333 | if (error) { |
279 | io_end->flag |= EXT4_IO_END_ERROR; | 334 | struct inode *inode = io_end->inode; |
335 | |||
280 | ext4_warning(inode->i_sb, "I/O error writing to inode %lu " | 336 | ext4_warning(inode->i_sb, "I/O error writing to inode %lu " |
281 | "(offset %llu size %ld starting block %llu)", | 337 | "(offset %llu size %ld starting block %llu)", |
282 | inode->i_ino, | 338 | inode->i_ino, |
@@ -285,13 +341,7 @@ static void ext4_end_bio(struct bio *bio, int error) | |||
285 | (unsigned long long) | 341 | (unsigned long long) |
286 | bi_sector >> (inode->i_blkbits - 9)); | 342 | bi_sector >> (inode->i_blkbits - 9)); |
287 | } | 343 | } |
288 | 344 | ext4_put_io_end_defer(io_end); | |
289 | if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { | ||
290 | ext4_free_io_end(io_end); | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | ext4_add_complete_io(io_end); | ||
295 | } | 345 | } |
296 | 346 | ||
297 | void ext4_io_submit(struct ext4_io_submit *io) | 347 | void ext4_io_submit(struct ext4_io_submit *io) |
@@ -305,43 +355,38 @@ void ext4_io_submit(struct ext4_io_submit *io) | |||
305 | bio_put(io->io_bio); | 355 | bio_put(io->io_bio); |
306 | } | 356 | } |
307 | io->io_bio = NULL; | 357 | io->io_bio = NULL; |
308 | io->io_op = 0; | 358 | } |
359 | |||
360 | void ext4_io_submit_init(struct ext4_io_submit *io, | ||
361 | struct writeback_control *wbc) | ||
362 | { | ||
363 | io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); | ||
364 | io->io_bio = NULL; | ||
309 | io->io_end = NULL; | 365 | io->io_end = NULL; |
310 | } | 366 | } |
311 | 367 | ||
312 | static int io_submit_init(struct ext4_io_submit *io, | 368 | static int io_submit_init_bio(struct ext4_io_submit *io, |
313 | struct inode *inode, | 369 | struct buffer_head *bh) |
314 | struct writeback_control *wbc, | ||
315 | struct buffer_head *bh) | ||
316 | { | 370 | { |
317 | ext4_io_end_t *io_end; | ||
318 | struct page *page = bh->b_page; | ||
319 | int nvecs = bio_get_nr_vecs(bh->b_bdev); | 371 | int nvecs = bio_get_nr_vecs(bh->b_bdev); |
320 | struct bio *bio; | 372 | struct bio *bio; |
321 | 373 | ||
322 | io_end = ext4_init_io_end(inode, GFP_NOFS); | ||
323 | if (!io_end) | ||
324 | return -ENOMEM; | ||
325 | bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES)); | 374 | bio = bio_alloc(GFP_NOIO, min(nvecs, BIO_MAX_PAGES)); |
375 | if (!bio) | ||
376 | return -ENOMEM; | ||
326 | bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); | 377 | bio->bi_sector = bh->b_blocknr * (bh->b_size >> 9); |
327 | bio->bi_bdev = bh->b_bdev; | 378 | bio->bi_bdev = bh->b_bdev; |
328 | bio->bi_private = io->io_end = io_end; | ||
329 | bio->bi_end_io = ext4_end_bio; | 379 | bio->bi_end_io = ext4_end_bio; |
330 | 380 | bio->bi_private = ext4_get_io_end(io->io_end); | |
331 | io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); | ||
332 | |||
333 | io->io_bio = bio; | 381 | io->io_bio = bio; |
334 | io->io_op = (wbc->sync_mode == WB_SYNC_ALL ? WRITE_SYNC : WRITE); | ||
335 | io->io_next_block = bh->b_blocknr; | 382 | io->io_next_block = bh->b_blocknr; |
336 | return 0; | 383 | return 0; |
337 | } | 384 | } |
338 | 385 | ||
339 | static int io_submit_add_bh(struct ext4_io_submit *io, | 386 | static int io_submit_add_bh(struct ext4_io_submit *io, |
340 | struct inode *inode, | 387 | struct inode *inode, |
341 | struct writeback_control *wbc, | ||
342 | struct buffer_head *bh) | 388 | struct buffer_head *bh) |
343 | { | 389 | { |
344 | ext4_io_end_t *io_end; | ||
345 | int ret; | 390 | int ret; |
346 | 391 | ||
347 | if (io->io_bio && bh->b_blocknr != io->io_next_block) { | 392 | if (io->io_bio && bh->b_blocknr != io->io_next_block) { |
@@ -349,18 +394,14 @@ submit_and_retry: | |||
349 | ext4_io_submit(io); | 394 | ext4_io_submit(io); |
350 | } | 395 | } |
351 | if (io->io_bio == NULL) { | 396 | if (io->io_bio == NULL) { |
352 | ret = io_submit_init(io, inode, wbc, bh); | 397 | ret = io_submit_init_bio(io, bh); |
353 | if (ret) | 398 | if (ret) |
354 | return ret; | 399 | return ret; |
355 | } | 400 | } |
356 | io_end = io->io_end; | ||
357 | if (test_clear_buffer_uninit(bh)) | ||
358 | ext4_set_io_unwritten_flag(inode, io_end); | ||
359 | io->io_end->size += bh->b_size; | ||
360 | io->io_next_block++; | ||
361 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); | 401 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); |
362 | if (ret != bh->b_size) | 402 | if (ret != bh->b_size) |
363 | goto submit_and_retry; | 403 | goto submit_and_retry; |
404 | io->io_next_block++; | ||
364 | return 0; | 405 | return 0; |
365 | } | 406 | } |
366 | 407 | ||
@@ -432,7 +473,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io, | |||
432 | do { | 473 | do { |
433 | if (!buffer_async_write(bh)) | 474 | if (!buffer_async_write(bh)) |
434 | continue; | 475 | continue; |
435 | ret = io_submit_add_bh(io, inode, wbc, bh); | 476 | ret = io_submit_add_bh(io, inode, bh); |
436 | if (ret) { | 477 | if (ret) { |
437 | /* | 478 | /* |
438 | * We only get here on ENOMEM. Not much else | 479 | * We only get here on ENOMEM. Not much else |