@@ -84,6 +84,15 @@ typedef struct vdev_disk {
8484 */
8585uint_t zfs_vdev_disk_max_segs = 0 ;
8686
87+ /*
88+ * BIO fill debugging. 0 disables it (default). If enabled, the BIO fill layout
89+ * is record if as its filled. If set to 1, layout is logged to the kernel log
90+ * on error. If 2, layout is logged for all IOs.
91+ */
92+ uint_t zfs_vdev_disk_debug_bio_fill = 0 ;
93+
94+ #define DEBUG_BIO_FILL_ALLOC_SIZE (256)
95+
8796/*
8897 * Unique identifier for the exclusive vdev holder.
8998 */
@@ -689,6 +698,11 @@ typedef struct {
689698
690699 struct bio * vbio_bio ; /* pointer to the current bio */
691700 int vbio_flags ; /* bio flags */
701+
702+ /* debugging info, when zfs_vdev_disk_debug_bio_fill > 0 */
703+ char * vbio_debug ;
704+ size_t vbio_debug_size ;
705+ size_t vbio_debug_pos ;
692706} vbio_t ;
693707
694708static vbio_t *
@@ -706,9 +720,56 @@ vbio_alloc(zio_t *zio, struct block_device *bdev, int flags)
706720 vbio -> vbio_bio = NULL ;
707721 vbio -> vbio_flags = flags ;
708722
723+ if (zfs_vdev_disk_debug_bio_fill > 0 ) {
724+ vbio -> vbio_debug =
725+ kmem_alloc (DEBUG_BIO_FILL_ALLOC_SIZE , KM_SLEEP );
726+ vbio -> vbio_debug_size = DEBUG_BIO_FILL_ALLOC_SIZE ;
727+ vbio -> vbio_debug_pos = 0 ;
728+ }
729+
709730 return (vbio );
710731}
711732
733+ static inline void
734+ vbio_debug_append (vbio_t * vbio , char c )
735+ {
736+ if (vbio -> vbio_debug == NULL )
737+ return ;
738+
739+ vbio -> vbio_debug [vbio -> vbio_debug_pos ++ ] = c ;
740+
741+ if (vbio -> vbio_debug_pos < vbio -> vbio_debug_size )
742+ return ;
743+
744+ size_t new_size = vbio -> vbio_debug_size * 2 ;
745+ char * new = kmem_alloc (new_size , KM_SLEEP );
746+ memcpy (new , vbio -> vbio_debug , vbio -> vbio_debug_size );
747+ kmem_free (vbio -> vbio_debug , vbio -> vbio_debug_size );
748+ vbio -> vbio_debug = new ;
749+ vbio -> vbio_debug_size = new_size ;
750+ }
751+
752+ static inline void
753+ vbio_debug_append_size (vbio_t * vbio , size_t ssize )
754+ {
755+ const uint_t nlb = (ssize / ((~vbio -> vbio_lbs_mask )+ 1 ));
756+ const char cnlb = (nlb < 10 ) ? (nlb + 0x30 ) : (nlb + (0x97 - 10 ));
757+ vbio_debug_append (vbio , cnlb );
758+
759+ }
760+
761+ static void
762+ vbio_debug_log (vbio_t * vbio )
763+ {
764+ printk (KERN_INFO "vbio debug: vd=%llu ms=%x mb=%x bs=%x "
765+ "ty=%u sz=%llx bt=%c %.*s\n" , vbio -> vbio_zio -> io_vd -> vdev_id ,
766+ vbio -> vbio_max_segs , vbio -> vbio_max_bytes , (~vbio -> vbio_lbs_mask )+ 1 ,
767+ vbio -> vbio_zio -> io_type , vbio -> vbio_zio -> io_size ,
768+ abd_is_linear (vbio -> vbio_zio -> io_abd ) ? 'L' :
769+ abd_is_gang (vbio -> vbio_zio -> io_abd ) ? 'G' : 'S' ,
770+ (int )vbio -> vbio_debug_pos , vbio -> vbio_debug );
771+ }
772+
712773BIO_END_IO_PROTO (vbio_completion , bio , error );
713774
714775static int
@@ -717,6 +778,9 @@ vbio_add_page(vbio_t *vbio, struct page *page, uint_t size, uint_t offset)
717778 struct bio * bio = vbio -> vbio_bio ;
718779 uint_t ssize ;
719780
781+ vbio_debug_append_size (vbio , size );
782+ vbio_debug_append (vbio , '[' );
783+
720784 while (size > 0 ) {
721785 if (bio == NULL ) {
722786 /* New BIO, allocate and set up */
@@ -730,10 +794,13 @@ vbio_add_page(vbio_t *vbio, struct page *page, uint_t size, uint_t offset)
730794 WRITE : READ , vbio -> vbio_flags );
731795
732796 if (vbio -> vbio_bio ) {
797+ vbio_debug_append (vbio , '$' );
733798 bio_chain (vbio -> vbio_bio , bio );
734799 vdev_submit_bio (vbio -> vbio_bio );
735800 }
736801 vbio -> vbio_bio = bio ;
802+
803+ vbio_debug_append (vbio , '^' );
737804 }
738805
739806 /*
@@ -748,19 +815,25 @@ vbio_add_page(vbio_t *vbio, struct page *page, uint_t size, uint_t offset)
748815 vbio -> vbio_lbs_mask );
749816 if (ssize > 0 &&
750817 bio_add_page (bio , page , ssize , offset ) == ssize ) {
818+ vbio_debug_append_size (vbio , ssize );
751819 /* Accepted, adjust and load any remaining. */
752820 size -= ssize ;
753821 offset += ssize ;
754822 continue ;
755823 }
756824
825+ vbio_debug_append_size (vbio , ssize );
826+ vbio_debug_append (vbio , '!' );
827+
757828 /* No room, set up for a new BIO and loop */
758829 vbio -> vbio_offset += BIO_BI_SIZE (bio );
759830
760831 /* Signal new BIO allocation wanted */
761832 bio = NULL ;
762833 }
763834
835+ vbio_debug_append (vbio , ']' );
836+
764837 return (0 );
765838}
766839
@@ -799,6 +872,7 @@ vbio_submit(vbio_t *vbio, abd_t *abd, uint64_t size)
799872 * called and free the vbio before this task is run again, so we must
800873 * consider it invalid from this point.
801874 */
875+ vbio_debug_append (vbio , '$' );
802876 vdev_submit_bio (vbio -> vbio_bio );
803877
804878 blk_finish_plug (& plug );
@@ -830,6 +904,14 @@ BIO_END_IO_PROTO(vbio_completion, bio, error)
830904 /* Return the BIO to the kernel */
831905 bio_put (bio );
832906
907+ /* Emit debug output if wanted */
908+ if (vbio -> vbio_debug != NULL ) {
909+ if ((zfs_vdev_disk_debug_bio_fill == 1 && zio -> io_error != 0 ) ||
910+ zfs_vdev_disk_debug_bio_fill == 2 )
911+ vbio_debug_log (vbio );
912+ kmem_free (vbio -> vbio_debug , vbio -> vbio_debug_size );
913+ }
914+
833915 /*
834916 * If we copied the ABD before issuing it, clean up and return the copy
835917 * to the ADB, with changes if appropriate.
@@ -1663,3 +1745,6 @@ ZFS_MODULE_PARAM(zfs_vdev_disk, zfs_vdev_disk_, max_segs, UINT, ZMOD_RW,
16631745ZFS_MODULE_PARAM_CALL (zfs_vdev_disk , zfs_vdev_disk_ , classic ,
16641746 vdev_disk_param_set_classic , param_get_uint , ZMOD_RD ,
16651747 "Use classic BIO submission method" );
1748+
1749+ ZFS_MODULE_PARAM (zfs_vdev_disk , zfs_vdev_disk_ , debug_bio_fill , UINT , ZMOD_RW ,
1750+ "BIO fill debugging: 0 - disable, 1 - errors only, 2 - everything" );
0 commit comments