aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/page-io.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r--fs/ext4/page-io.c59
1 files changed, 34 insertions, 25 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 46a7d6a9d97..a24c8cca737 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -32,8 +32,14 @@
32 32
33static struct kmem_cache *io_page_cachep, *io_end_cachep; 33static struct kmem_cache *io_page_cachep, *io_end_cachep;
34 34
35#define WQ_HASH_SZ 37
36#define to_ioend_wq(v) (&ioend_wq[((unsigned long)v) % WQ_HASH_SZ])
37static wait_queue_head_t ioend_wq[WQ_HASH_SZ];
38
35int __init ext4_init_pageio(void) 39int __init ext4_init_pageio(void)
36{ 40{
41 int i;
42
37 io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT); 43 io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT);
38 if (io_page_cachep == NULL) 44 if (io_page_cachep == NULL)
39 return -ENOMEM; 45 return -ENOMEM;
@@ -42,6 +48,8 @@ int __init ext4_init_pageio(void)
42 kmem_cache_destroy(io_page_cachep); 48 kmem_cache_destroy(io_page_cachep);
43 return -ENOMEM; 49 return -ENOMEM;
44 } 50 }
51 for (i = 0; i < WQ_HASH_SZ; i++)
52 init_waitqueue_head(&ioend_wq[i]);
45 53
46 return 0; 54 return 0;
47} 55}
@@ -52,9 +60,17 @@ void ext4_exit_pageio(void)
52 kmem_cache_destroy(io_page_cachep); 60 kmem_cache_destroy(io_page_cachep);
53} 61}
54 62
63void ext4_ioend_wait(struct inode *inode)
64{
65 wait_queue_head_t *wq = to_ioend_wq(inode);
66
67 wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0));
68}
69
55void ext4_free_io_end(ext4_io_end_t *io) 70void ext4_free_io_end(ext4_io_end_t *io)
56{ 71{
57 int i; 72 int i;
73 wait_queue_head_t *wq;
58 74
59 BUG_ON(!io); 75 BUG_ON(!io);
60 if (io->page) 76 if (io->page)
@@ -69,7 +85,10 @@ void ext4_free_io_end(ext4_io_end_t *io)
69 } 85 }
70 } 86 }
71 io->num_io_pages = 0; 87 io->num_io_pages = 0;
72 iput(io->inode); 88 wq = to_ioend_wq(io->inode);
89 if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) &&
90 waitqueue_active(wq))
91 wake_up_all(wq);
73 kmem_cache_free(io_end_cachep, io); 92 kmem_cache_free(io_end_cachep, io);
74} 93}
75 94
@@ -142,8 +161,8 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
142 io = kmem_cache_alloc(io_end_cachep, flags); 161 io = kmem_cache_alloc(io_end_cachep, flags);
143 if (io) { 162 if (io) {
144 memset(io, 0, sizeof(*io)); 163 memset(io, 0, sizeof(*io));
145 io->inode = igrab(inode); 164 atomic_inc(&EXT4_I(inode)->i_ioend_count);
146 BUG_ON(!io->inode); 165 io->inode = inode;
147 INIT_WORK(&io->work, ext4_end_io_work); 166 INIT_WORK(&io->work, ext4_end_io_work);
148 INIT_LIST_HEAD(&io->list); 167 INIT_LIST_HEAD(&io->list);
149 } 168 }
@@ -171,35 +190,15 @@ static void ext4_end_bio(struct bio *bio, int error)
171 struct workqueue_struct *wq; 190 struct workqueue_struct *wq;
172 struct inode *inode; 191 struct inode *inode;
173 unsigned long flags; 192 unsigned long flags;
174 ext4_fsblk_t err_block;
175 int i; 193 int i;
176 194
177 BUG_ON(!io_end); 195 BUG_ON(!io_end);
178 inode = io_end->inode;
179 bio->bi_private = NULL; 196 bio->bi_private = NULL;
180 bio->bi_end_io = NULL; 197 bio->bi_end_io = NULL;
181 if (test_bit(BIO_UPTODATE, &bio->bi_flags)) 198 if (test_bit(BIO_UPTODATE, &bio->bi_flags))
182 error = 0; 199 error = 0;
183 err_block = bio->bi_sector >> (inode->i_blkbits - 9);
184 bio_put(bio); 200 bio_put(bio);
185 201
186 if (!(inode->i_sb->s_flags & MS_ACTIVE)) {
187 pr_err("sb umounted, discard end_io request for inode %lu\n",
188 io_end->inode->i_ino);
189 ext4_free_io_end(io_end);
190 return;
191 }
192
193 if (error) {
194 io_end->flag |= EXT4_IO_END_ERROR;
195 ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
196 "(offset %llu size %ld starting block %llu)",
197 inode->i_ino,
198 (unsigned long long) io_end->offset,
199 (long) io_end->size,
200 (unsigned long long) err_block);
201 }
202
203 for (i = 0; i < io_end->num_io_pages; i++) { 202 for (i = 0; i < io_end->num_io_pages; i++) {
204 struct page *page = io_end->pages[i]->p_page; 203 struct page *page = io_end->pages[i]->p_page;
205 struct buffer_head *bh, *head; 204 struct buffer_head *bh, *head;
@@ -254,8 +253,19 @@ static void ext4_end_bio(struct bio *bio, int error)
254 if (!partial_write) 253 if (!partial_write)
255 SetPageUptodate(page); 254 SetPageUptodate(page);
256 } 255 }
257
258 io_end->num_io_pages = 0; 256 io_end->num_io_pages = 0;
257 inode = io_end->inode;
258
259 if (error) {
260 io_end->flag |= EXT4_IO_END_ERROR;
261 ext4_warning(inode->i_sb, "I/O error writing to inode %lu "
262 "(offset %llu size %ld starting block %llu)",
263 inode->i_ino,
264 (unsigned long long) io_end->offset,
265 (long) io_end->size,
266 (unsigned long long)
267 bio->bi_sector >> (inode->i_blkbits - 9));
268 }
259 269
260 /* Add the io_end to per-inode completed io list*/ 270 /* Add the io_end to per-inode completed io list*/
261 spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags); 271 spin_lock_irqsave(&EXT4_I(inode)->i_completed_io_lock, flags);
@@ -305,7 +315,6 @@ static int io_submit_init(struct ext4_io_submit *io,
305 bio->bi_private = io->io_end = io_end; 315 bio->bi_private = io->io_end = io_end;
306 bio->bi_end_io = ext4_end_bio; 316 bio->bi_end_io = ext4_end_bio;
307 317
308 io_end->inode = inode;
309 io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh); 318 io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
310 319
311 io->io_bio = bio; 320 io->io_bio = bio;