2929#define NUM_PREALLOC_POST_READ_CTXS 128
3030
3131static struct kmem_cache * bio_post_read_ctx_cache ;
32+ static struct kmem_cache * bio_entry_slab ;
3233static mempool_t * bio_post_read_ctx_pool ;
3334
3435static bool __is_cp_guaranteed (struct page * page )
@@ -543,6 +544,126 @@ static bool io_is_mergeable(struct f2fs_sb_info *sbi, struct bio *bio,
543544 return io_type_is_mergeable (io , fio );
544545}
545546
547+ static void add_bio_entry (struct f2fs_sb_info * sbi , struct bio * bio ,
548+ struct page * page , enum temp_type temp )
549+ {
550+ struct f2fs_bio_info * io = sbi -> write_io [DATA ] + temp ;
551+ struct bio_entry * be ;
552+
553+ be = f2fs_kmem_cache_alloc (bio_entry_slab , GFP_NOFS );
554+ be -> bio = bio ;
555+ bio_get (bio );
556+
557+ if (bio_add_page (bio , page , PAGE_SIZE , 0 ) != PAGE_SIZE )
558+ f2fs_bug_on (sbi , 1 );
559+
560+ down_write (& io -> bio_list_lock );
561+ list_add_tail (& be -> list , & io -> bio_list );
562+ up_write (& io -> bio_list_lock );
563+ }
564+
565+ static void del_bio_entry (struct bio_entry * be )
566+ {
567+ list_del (& be -> list );
568+ kmem_cache_free (bio_entry_slab , be );
569+ }
570+
571+ static int add_ipu_page (struct f2fs_sb_info * sbi , struct bio * * bio ,
572+ struct page * page )
573+ {
574+ enum temp_type temp ;
575+ bool found = false;
576+ int ret = - EAGAIN ;
577+
578+ for (temp = HOT ; temp < NR_TEMP_TYPE && !found ; temp ++ ) {
579+ struct f2fs_bio_info * io = sbi -> write_io [DATA ] + temp ;
580+ struct list_head * head = & io -> bio_list ;
581+ struct bio_entry * be ;
582+
583+ down_write (& io -> bio_list_lock );
584+ list_for_each_entry (be , head , list ) {
585+ if (be -> bio != * bio )
586+ continue ;
587+
588+ found = true;
589+
590+ if (bio_add_page (* bio , page , PAGE_SIZE , 0 ) == PAGE_SIZE ) {
591+ ret = 0 ;
592+ break ;
593+ }
594+
595+ /* bio is full */
596+ del_bio_entry (be );
597+ __submit_bio (sbi , * bio , DATA );
598+ break ;
599+ }
600+ up_write (& io -> bio_list_lock );
601+ }
602+
603+ if (ret ) {
604+ bio_put (* bio );
605+ * bio = NULL ;
606+ }
607+
608+ return ret ;
609+ }
610+
611+ void f2fs_submit_merged_ipu_write (struct f2fs_sb_info * sbi ,
612+ struct bio * * bio , struct page * page )
613+ {
614+ enum temp_type temp ;
615+ bool found = false;
616+ struct bio * target = bio ? * bio : NULL ;
617+
618+ for (temp = HOT ; temp < NR_TEMP_TYPE && !found ; temp ++ ) {
619+ struct f2fs_bio_info * io = sbi -> write_io [DATA ] + temp ;
620+ struct list_head * head = & io -> bio_list ;
621+ struct bio_entry * be ;
622+
623+ if (list_empty (head ))
624+ continue ;
625+
626+ down_read (& io -> bio_list_lock );
627+ list_for_each_entry (be , head , list ) {
628+ if (target )
629+ found = (target == be -> bio );
630+ else
631+ found = __has_merged_page (be -> bio , NULL ,
632+ page , 0 );
633+ if (found )
634+ break ;
635+ }
636+ up_read (& io -> bio_list_lock );
637+
638+ if (!found )
639+ continue ;
640+
641+ found = false;
642+
643+ down_write (& io -> bio_list_lock );
644+ list_for_each_entry (be , head , list ) {
645+ if (target )
646+ found = (target == be -> bio );
647+ else
648+ found = __has_merged_page (be -> bio , NULL ,
649+ page , 0 );
650+ if (found ) {
651+ target = be -> bio ;
652+ del_bio_entry (be );
653+ break ;
654+ }
655+ }
656+ up_write (& io -> bio_list_lock );
657+ }
658+
659+ if (found )
660+ __submit_bio (sbi , target , DATA );
661+ if (bio && * bio ) {
662+ bio_put (* bio );
663+ * bio = NULL ;
664+ }
665+ }
666+
546667int f2fs_merge_page_bio (struct f2fs_io_info * fio )
547668{
548669 struct bio * bio = * fio -> bio ;
@@ -557,20 +678,17 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
557678 f2fs_trace_ios (fio , 0 );
558679
559680 if (bio && !page_is_mergeable (fio -> sbi , bio , * fio -> last_block ,
560- fio -> new_blkaddr )) {
561- __submit_bio (fio -> sbi , bio , fio -> type );
562- bio = NULL ;
563- }
681+ fio -> new_blkaddr ))
682+ f2fs_submit_merged_ipu_write (fio -> sbi , & bio , NULL );
564683alloc_new :
565684 if (!bio ) {
566685 bio = __bio_alloc (fio , BIO_MAX_PAGES );
567686 bio_set_op_attrs (bio , fio -> op , fio -> op_flags );
568- }
569687
570- if ( bio_add_page ( bio , page , PAGE_SIZE , 0 ) < PAGE_SIZE ) {
571- __submit_bio ( fio -> sbi , bio , fio -> type );
572- bio = NULL ;
573- goto alloc_new ;
688+ add_bio_entry ( fio -> sbi , bio , page , fio -> temp );
689+ } else {
690+ if ( add_ipu_page ( fio -> sbi , & bio , page ))
691+ goto alloc_new ;
574692 }
575693
576694 if (fio -> io_wbc )
@@ -584,19 +702,6 @@ int f2fs_merge_page_bio(struct f2fs_io_info *fio)
584702 return 0 ;
585703}
586704
587- static void f2fs_submit_ipu_bio (struct f2fs_sb_info * sbi , struct bio * * bio ,
588- struct page * page )
589- {
590- if (!bio )
591- return ;
592-
593- if (!__has_merged_page (* bio , NULL , page , 0 ))
594- return ;
595-
596- __submit_bio (sbi , * bio , DATA );
597- * bio = NULL ;
598- }
599-
600705void f2fs_submit_page_write (struct f2fs_io_info * fio )
601706{
602707 struct f2fs_sb_info * sbi = fio -> sbi ;
@@ -2215,14 +2320,12 @@ static int __write_data_page(struct page *page, bool *submitted,
22152320
22162321 unlock_page (page );
22172322 if (!S_ISDIR (inode -> i_mode ) && !IS_NOQUOTA (inode ) &&
2218- !F2FS_I (inode )-> cp_task ) {
2219- f2fs_submit_ipu_bio (sbi , bio , page );
2323+ !F2FS_I (inode )-> cp_task )
22202324 f2fs_balance_fs (sbi , need_balance_fs );
2221- }
22222325
22232326 if (unlikely (f2fs_cp_error (sbi ))) {
2224- f2fs_submit_ipu_bio (sbi , bio , page );
22252327 f2fs_submit_merged_write (sbi , DATA );
2328+ f2fs_submit_merged_ipu_write (sbi , bio , NULL );
22262329 submitted = NULL ;
22272330 }
22282331
@@ -2342,13 +2445,11 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
23422445 }
23432446
23442447 if (PageWriteback (page )) {
2345- if (wbc -> sync_mode != WB_SYNC_NONE ) {
2448+ if (wbc -> sync_mode != WB_SYNC_NONE )
23462449 f2fs_wait_on_page_writeback (page ,
23472450 DATA , true, true);
2348- f2fs_submit_ipu_bio (sbi , & bio , page );
2349- } else {
2451+ else
23502452 goto continue_unlock ;
2351- }
23522453 }
23532454
23542455 if (!clear_page_dirty_for_io (page ))
@@ -2406,7 +2507,7 @@ static int f2fs_write_cache_pages(struct address_space *mapping,
24062507 NULL , 0 , DATA );
24072508 /* submit cached bio of IPU write */
24082509 if (bio )
2409- __submit_bio (sbi , bio , DATA );
2510+ f2fs_submit_merged_ipu_write (sbi , & bio , NULL );
24102511
24112512 return ret ;
24122513}
@@ -3211,8 +3312,22 @@ int __init f2fs_init_post_read_processing(void)
32113312 return - ENOMEM ;
32123313}
32133314
3214- void __exit f2fs_destroy_post_read_processing (void )
3315+ void f2fs_destroy_post_read_processing (void )
32153316{
32163317 mempool_destroy (bio_post_read_ctx_pool );
32173318 kmem_cache_destroy (bio_post_read_ctx_cache );
32183319}
3320+
3321+ int __init f2fs_init_bio_entry_cache (void )
3322+ {
3323+ bio_entry_slab = f2fs_kmem_cache_create ("bio_entry_slab" ,
3324+ sizeof (struct bio_entry ));
3325+ if (!bio_entry_slab )
3326+ return - ENOMEM ;
3327+ return 0 ;
3328+ }
3329+
3330+ void __exit f2fs_destroy_bio_entry_cache (void )
3331+ {
3332+ kmem_cache_destroy (bio_entry_slab );
3333+ }
0 commit comments