2626#define __reverse_ffz (x ) __reverse_ffs(~(x))
2727
2828static struct kmem_cache * discard_entry_slab ;
29+ static struct kmem_cache * bio_entry_slab ;
2930static struct kmem_cache * sit_entry_set_slab ;
3031static struct kmem_cache * inmem_entry_slab ;
3132
@@ -622,6 +623,162 @@ static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno)
622623 mutex_unlock (& dirty_i -> seglist_lock );
623624}
624625
626+ static struct bio_entry * __add_bio_entry (struct f2fs_sb_info * sbi ,
627+ struct bio * bio )
628+ {
629+ struct list_head * wait_list = & (SM_I (sbi )-> wait_list );
630+ struct bio_entry * be = f2fs_kmem_cache_alloc (bio_entry_slab , GFP_NOFS );
631+
632+ INIT_LIST_HEAD (& be -> list );
633+ be -> bio = bio ;
634+ init_completion (& be -> event );
635+ list_add_tail (& be -> list , wait_list );
636+
637+ return be ;
638+ }
639+
640+ void f2fs_wait_all_discard_bio (struct f2fs_sb_info * sbi )
641+ {
642+ struct list_head * wait_list = & (SM_I (sbi )-> wait_list );
643+ struct bio_entry * be , * tmp ;
644+
645+ list_for_each_entry_safe (be , tmp , wait_list , list ) {
646+ struct bio * bio = be -> bio ;
647+ int err ;
648+
649+ wait_for_completion_io (& be -> event );
650+ err = be -> error ;
651+ if (err == - EOPNOTSUPP )
652+ err = 0 ;
653+
654+ if (err )
655+ f2fs_msg (sbi -> sb , KERN_INFO ,
656+ "Issue discard failed, ret: %d" , err );
657+
658+ bio_put (bio );
659+ list_del (& be -> list );
660+ kmem_cache_free (bio_entry_slab , be );
661+ }
662+ }
663+
664+ static void f2fs_submit_bio_wait_endio (struct bio * bio )
665+ {
666+ struct bio_entry * be = (struct bio_entry * )bio -> bi_private ;
667+
668+ be -> error = bio -> bi_error ;
669+ complete (& be -> event );
670+ }
671+
672+ /* copied from block/blk-lib.c in 4.10-rc1 */
673+ static int __blkdev_issue_discard (struct block_device * bdev , sector_t sector ,
674+ sector_t nr_sects , gfp_t gfp_mask , int flags ,
675+ struct bio * * biop )
676+ {
677+ struct request_queue * q = bdev_get_queue (bdev );
678+ struct bio * bio = * biop ;
679+ unsigned int granularity ;
680+ int op = REQ_WRITE | REQ_DISCARD ;
681+ int alignment ;
682+ sector_t bs_mask ;
683+
684+ if (!q )
685+ return - ENXIO ;
686+
687+ if (!blk_queue_discard (q ))
688+ return - EOPNOTSUPP ;
689+
690+ if (flags & BLKDEV_DISCARD_SECURE ) {
691+ if (!blk_queue_secdiscard (q ))
692+ return - EOPNOTSUPP ;
693+ op |= REQ_SECURE ;
694+ }
695+
696+ bs_mask = (bdev_logical_block_size (bdev ) >> 9 ) - 1 ;
697+ if ((sector | nr_sects ) & bs_mask )
698+ return - EINVAL ;
699+
700+ /* Zero-sector (unknown) and one-sector granularities are the same. */
701+ granularity = max (q -> limits .discard_granularity >> 9 , 1U );
702+ alignment = (bdev_discard_alignment (bdev ) >> 9 ) % granularity ;
703+
704+ while (nr_sects ) {
705+ unsigned int req_sects ;
706+ sector_t end_sect , tmp ;
707+
708+ /* Make sure bi_size doesn't overflow */
709+ req_sects = min_t (sector_t , nr_sects , UINT_MAX >> 9 );
710+
711+ /**
712+ * If splitting a request, and the next starting sector would be
713+ * misaligned, stop the discard at the previous aligned sector.
714+ */
715+ end_sect = sector + req_sects ;
716+ tmp = end_sect ;
717+ if (req_sects < nr_sects &&
718+ sector_div (tmp , granularity ) != alignment ) {
719+ end_sect = end_sect - alignment ;
720+ sector_div (end_sect , granularity );
721+ end_sect = end_sect * granularity + alignment ;
722+ req_sects = end_sect - sector ;
723+ }
724+
725+ if (bio ) {
726+ int ret = submit_bio_wait (0 , bio );
727+ bio_put (bio );
728+ if (ret )
729+ return ret ;
730+ }
731+ bio = f2fs_bio_alloc (0 );
732+ bio -> bi_iter .bi_sector = sector ;
733+ bio -> bi_bdev = bdev ;
734+ bio_set_op_attrs (bio , op , 0 );
735+
736+ bio -> bi_iter .bi_size = req_sects << 9 ;
737+ nr_sects -= req_sects ;
738+ sector = end_sect ;
739+
740+ /*
741+ * We can loop for a long time in here, if someone does
742+ * full device discards (like mkfs). Be nice and allow
743+ * us to schedule out to avoid softlocking if preempt
744+ * is disabled.
745+ */
746+ cond_resched ();
747+ }
748+
749+ * biop = bio ;
750+ return 0 ;
751+ }
752+
753+ /* this function is copied from blkdev_issue_discard from block/blk-lib.c */
754+ static int __f2fs_issue_discard_async (struct f2fs_sb_info * sbi ,
755+ struct block_device * bdev , block_t blkstart , block_t blklen )
756+ {
757+ struct bio * bio = NULL ;
758+ int err ;
759+
760+ trace_f2fs_issue_discard (sbi -> sb , blkstart , blklen );
761+
762+ if (sbi -> s_ndevs ) {
763+ int devi = f2fs_target_device_index (sbi , blkstart );
764+
765+ blkstart -= FDEV (devi ).start_blk ;
766+ }
767+ err = __blkdev_issue_discard (bdev ,
768+ SECTOR_FROM_BLOCK (blkstart ),
769+ SECTOR_FROM_BLOCK (blklen ),
770+ GFP_NOFS , 0 , & bio );
771+ if (!err && bio ) {
772+ struct bio_entry * be = __add_bio_entry (sbi , bio );
773+
774+ bio -> bi_private = be ;
775+ bio -> bi_end_io = f2fs_submit_bio_wait_endio ;
776+ submit_bio (REQ_SYNC , bio );
777+ }
778+
779+ return err ;
780+ }
781+
625782#ifdef CONFIG_BLK_DEV_ZONED
626783static int __f2fs_issue_discard_zone (struct f2fs_sb_info * sbi ,
627784 struct block_device * bdev , block_t blkstart , block_t blklen )
@@ -655,8 +812,7 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
655812 case BLK_ZONE_TYPE_CONVENTIONAL :
656813 if (!blk_queue_discard (bdev_get_queue (bdev )))
657814 return 0 ;
658- return blkdev_issue_discard (bdev , sector , nr_sects ,
659- GFP_NOFS , 0 );
815+ return __f2fs_issue_discard_async (sbi , bdev , blkstart , blklen );
660816 case BLK_ZONE_TYPE_SEQWRITE_REQ :
661817 case BLK_ZONE_TYPE_SEQWRITE_PREF :
662818 trace_f2fs_issue_reset_zone (sbi -> sb , blkstart );
@@ -672,15 +828,12 @@ static int __f2fs_issue_discard_zone(struct f2fs_sb_info *sbi,
672828static int __issue_discard_async (struct f2fs_sb_info * sbi ,
673829 struct block_device * bdev , block_t blkstart , block_t blklen )
674830{
675- sector_t start = SECTOR_FROM_BLOCK (blkstart );
676- sector_t len = SECTOR_FROM_BLOCK (blklen );
677-
678831#ifdef CONFIG_BLK_DEV_ZONED
679832 if (f2fs_sb_mounted_blkzoned (sbi -> sb ) &&
680833 bdev_zoned_model (bdev ) != BLK_ZONED_NONE )
681834 return __f2fs_issue_discard_zone (sbi , bdev , blkstart , blklen );
682835#endif
683- return blkdev_issue_discard ( bdev , start , len , GFP_NOFS , 0 );
836+ return __f2fs_issue_discard_async ( sbi , bdev , blkstart , blklen );
684837}
685838
686839static int f2fs_issue_discard (struct f2fs_sb_info * sbi ,
@@ -720,8 +873,6 @@ static int f2fs_issue_discard(struct f2fs_sb_info *sbi,
720873
721874 if (len )
722875 err = __issue_discard_async (sbi , bdev , start , len );
723-
724- trace_f2fs_issue_discard (sbi -> sb , blkstart , blklen );
725876 return err ;
726877}
727878
@@ -822,11 +973,14 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
822973 struct list_head * head = & (SM_I (sbi )-> discard_list );
823974 struct discard_entry * entry , * this ;
824975 struct dirty_seglist_info * dirty_i = DIRTY_I (sbi );
976+ struct blk_plug plug ;
825977 unsigned long * prefree_map = dirty_i -> dirty_segmap [PRE ];
826978 unsigned int start = 0 , end = -1 ;
827979 unsigned int secno , start_segno ;
828980 bool force = (cpc -> reason == CP_DISCARD );
829981
982+ blk_start_plug (& plug );
983+
830984 mutex_lock (& dirty_i -> seglist_lock );
831985
832986 while (1 ) {
@@ -875,6 +1029,8 @@ void clear_prefree_segments(struct f2fs_sb_info *sbi, struct cp_control *cpc)
8751029 SM_I (sbi )-> nr_discards -= entry -> len ;
8761030 kmem_cache_free (discard_entry_slab , entry );
8771031 }
1032+
1033+ blk_finish_plug (& plug );
8781034}
8791035
8801036static bool __mark_sit_entry_dirty (struct f2fs_sb_info * sbi , unsigned int segno )
@@ -2551,6 +2707,7 @@ int build_segment_manager(struct f2fs_sb_info *sbi)
25512707 sm_info -> min_fsync_blocks = DEF_MIN_FSYNC_BLOCKS ;
25522708
25532709 INIT_LIST_HEAD (& sm_info -> discard_list );
2710+ INIT_LIST_HEAD (& sm_info -> wait_list );
25542711 sm_info -> nr_discards = 0 ;
25552712 sm_info -> max_discards = 0 ;
25562713
@@ -2694,10 +2851,15 @@ int __init create_segment_manager_caches(void)
26942851 if (!discard_entry_slab )
26952852 goto fail ;
26962853
2854+ bio_entry_slab = f2fs_kmem_cache_create ("bio_entry" ,
2855+ sizeof (struct bio_entry ));
2856+ if (!bio_entry_slab )
2857+ goto destroy_discard_entry ;
2858+
26972859 sit_entry_set_slab = f2fs_kmem_cache_create ("sit_entry_set" ,
26982860 sizeof (struct sit_entry_set ));
26992861 if (!sit_entry_set_slab )
2700- goto destroy_discard_entry ;
2862+ goto destroy_bio_entry ;
27012863
27022864 inmem_entry_slab = f2fs_kmem_cache_create ("inmem_page_entry" ,
27032865 sizeof (struct inmem_pages ));
@@ -2707,6 +2869,8 @@ int __init create_segment_manager_caches(void)
27072869
27082870destroy_sit_entry_set :
27092871 kmem_cache_destroy (sit_entry_set_slab );
2872+ destroy_bio_entry :
2873+ kmem_cache_destroy (bio_entry_slab );
27102874destroy_discard_entry :
27112875 kmem_cache_destroy (discard_entry_slab );
27122876fail :
@@ -2716,6 +2880,7 @@ int __init create_segment_manager_caches(void)
27162880void destroy_segment_manager_caches (void )
27172881{
27182882 kmem_cache_destroy (sit_entry_set_slab );
2883+ kmem_cache_destroy (bio_entry_slab );
27192884 kmem_cache_destroy (discard_entry_slab );
27202885 kmem_cache_destroy (inmem_entry_slab );
27212886}
0 commit comments