diff options
Diffstat (limited to 'fs/ext4/page-io.c')
-rw-r--r-- | fs/ext4/page-io.c | 66 |
1 files changed, 25 insertions, 41 deletions
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 92f38ee13f8..7ce1d0b19c9 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -70,7 +70,6 @@ static void put_io_page(struct ext4_io_page *io_page) | |||
70 | void ext4_free_io_end(ext4_io_end_t *io) | 70 | void ext4_free_io_end(ext4_io_end_t *io) |
71 | { | 71 | { |
72 | int i; | 72 | int i; |
73 | wait_queue_head_t *wq; | ||
74 | 73 | ||
75 | BUG_ON(!io); | 74 | BUG_ON(!io); |
76 | if (io->page) | 75 | if (io->page) |
@@ -78,56 +77,43 @@ void ext4_free_io_end(ext4_io_end_t *io) | |||
78 | for (i = 0; i < io->num_io_pages; i++) | 77 | for (i = 0; i < io->num_io_pages; i++) |
79 | put_io_page(io->pages[i]); | 78 | put_io_page(io->pages[i]); |
80 | io->num_io_pages = 0; | 79 | io->num_io_pages = 0; |
81 | wq = ext4_ioend_wq(io->inode); | 80 | if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count)) |
82 | if (atomic_dec_and_test(&EXT4_I(io->inode)->i_ioend_count) && | 81 | wake_up_all(ext4_ioend_wq(io->inode)); |
83 | waitqueue_active(wq)) | ||
84 | wake_up_all(wq); | ||
85 | kmem_cache_free(io_end_cachep, io); | 82 | kmem_cache_free(io_end_cachep, io); |
86 | } | 83 | } |
87 | 84 | ||
88 | /* | 85 | /* |
89 | * check a range of space and convert unwritten extents to written. | 86 | * check a range of space and convert unwritten extents to written. |
87 | * | ||
88 | * Called with inode->i_mutex; we depend on this when we manipulate | ||
89 | * io->flag, since we could otherwise race with ext4_flush_completed_IO() | ||
90 | */ | 90 | */ |
91 | int ext4_end_io_nolock(ext4_io_end_t *io) | 91 | int ext4_end_io_nolock(ext4_io_end_t *io) |
92 | { | 92 | { |
93 | struct inode *inode = io->inode; | 93 | struct inode *inode = io->inode; |
94 | loff_t offset = io->offset; | 94 | loff_t offset = io->offset; |
95 | ssize_t size = io->size; | 95 | ssize_t size = io->size; |
96 | wait_queue_head_t *wq; | ||
97 | int ret = 0; | 96 | int ret = 0; |
98 | 97 | ||
99 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," | 98 | ext4_debug("ext4_end_io_nolock: io 0x%p from inode %lu,list->next 0x%p," |
100 | "list->prev 0x%p\n", | 99 | "list->prev 0x%p\n", |
101 | io, inode->i_ino, io->list.next, io->list.prev); | 100 | io, inode->i_ino, io->list.next, io->list.prev); |
102 | 101 | ||
103 | if (list_empty(&io->list)) | ||
104 | return ret; | ||
105 | |||
106 | if (!(io->flag & EXT4_IO_END_UNWRITTEN)) | ||
107 | return ret; | ||
108 | |||
109 | ret = ext4_convert_unwritten_extents(inode, offset, size); | 102 | ret = ext4_convert_unwritten_extents(inode, offset, size); |
110 | if (ret < 0) { | 103 | if (ret < 0) { |
111 | printk(KERN_EMERG "%s: failed to convert unwritten " | 104 | ext4_msg(inode->i_sb, KERN_EMERG, |
112 | "extents to written extents, error is %d " | 105 | "failed to convert unwritten extents to written " |
113 | "io is still on inode %lu aio dio list\n", | 106 | "extents -- potential data loss! " |
114 | __func__, ret, inode->i_ino); | 107 | "(inode %lu, offset %llu, size %zd, error %d)", |
115 | return ret; | 108 | inode->i_ino, offset, size, ret); |
116 | } | 109 | } |
117 | 110 | ||
118 | if (io->iocb) | 111 | if (io->iocb) |
119 | aio_complete(io->iocb, io->result, 0); | 112 | aio_complete(io->iocb, io->result, 0); |
120 | /* clear the DIO AIO unwritten flag */ | ||
121 | if (io->flag & EXT4_IO_END_UNWRITTEN) { | ||
122 | io->flag &= ~EXT4_IO_END_UNWRITTEN; | ||
123 | /* Wake up anyone waiting on unwritten extent conversion */ | ||
124 | wq = ext4_ioend_wq(io->inode); | ||
125 | if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten) && | ||
126 | waitqueue_active(wq)) { | ||
127 | wake_up_all(wq); | ||
128 | } | ||
129 | } | ||
130 | 113 | ||
114 | /* Wake up anyone waiting on unwritten extent conversion */ | ||
115 | if (atomic_dec_and_test(&EXT4_I(inode)->i_aiodio_unwritten)) | ||
116 | wake_up_all(ext4_ioend_wq(io->inode)); | ||
131 | return ret; | 117 | return ret; |
132 | } | 118 | } |
133 | 119 | ||
@@ -140,9 +126,15 @@ static void ext4_end_io_work(struct work_struct *work) | |||
140 | struct inode *inode = io->inode; | 126 | struct inode *inode = io->inode; |
141 | struct ext4_inode_info *ei = EXT4_I(inode); | 127 | struct ext4_inode_info *ei = EXT4_I(inode); |
142 | unsigned long flags; | 128 | unsigned long flags; |
143 | int ret; | 129 | |
130 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); | ||
131 | if (list_empty(&io->list)) { | ||
132 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | ||
133 | goto free; | ||
134 | } | ||
144 | 135 | ||
145 | if (!mutex_trylock(&inode->i_mutex)) { | 136 | if (!mutex_trylock(&inode->i_mutex)) { |
137 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | ||
146 | /* | 138 | /* |
147 | * Requeue the work instead of waiting so that the work | 139 | * Requeue the work instead of waiting so that the work |
148 | * items queued after this can be processed. | 140 | * items queued after this can be processed. |
@@ -159,17 +151,11 @@ static void ext4_end_io_work(struct work_struct *work) | |||
159 | io->flag |= EXT4_IO_END_QUEUED; | 151 | io->flag |= EXT4_IO_END_QUEUED; |
160 | return; | 152 | return; |
161 | } | 153 | } |
162 | ret = ext4_end_io_nolock(io); | 154 | list_del_init(&io->list); |
163 | if (ret < 0) { | ||
164 | mutex_unlock(&inode->i_mutex); | ||
165 | return; | ||
166 | } | ||
167 | |||
168 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); | ||
169 | if (!list_empty(&io->list)) | ||
170 | list_del_init(&io->list); | ||
171 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | 155 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); |
156 | (void) ext4_end_io_nolock(io); | ||
172 | mutex_unlock(&inode->i_mutex); | 157 | mutex_unlock(&inode->i_mutex); |
158 | free: | ||
173 | ext4_free_io_end(io); | 159 | ext4_free_io_end(io); |
174 | } | 160 | } |
175 | 161 | ||
@@ -350,10 +336,8 @@ submit_and_retry: | |||
350 | if ((io_end->num_io_pages >= MAX_IO_PAGES) && | 336 | if ((io_end->num_io_pages >= MAX_IO_PAGES) && |
351 | (io_end->pages[io_end->num_io_pages-1] != io_page)) | 337 | (io_end->pages[io_end->num_io_pages-1] != io_page)) |
352 | goto submit_and_retry; | 338 | goto submit_and_retry; |
353 | if (buffer_uninit(bh) && !(io_end->flag & EXT4_IO_END_UNWRITTEN)) { | 339 | if (buffer_uninit(bh)) |
354 | io_end->flag |= EXT4_IO_END_UNWRITTEN; | 340 | ext4_set_io_unwritten_flag(inode, io_end); |
355 | atomic_inc(&EXT4_I(inode)->i_aiodio_unwritten); | ||
356 | } | ||
357 | io->io_end->size += bh->b_size; | 341 | io->io_end->size += bh->b_size; |
358 | io->io_next_block++; | 342 | io->io_next_block++; |
359 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); | 343 | ret = bio_add_page(io->io_bio, bh->b_page, bh->b_size, bh_offset(bh)); |