Commit 187b5b8b authored by Jaegeuk Kim's avatar Jaegeuk Kim

f2fs: remove the own bi_private allocation

Previously f2fs allocates its own bi_private data structure all the time even
though we don't use it. But, can we remove this bi_private allocation?

This patch removes such the additional bi_private allocation.

1. Retrieve f2fs_sb_info from its page->mapping->host->i_sb.
 - This removes the usecases of bi_private in end_io.

2. Use bi_private only when we really need it.
 - The bi_private is used only when the checkpoint procedure is conducted.
 - When conducting the checkpoint, f2fs submits a META_FLUSH bio to wait its bio
completion.
 - Since we have no dependancies to remove bi_private now, let's just use
 bi_private pointer as the completion pointer.
Reviewed-by: default avatarGu Zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk.kim@samsung.com>
parent 8f99a946
...@@ -791,7 +791,7 @@ static void f2fs_end_io_write(struct bio *bio, int err) ...@@ -791,7 +791,7 @@ static void f2fs_end_io_write(struct bio *bio, int err)
{ {
const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1;
struct bio_private *p = bio->bi_private; struct f2fs_sb_info *sbi = F2FS_SB(bvec->bv_page->mapping->host->i_sb);
do { do {
struct page *page = bvec->bv_page; struct page *page = bvec->bv_page;
...@@ -802,21 +802,21 @@ static void f2fs_end_io_write(struct bio *bio, int err) ...@@ -802,21 +802,21 @@ static void f2fs_end_io_write(struct bio *bio, int err)
SetPageError(page); SetPageError(page);
if (page->mapping) if (page->mapping)
set_bit(AS_EIO, &page->mapping->flags); set_bit(AS_EIO, &page->mapping->flags);
set_ckpt_flags(p->sbi->ckpt, CP_ERROR_FLAG);
p->sbi->sb->s_flags |= MS_RDONLY; set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG);
sbi->sb->s_flags |= MS_RDONLY;
} }
end_page_writeback(page); end_page_writeback(page);
dec_page_count(p->sbi, F2FS_WRITEBACK); dec_page_count(sbi, F2FS_WRITEBACK);
} while (bvec >= bio->bi_io_vec); } while (bvec >= bio->bi_io_vec);
if (p->is_sync) if (bio->bi_private)
complete(p->wait); complete(bio->bi_private);
if (!get_pages(p->sbi, F2FS_WRITEBACK) && if (!get_pages(sbi, F2FS_WRITEBACK) &&
!list_empty(&p->sbi->cp_wait.task_list)) !list_empty(&sbi->cp_wait.task_list))
wake_up(&p->sbi->cp_wait); wake_up(&sbi->cp_wait);
kfree(p);
bio_put(bio); bio_put(bio);
} }
...@@ -838,7 +838,6 @@ static void do_submit_bio(struct f2fs_sb_info *sbi, ...@@ -838,7 +838,6 @@ static void do_submit_bio(struct f2fs_sb_info *sbi,
int rw = sync ? WRITE_SYNC : WRITE; int rw = sync ? WRITE_SYNC : WRITE;
enum page_type btype = PAGE_TYPE_OF_BIO(type); enum page_type btype = PAGE_TYPE_OF_BIO(type);
struct f2fs_bio_info *io = &sbi->write_io[btype]; struct f2fs_bio_info *io = &sbi->write_io[btype];
struct bio_private *p;
if (!io->bio) if (!io->bio)
return; return;
...@@ -851,18 +850,16 @@ static void do_submit_bio(struct f2fs_sb_info *sbi, ...@@ -851,18 +850,16 @@ static void do_submit_bio(struct f2fs_sb_info *sbi,
trace_f2fs_submit_write_bio(sbi->sb, rw, btype, io->bio); trace_f2fs_submit_write_bio(sbi->sb, rw, btype, io->bio);
p = io->bio->bi_private; /*
p->sbi = sbi; * META_FLUSH is only from the checkpoint procedure, and we should wait
io->bio->bi_end_io = f2fs_end_io_write; * this metadata bio for FS consistency.
*/
if (type == META_FLUSH) { if (type == META_FLUSH) {
DECLARE_COMPLETION_ONSTACK(wait); DECLARE_COMPLETION_ONSTACK(wait);
p->is_sync = true; io->bio->bi_private = &wait;
p->wait = &wait;
submit_bio(rw, io->bio); submit_bio(rw, io->bio);
wait_for_completion(&wait); wait_for_completion(&wait);
} else { } else {
p->is_sync = false;
submit_bio(rw, io->bio); submit_bio(rw, io->bio);
} }
io->bio = NULL; io->bio = NULL;
...@@ -897,18 +894,10 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, ...@@ -897,18 +894,10 @@ static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page,
do_submit_bio(sbi, type, false); do_submit_bio(sbi, type, false);
alloc_new: alloc_new:
if (io->bio == NULL) { if (io->bio == NULL) {
struct bio_private *priv;
retry:
priv = kmalloc(sizeof(struct bio_private), GFP_NOFS);
if (!priv) {
cond_resched();
goto retry;
}
bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi));
io->bio = f2fs_bio_alloc(bdev, bio_blocks); io->bio = f2fs_bio_alloc(bdev, bio_blocks);
io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr);
io->bio->bi_private = priv; io->bio->bi_end_io = f2fs_end_io_write;
/* /*
* The end_io will be assigned at the sumbission phase. * The end_io will be assigned at the sumbission phase.
* Until then, let bio_add_page() merge consecutive IOs as much * Until then, let bio_add_page() merge consecutive IOs as much
......
...@@ -92,13 +92,6 @@ ...@@ -92,13 +92,6 @@
#define MAX_BIO_BLOCKS(max_hw_blocks) \ #define MAX_BIO_BLOCKS(max_hw_blocks) \
(min((int)max_hw_blocks, BIO_MAX_PAGES)) (min((int)max_hw_blocks, BIO_MAX_PAGES))
/* during checkpoint, bio_private is used to synchronize the last bio */
struct bio_private {
struct f2fs_sb_info *sbi;
bool is_sync;
struct completion *wait;
};
/* /*
* indicate a block allocation direction: RIGHT and LEFT. * indicate a block allocation direction: RIGHT and LEFT.
* RIGHT means allocating new sections towards the end of volume. * RIGHT means allocating new sections towards the end of volume.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment