32
32
33
33
static 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])
37
+ static wait_queue_head_t ioend_wq [WQ_HASH_SZ ];
38
+
35
39
int __init ext4_init_pageio (void )
36
40
{
41
+ int i ;
42
+
37
43
io_page_cachep = KMEM_CACHE (ext4_io_page , SLAB_RECLAIM_ACCOUNT );
38
44
if (io_page_cachep == NULL )
39
45
return - ENOMEM ;
@@ -42,6 +48,8 @@ int __init ext4_init_pageio(void)
42
48
kmem_cache_destroy (io_page_cachep );
43
49
return - ENOMEM ;
44
50
}
51
+ for (i = 0 ; i < WQ_HASH_SZ ; i ++ )
52
+ init_waitqueue_head (& ioend_wq [i ]);
45
53
46
54
return 0 ;
47
55
}
@@ -52,24 +60,37 @@ void ext4_exit_pageio(void)
52
60
kmem_cache_destroy (io_page_cachep );
53
61
}
54
62
63
+ void 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
+
70
+ static void put_io_page (struct ext4_io_page * io_page )
71
+ {
72
+ if (atomic_dec_and_test (& io_page -> p_count )) {
73
+ end_page_writeback (io_page -> p_page );
74
+ put_page (io_page -> p_page );
75
+ kmem_cache_free (io_page_cachep , io_page );
76
+ }
77
+ }
78
+
55
79
void ext4_free_io_end (ext4_io_end_t * io )
56
80
{
57
81
int i ;
82
+ wait_queue_head_t * wq ;
58
83
59
84
BUG_ON (!io );
60
85
if (io -> page )
61
86
put_page (io -> page );
62
- for (i = 0 ; i < io -> num_io_pages ; i ++ ) {
63
- if (-- io -> pages [i ]-> p_count == 0 ) {
64
- struct page * page = io -> pages [i ]-> p_page ;
65
-
66
- end_page_writeback (page );
67
- put_page (page );
68
- kmem_cache_free (io_page_cachep , io -> pages [i ]);
69
- }
70
- }
87
+ for (i = 0 ; i < io -> num_io_pages ; i ++ )
88
+ put_io_page (io -> pages [i ]);
71
89
io -> num_io_pages = 0 ;
72
- iput (io -> inode );
90
+ wq = to_ioend_wq (io -> inode );
91
+ if (atomic_dec_and_test (& EXT4_I (io -> inode )-> i_ioend_count ) &&
92
+ waitqueue_active (wq ))
93
+ wake_up_all (wq );
73
94
kmem_cache_free (io_end_cachep , io );
74
95
}
75
96
@@ -142,8 +163,8 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
142
163
io = kmem_cache_alloc (io_end_cachep , flags );
143
164
if (io ) {
144
165
memset (io , 0 , sizeof (* io ));
145
- io -> inode = igrab ( inode );
146
- BUG_ON (! io -> inode ) ;
166
+ atomic_inc ( & EXT4_I ( inode ) -> i_ioend_count );
167
+ io -> inode = inode ;
147
168
INIT_WORK (& io -> work , ext4_end_io_work );
148
169
INIT_LIST_HEAD (& io -> list );
149
170
}
@@ -171,35 +192,15 @@ static void ext4_end_bio(struct bio *bio, int error)
171
192
struct workqueue_struct * wq ;
172
193
struct inode * inode ;
173
194
unsigned long flags ;
174
- ext4_fsblk_t err_block ;
175
195
int i ;
176
196
177
197
BUG_ON (!io_end );
178
- inode = io_end -> inode ;
179
198
bio -> bi_private = NULL ;
180
199
bio -> bi_end_io = NULL ;
181
200
if (test_bit (BIO_UPTODATE , & bio -> bi_flags ))
182
201
error = 0 ;
183
- err_block = bio -> bi_sector >> (inode -> i_blkbits - 9 );
184
202
bio_put (bio );
185
203
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
204
for (i = 0 ; i < io_end -> num_io_pages ; i ++ ) {
204
205
struct page * page = io_end -> pages [i ]-> p_page ;
205
206
struct buffer_head * bh , * head ;
@@ -236,13 +237,7 @@ static void ext4_end_bio(struct bio *bio, int error)
236
237
} while (bh != head );
237
238
}
238
239
239
- if (-- io_end -> pages [i ]-> p_count == 0 ) {
240
- struct page * page = io_end -> pages [i ]-> p_page ;
241
-
242
- end_page_writeback (page );
243
- put_page (page );
244
- kmem_cache_free (io_page_cachep , io_end -> pages [i ]);
245
- }
240
+ put_io_page (io_end -> pages [i ]);
246
241
247
242
/*
248
243
* If this is a partial write which happened to make
@@ -254,8 +249,19 @@ static void ext4_end_bio(struct bio *bio, int error)
254
249
if (!partial_write )
255
250
SetPageUptodate (page );
256
251
}
257
-
258
252
io_end -> num_io_pages = 0 ;
253
+ inode = io_end -> inode ;
254
+
255
+ if (error ) {
256
+ io_end -> flag |= EXT4_IO_END_ERROR ;
257
+ ext4_warning (inode -> i_sb , "I/O error writing to inode %lu "
258
+ "(offset %llu size %ld starting block %llu)" ,
259
+ inode -> i_ino ,
260
+ (unsigned long long ) io_end -> offset ,
261
+ (long ) io_end -> size ,
262
+ (unsigned long long )
263
+ bio -> bi_sector >> (inode -> i_blkbits - 9 ));
264
+ }
259
265
260
266
/* Add the io_end to per-inode completed io list*/
261
267
spin_lock_irqsave (& EXT4_I (inode )-> i_completed_io_lock , flags );
@@ -305,7 +311,6 @@ static int io_submit_init(struct ext4_io_submit *io,
305
311
bio -> bi_private = io -> io_end = io_end ;
306
312
bio -> bi_end_io = ext4_end_bio ;
307
313
308
- io_end -> inode = inode ;
309
314
io_end -> offset = (page -> index << PAGE_CACHE_SHIFT ) + bh_offset (bh );
310
315
311
316
io -> io_bio = bio ;
@@ -360,7 +365,7 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
360
365
if ((io_end -> num_io_pages == 0 ) ||
361
366
(io_end -> pages [io_end -> num_io_pages - 1 ] != io_page )) {
362
367
io_end -> pages [io_end -> num_io_pages ++ ] = io_page ;
363
- io_page -> p_count ++ ;
368
+ atomic_inc ( & io_page -> p_count ) ;
364
369
}
365
370
return 0 ;
366
371
}
@@ -389,7 +394,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
389
394
return - ENOMEM ;
390
395
}
391
396
io_page -> p_page = page ;
392
- io_page -> p_count = 0 ;
397
+ atomic_set ( & io_page -> p_count , 1 ) ;
393
398
get_page (page );
394
399
395
400
for (bh = head = page_buffers (page ), block_start = 0 ;
@@ -421,10 +426,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
421
426
* PageWriteback bit from the page to prevent the system from
422
427
* wedging later on.
423
428
*/
424
- if (io_page -> p_count == 0 ) {
425
- put_page (page );
426
- end_page_writeback (page );
427
- kmem_cache_free (io_page_cachep , io_page );
428
- }
429
+ put_io_page (io_page );
429
430
return ret ;
430
431
}
0 commit comments