Skip to content

Commit a7bcf21

Browse files
committed
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: Add new ext4 inode tracepoints ext4: Don't call sb_issue_discard() in ext4_free_blocks() ext4: do not try to grab the s_umount semaphore in ext4_quota_off ext4: fix potential race when freeing ext4_io_page structures ext4: handle writeback of inodes which are being freed ext4: initialize the percpu counters before replaying the journal ext4: "ret" may be used uninitialized in ext4_lazyinit_thread() ext4: fix lazyinit hang after removing request
2 parents 5398a64 + 7ff9c07 commit a7bcf21

File tree

6 files changed

+214
-91
lines changed

6 files changed

+214
-91
lines changed

fs/ext4/ext4.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ struct mpage_da_data {
177177

178178
struct ext4_io_page {
179179
struct page *p_page;
180-
int p_count;
180+
atomic_t p_count;
181181
};
182182

183183
#define MAX_IO_PAGES 128
@@ -858,6 +858,7 @@ struct ext4_inode_info {
858858
spinlock_t i_completed_io_lock;
859859
/* current io_end structure for async DIO write*/
860860
ext4_io_end_t *cur_aio_dio;
861+
atomic_t i_ioend_count; /* Number of outstanding io_end structs */
861862

862863
/*
863864
* Transactions that contain inode's metadata needed to complete
@@ -2060,6 +2061,7 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
20602061
/* page-io.c */
20612062
extern int __init ext4_init_pageio(void);
20622063
extern void ext4_exit_pageio(void);
2064+
extern void ext4_ioend_wait(struct inode *);
20632065
extern void ext4_free_io_end(ext4_io_end_t *io);
20642066
extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
20652067
extern int ext4_end_io_nolock(ext4_io_end_t *io);

fs/ext4/inode.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
static inline int ext4_begin_ordered_truncate(struct inode *inode,
5454
loff_t new_size)
5555
{
56+
trace_ext4_begin_ordered_truncate(inode, new_size);
5657
return jbd2_journal_begin_ordered_truncate(
5758
EXT4_SB(inode->i_sb)->s_journal,
5859
&EXT4_I(inode)->jinode,
@@ -178,6 +179,7 @@ void ext4_evict_inode(struct inode *inode)
178179
handle_t *handle;
179180
int err;
180181

182+
trace_ext4_evict_inode(inode);
181183
if (inode->i_nlink) {
182184
truncate_inode_pages(&inode->i_data, 0);
183185
goto no_delete;
@@ -5647,6 +5649,7 @@ int ext4_mark_inode_dirty(handle_t *handle, struct inode *inode)
56475649
int err, ret;
56485650

56495651
might_sleep();
5652+
trace_ext4_mark_inode_dirty(inode, _RET_IP_);
56505653
err = ext4_reserve_inode_write(handle, inode, &iloc);
56515654
if (ext4_handle_valid(handle) &&
56525655
EXT4_I(inode)->i_extra_isize < sbi->s_want_extra_isize &&

fs/ext4/mballoc.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4640,8 +4640,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
46404640
* with group lock held. generate_buddy look at
46414641
* them with group lock_held
46424642
*/
4643-
if (test_opt(sb, DISCARD))
4644-
ext4_issue_discard(sb, block_group, bit, count);
46454643
ext4_lock_group(sb, block_group);
46464644
mb_clear_bits(bitmap_bh->b_data, bit, count);
46474645
mb_free_blocks(inode, &e4b, bit, count);

fs/ext4/page-io.c

Lines changed: 49 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,14 @@
3232

3333
static struct kmem_cache *io_page_cachep, *io_end_cachep;
3434

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+
3539
int __init ext4_init_pageio(void)
3640
{
41+
int i;
42+
3743
io_page_cachep = KMEM_CACHE(ext4_io_page, SLAB_RECLAIM_ACCOUNT);
3844
if (io_page_cachep == NULL)
3945
return -ENOMEM;
@@ -42,6 +48,8 @@ int __init ext4_init_pageio(void)
4248
kmem_cache_destroy(io_page_cachep);
4349
return -ENOMEM;
4450
}
51+
for (i = 0; i < WQ_HASH_SZ; i++)
52+
init_waitqueue_head(&ioend_wq[i]);
4553

4654
return 0;
4755
}
@@ -52,24 +60,37 @@ void ext4_exit_pageio(void)
5260
kmem_cache_destroy(io_page_cachep);
5361
}
5462

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+
5579
void ext4_free_io_end(ext4_io_end_t *io)
5680
{
5781
int i;
82+
wait_queue_head_t *wq;
5883

5984
BUG_ON(!io);
6085
if (io->page)
6186
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]);
7189
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);
7394
kmem_cache_free(io_end_cachep, io);
7495
}
7596

@@ -142,8 +163,8 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags)
142163
io = kmem_cache_alloc(io_end_cachep, flags);
143164
if (io) {
144165
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;
147168
INIT_WORK(&io->work, ext4_end_io_work);
148169
INIT_LIST_HEAD(&io->list);
149170
}
@@ -171,35 +192,15 @@ static void ext4_end_bio(struct bio *bio, int error)
171192
struct workqueue_struct *wq;
172193
struct inode *inode;
173194
unsigned long flags;
174-
ext4_fsblk_t err_block;
175195
int i;
176196

