diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-11-18 22:47:22 -0500 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-22 20:18:01 -0500 |
commit | 1ff7bd3bb5f7f57bc7418ee6ed12f3ae217e4e9c (patch) | |
tree | 13501b9baf93ba8ba9f35355fc8b37a6c2da30b8 | |
parent | c11abd1a8075e428ecf5303359513b48193b29cd (diff) |
f2fs: introduce a bio array for per-page write bios
The f2fs has three bio types, NODE, DATA, and META, and manages some data
structures per each bio types.
The codes are a little bit messy, thus, this patch introduces a bio array
which groups individual data structures as follows.
struct f2fs_bio_info {
struct bio *bio; /* bios to merge */
sector_t last_block_in_bio; /* last block number */
struct mutex io_mutex; /* mutex for bio */
};
struct f2fs_sb_info {
...
struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */
...
};
The code changes from this new data structure are trivial.
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
-rw-r--r-- | fs/f2fs/f2fs.h | 12 | ||||
-rw-r--r-- | fs/f2fs/segment.c | 44 | ||||
-rw-r--r-- | fs/f2fs/super.c | 2 |
3 files changed, 32 insertions, 26 deletions
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index e9038bbeee9f..05f8fe1399ac 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h | |||
@@ -361,6 +361,12 @@ enum page_type { | |||
361 | META_FLUSH, | 361 | META_FLUSH, |
362 | }; | 362 | }; |
363 | 363 | ||
364 | struct f2fs_bio_info { | ||
365 | struct bio *bio; /* bios to merge */ | ||
366 | sector_t last_block_in_bio; /* last block number */ | ||
367 | struct mutex io_mutex; /* mutex for bio */ | ||
368 | }; | ||
369 | |||
364 | struct f2fs_sb_info { | 370 | struct f2fs_sb_info { |
365 | struct super_block *sb; /* pointer to VFS super block */ | 371 | struct super_block *sb; /* pointer to VFS super block */ |
366 | struct proc_dir_entry *s_proc; /* proc entry */ | 372 | struct proc_dir_entry *s_proc; /* proc entry */ |
@@ -374,9 +380,9 @@ struct f2fs_sb_info { | |||
374 | 380 | ||
375 | /* for segment-related operations */ | 381 | /* for segment-related operations */ |
376 | struct f2fs_sm_info *sm_info; /* segment manager */ | 382 | struct f2fs_sm_info *sm_info; /* segment manager */ |
377 | struct bio *bio[NR_PAGE_TYPE]; /* bios to merge */ | 383 | |
378 | sector_t last_block_in_bio[NR_PAGE_TYPE]; /* last block number */ | 384 | /* for bio operations */ |
379 | struct mutex write_mutex[NR_PAGE_TYPE]; /* mutex for writing IOs */ | 385 | struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */ |
380 | 386 | ||
381 | /* for checkpoint */ | 387 | /* for checkpoint */ |
382 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ | 388 | struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ |
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 68b8a2bdf6d8..38c1a89f54cc 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c | |||
@@ -836,65 +836,65 @@ static void do_submit_bio(struct f2fs_sb_info *sbi, | |||
836 | { | 836 | { |
837 | int rw = sync ? WRITE_SYNC : WRITE; | 837 | int rw = sync ? WRITE_SYNC : WRITE; |
838 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 838 | enum page_type btype = PAGE_TYPE_OF_BIO(type); |
839 | struct bio *bio = sbi->bio[btype]; | 839 | struct f2fs_bio_info *io = &sbi->write_io[btype]; |
840 | struct bio_private *p; | 840 | struct bio_private *p; |
841 | 841 | ||
842 | if (!bio) | 842 | if (!io->bio) |
843 | return; | 843 | return; |
844 | 844 | ||
845 | sbi->bio[btype] = NULL; | ||
846 | |||
847 | if (type >= META_FLUSH) | 845 | if (type >= META_FLUSH) |
848 | rw = WRITE_FLUSH_FUA; | 846 | rw = WRITE_FLUSH_FUA; |
849 | if (btype == META) | 847 | if (btype == META) |
850 | rw |= REQ_META; | 848 | rw |= REQ_META; |
851 | 849 | ||
852 | p = bio->bi_private; | 850 | p = io->bio->bi_private; |
853 | p->sbi = sbi; | 851 | p->sbi = sbi; |
854 | bio->bi_end_io = f2fs_end_io_write; | 852 | io->bio->bi_end_io = f2fs_end_io_write; |
855 | 853 | ||
856 | trace_f2fs_do_submit_bio(sbi->sb, btype, sync, bio); | 854 | trace_f2fs_do_submit_bio(sbi->sb, btype, sync, io->bio); |
857 | 855 | ||
858 | if (type == META_FLUSH) { | 856 | if (type == META_FLUSH) { |
859 | DECLARE_COMPLETION_ONSTACK(wait); | 857 | DECLARE_COMPLETION_ONSTACK(wait); |
860 | p->is_sync = true; | 858 | p->is_sync = true; |
861 | p->wait = &wait; | 859 | p->wait = &wait; |
862 | submit_bio(rw, bio); | 860 | submit_bio(rw, io->bio); |
863 | wait_for_completion(&wait); | 861 | wait_for_completion(&wait); |
864 | } else { | 862 | } else { |
865 | p->is_sync = false; | 863 | p->is_sync = false; |
866 | submit_bio(rw, bio); | 864 | submit_bio(rw, io->bio); |
867 | } | 865 | } |
866 | io->bio = NULL; | ||
868 | } | 867 | } |
869 | 868 | ||
870 | void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync) | 869 | void f2fs_submit_bio(struct f2fs_sb_info *sbi, enum page_type type, bool sync) |
871 | { | 870 | { |
872 | enum page_type btype = PAGE_TYPE_OF_BIO(type); | 871 | struct f2fs_bio_info *io = &sbi->write_io[PAGE_TYPE_OF_BIO(type)]; |
873 | 872 | ||
874 | if (!sbi->bio[btype]) | 873 | if (!io->bio) |
875 | return; | 874 | return; |
876 | 875 | ||
877 | mutex_lock(&sbi->write_mutex[btype]); | 876 | mutex_lock(&io->io_mutex); |
878 | do_submit_bio(sbi, type, sync); | 877 | do_submit_bio(sbi, type, sync); |
879 | mutex_unlock(&sbi->write_mutex[btype]); | 878 | mutex_unlock(&io->io_mutex); |
880 | } | 879 | } |
881 | 880 | ||
882 | static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, | 881 | static void submit_write_page(struct f2fs_sb_info *sbi, struct page *page, |
883 | block_t blk_addr, enum page_type type) | 882 | block_t blk_addr, enum page_type type) |
884 | { | 883 | { |
885 | struct block_device *bdev = sbi->sb->s_bdev; | 884 | struct block_device *bdev = sbi->sb->s_bdev; |
885 | struct f2fs_bio_info *io = &sbi->write_io[type]; | ||
886 | int bio_blocks; | 886 | int bio_blocks; |
887 | 887 | ||
888 | verify_block_addr(sbi, blk_addr); | 888 | verify_block_addr(sbi, blk_addr); |
889 | 889 | ||
890 | mutex_lock(&sbi->write_mutex[type]); | 890 | mutex_lock(&io->io_mutex); |
891 | 891 | ||
892 | inc_page_count(sbi, F2FS_WRITEBACK); | 892 | inc_page_count(sbi, F2FS_WRITEBACK); |
893 | 893 | ||
894 | if (sbi->bio[type] && sbi->last_block_in_bio[type] != blk_addr - 1) | 894 | if (io->bio && io->last_block_in_bio != blk_addr - 1) |
895 | do_submit_bio(sbi, type, false); | 895 | do_submit_bio(sbi, type, false); |
896 | alloc_new: | 896 | alloc_new: |
897 | if (sbi->bio[type] == NULL) { | 897 | if (io->bio == NULL) { |
898 | struct bio_private *priv; | 898 | struct bio_private *priv; |
899 | retry: | 899 | retry: |
900 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); | 900 | priv = kmalloc(sizeof(struct bio_private), GFP_NOFS); |
@@ -904,9 +904,9 @@ retry: | |||
904 | } | 904 | } |
905 | 905 | ||
906 | bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); | 906 | bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); |
907 | sbi->bio[type] = f2fs_bio_alloc(bdev, bio_blocks); | 907 | io->bio = f2fs_bio_alloc(bdev, bio_blocks); |
908 | sbi->bio[type]->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); | 908 | io->bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); |
909 | sbi->bio[type]->bi_private = priv; | 909 | io->bio->bi_private = priv; |
910 | /* | 910 | /* |
911 | * The end_io will be assigned at the sumbission phase. | 911 | * The end_io will be assigned at the sumbission phase. |
912 | * Until then, let bio_add_page() merge consecutive IOs as much | 912 | * Until then, let bio_add_page() merge consecutive IOs as much |
@@ -914,15 +914,15 @@ retry: | |||
914 | */ | 914 | */ |
915 | } | 915 | } |
916 | 916 | ||
917 | if (bio_add_page(sbi->bio[type], page, PAGE_CACHE_SIZE, 0) < | 917 | if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) < |
918 | PAGE_CACHE_SIZE) { | 918 | PAGE_CACHE_SIZE) { |
919 | do_submit_bio(sbi, type, false); | 919 | do_submit_bio(sbi, type, false); |
920 | goto alloc_new; | 920 | goto alloc_new; |
921 | } | 921 | } |
922 | 922 | ||
923 | sbi->last_block_in_bio[type] = blk_addr; | 923 | io->last_block_in_bio = blk_addr; |
924 | 924 | ||
925 | mutex_unlock(&sbi->write_mutex[type]); | 925 | mutex_unlock(&io->io_mutex); |
926 | trace_f2fs_submit_write_page(page, blk_addr, type); | 926 | trace_f2fs_submit_write_page(page, blk_addr, type); |
927 | } | 927 | } |
928 | 928 | ||
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index e194578b3594..8c677e958deb 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c | |||
@@ -879,7 +879,7 @@ static int f2fs_fill_super(struct super_block *sb, void *data, int silent) | |||
879 | spin_lock_init(&sbi->stat_lock); | 879 | spin_lock_init(&sbi->stat_lock); |
880 | 880 | ||
881 | for (i = 0; i < NR_PAGE_TYPE; i++) | 881 | for (i = 0; i < NR_PAGE_TYPE; i++) |
882 | mutex_init(&sbi->write_mutex[i]); | 882 | mutex_init(&sbi->write_io[i].io_mutex); |
883 | 883 | ||
884 | init_rwsem(&sbi->cp_rwsem); | 884 | init_rwsem(&sbi->cp_rwsem); |
885 | init_waitqueue_head(&sbi->cp_wait); | 885 | init_waitqueue_head(&sbi->cp_wait); |