177197
BUG_ON(!io_end);
178-
inode = io_end->inode;
179198
bio->bi_private = NULL;
180199
bio->bi_end_io = NULL;
181200
if (test_bit(BIO_UPTODATE, &bio->bi_flags))
182201
error = 0;
183-
err_block = bio->bi_sector >> (inode->i_blkbits - 9);
184202
bio_put(bio);
185203

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-
203204
for (i = 0; i < io_end->num_io_pages; i++) {
204205
struct page *page = io_end->pages[i]->p_page;
205206
struct buffer_head *bh, *head;
@@ -236,13 +237,7 @@ static void ext4_end_bio(struct bio *bio, int error)
236237
} while (bh != head);
237238
}
238239

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]);
246241

247242
/*
248243
* If this is a partial write which happened to make
@@ -254,8 +249,19 @@ static void ext4_end_bio(struct bio *bio, int error)
254249
if (!partial_write)
255250
SetPageUptodate(page);
256251
}
257-
258252
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+
}
259265

260266
/* Add the io_end to per-inode completed io list*/
261267
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,
305311
bio->bi_private = io->io_end = io_end;
306312
bio->bi_end_io = ext4_end_bio;
307313

308-
io_end->inode = inode;
309314
io_end->offset = (page->index << PAGE_CACHE_SHIFT) + bh_offset(bh);
310315

311316
io->io_bio = bio;
@@ -360,7 +365,7 @@ static int io_submit_add_bh(struct ext4_io_submit *io,
360365
if ((io_end->num_io_pages == 0) ||
361366
(io_end->pages[io_end->num_io_pages-1] != io_page)) {
362367
io_end->pages[io_end->num_io_pages++] = io_page;
363-
io_page->p_count++;
368+
atomic_inc(&io_page->p_count);
364369
}
365370
return 0;
366371
}
@@ -389,7 +394,7 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
389394
return -ENOMEM;
390395
}
391396
io_page->p_page = page;
392-
io_page->p_count = 0;
397+
atomic_set(&io_page->p_count, 1);
393398
get_page(page);
394399

395400
for (bh = head = page_buffers(page), block_start = 0;
@@ -421,10 +426,6 @@ int ext4_bio_write_page(struct ext4_io_submit *io,
421426
* PageWriteback bit from the page to prevent the system from
422427
* wedging later on.
423428
*/
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);
429430
return ret;
430431
}

0 commit comments

Comments
 (0)