1313#include <linux/uio.h>
1414#include <linux/bvec.h>
1515#include <linux/folio_queue.h>
16+ #include <linux/scatterlist.h>
1617#include <linux/minmax.h>
18+ #include <linux/mman.h>
1719#include <kunit/test.h>
1820
1921MODULE_DESCRIPTION ("iov_iter testing" );
@@ -1016,6 +1018,202 @@ static void __init iov_kunit_extract_pages_xarray(struct kunit *test)
10161018 KUNIT_SUCCEED (test );
10171019}
10181020
1021+ struct iov_kunit_iter_to_sg_data {
1022+ struct sg_table * sgt ;
1023+ u8 * buffer , * scratch ;
1024+ u8 __user * ubuf ;
1025+ struct page * * pages ;
1026+ size_t npages ;
1027+ };
1028+
1029+ static void __init
1030+ iov_kunit_iter_unpin_sgt (void * data )
1031+ {
1032+ struct sg_table * sgt = data ;
1033+
1034+ for (unsigned int i = 0 ; i < sgt -> nents ; ++ i )
1035+ unpin_user_page (sg_page (& sgt -> sgl [i ]));
1036+ }
1037+
1038+ static void __init
1039+ iov_kunit_iter_to_sg_init (struct kunit * test , size_t bufsize , bool user ,
1040+ struct iov_kunit_iter_to_sg_data * data )
1041+ {
1042+ struct page * * spages ;
1043+ struct scatterlist * sg ;
1044+ unsigned long uaddr ;
1045+ size_t i ;
1046+
1047+ data -> npages = bufsize / PAGE_SIZE ;
1048+ sg = kunit_kmalloc_array (test , data -> npages , sizeof (* sg ), GFP_KERNEL );
1049+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , sg );
1050+ sg_init_table (sg , data -> npages );
1051+ data -> sgt = kunit_kzalloc (test , sizeof (* data -> sgt ), GFP_KERNEL );
1052+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , data -> sgt );
1053+ data -> sgt -> orig_nents = 0 ;
1054+ data -> sgt -> sgl = sg ;
1055+
1056+ data -> buffer = NULL ;
1057+ data -> ubuf = NULL ;
1058+ if (user ) {
1059+ uaddr = kunit_vm_mmap (test , NULL , 0 , bufsize ,
1060+ PROT_READ | PROT_WRITE ,
1061+ MAP_ANONYMOUS | MAP_PRIVATE , 0 );
1062+ KUNIT_ASSERT_NE (test , uaddr , 0 );
1063+ data -> ubuf = (u8 __user * )uaddr ;
1064+ for (i = 0 ; i < bufsize ; ++ i )
1065+ put_user (pattern (i ), data -> ubuf + i );
1066+ } else {
1067+ data -> buffer = iov_kunit_create_buffer (test , & data -> pages ,
1068+ data -> npages );
1069+ for (i = 0 ; i < bufsize ; ++ i )
1070+ data -> buffer [i ] = pattern (i );
1071+ }
1072+ data -> scratch = iov_kunit_create_buffer (test , & spages , data -> npages );
1073+ memset (data -> scratch , 0 , bufsize );
1074+ }
1075+
1076+ static void __init
1077+ iov_kunit_iter_to_sg_check (struct kunit * test , struct iov_iter * iter ,
1078+ size_t bufsize ,
1079+ struct iov_kunit_iter_to_sg_data * data )
1080+ {
1081+ static const size_t tail = 16 * PAGE_SIZE ;
1082+ size_t i ;
1083+
1084+ KUNIT_ASSERT_LT (test , tail , bufsize );
1085+
1086+ if (iov_iter_extract_will_pin (iter ))
1087+ kunit_add_action_or_reset (test , iov_kunit_iter_unpin_sgt ,
1088+ data -> sgt );
1089+
1090+ i = extract_iter_to_sg (iter , bufsize , data -> sgt , 0 , 0 );
1091+ KUNIT_ASSERT_EQ (test , i , 0 );
1092+ KUNIT_ASSERT_EQ (test , data -> sgt -> nents , 0 );
1093+
1094+ i = extract_iter_to_sg (iter , bufsize - tail , data -> sgt , 1 , 0 );
1095+ KUNIT_ASSERT_LE (test , i , bufsize - tail );
1096+ KUNIT_ASSERT_EQ (test , data -> sgt -> nents , 1 );
1097+
1098+ i += extract_iter_to_sg (iter , bufsize - tail - i , data -> sgt ,
1099+ data -> npages - data -> sgt -> nents , 0 );
1100+ KUNIT_ASSERT_EQ (test , i , bufsize - tail );
1101+ KUNIT_ASSERT_LE (test , data -> sgt -> nents , data -> npages );
1102+
1103+ i += extract_iter_to_sg (iter , tail , data -> sgt ,
1104+ data -> npages - data -> sgt -> nents , 0 );
1105+ KUNIT_ASSERT_EQ (test , i , bufsize );
1106+ KUNIT_ASSERT_LE (test , data -> sgt -> nents , data -> npages );
1107+
1108+ sg_mark_end (& data -> sgt -> sgl [data -> sgt -> nents - 1 ]);
1109+
1110+ i = sg_copy_to_buffer (data -> sgt -> sgl , data -> sgt -> nents ,
1111+ data -> scratch , bufsize );
1112+ KUNIT_ASSERT_EQ (test , i , bufsize );
1113+
1114+ for (i = 0 ; i < bufsize ; ++ i ) {
1115+ KUNIT_EXPECT_EQ_MSG (test , data -> scratch [i ], pattern (i ),
1116+ "at i=%zx" , i );
1117+ if (data -> scratch [i ] != pattern (i ))
1118+ break ;
1119+ }
1120+
1121+ KUNIT_EXPECT_EQ (test , i , bufsize );
1122+ }
1123+
1124+ static void __init iov_kunit_iter_to_sg_kvec (struct kunit * test )
1125+ {
1126+ struct iov_kunit_iter_to_sg_data data ;
1127+ struct iov_iter iter ;
1128+ struct kvec kvec ;
1129+ size_t bufsize ;
1130+
1131+ bufsize = 0x100000 ;
1132+ iov_kunit_iter_to_sg_init (test , bufsize , false, & data );
1133+
1134+ kvec .iov_base = data .buffer ;
1135+ kvec .iov_len = bufsize ;
1136+ iov_iter_kvec (& iter , READ , & kvec , 1 , bufsize );
1137+
1138+ iov_kunit_iter_to_sg_check (test , & iter , bufsize , & data );
1139+ }
1140+
1141+ static void __init iov_kunit_iter_to_sg_bvec (struct kunit * test )
1142+ {
1143+ struct iov_kunit_iter_to_sg_data data ;
1144+ struct page * p , * can_merge = NULL ;
1145+ size_t i , k , bufsize ;
1146+ struct bio_vec * bvec ;
1147+ struct iov_iter iter ;
1148+
1149+ bufsize = 0x100000 ;
1150+ iov_kunit_iter_to_sg_init (test , bufsize , false, & data );
1151+
1152+ bvec = kunit_kmalloc_array (test , data .npages , sizeof (* bvec ),
1153+ GFP_KERNEL );
1154+ KUNIT_ASSERT_NOT_ERR_OR_NULL (test , bvec );
1155+ k = 0 ;
1156+ for (i = 0 ; i < data .npages ; ++ i ) {
1157+ p = data .pages [i ];
1158+ if (p == can_merge )
1159+ bvec [k - 1 ].bv_len += PAGE_SIZE ;
1160+ else
1161+ bvec_set_page (& bvec [k ++ ], p , PAGE_SIZE , 0 );
1162+ can_merge = p + 1 ;
1163+ }
1164+ iov_iter_bvec (& iter , READ , bvec , k , bufsize );
1165+
1166+ iov_kunit_iter_to_sg_check (test , & iter , bufsize , & data );
1167+ }
1168+
1169+ static void __init iov_kunit_iter_to_sg_folioq (struct kunit * test )
1170+ {
1171+ struct iov_kunit_iter_to_sg_data data ;
1172+ struct folio_queue * folioq ;
1173+ struct iov_iter iter ;
1174+ size_t bufsize ;
1175+
1176+ bufsize = 0x100000 ;
1177+ iov_kunit_iter_to_sg_init (test , bufsize , false, & data );
1178+
1179+ folioq = iov_kunit_create_folioq (test );
1180+ iov_kunit_load_folioq (test , & iter , READ , folioq , data .pages ,
1181+ data .npages );
1182+
1183+ iov_kunit_iter_to_sg_check (test , & iter , bufsize , & data );
1184+ }
1185+
1186+ static void __init iov_kunit_iter_to_sg_xarray (struct kunit * test )
1187+ {
1188+ struct iov_kunit_iter_to_sg_data data ;
1189+ struct xarray * xarray ;
1190+ struct iov_iter iter ;
1191+ size_t bufsize ;
1192+
1193+ bufsize = 0x100000 ;
1194+ iov_kunit_iter_to_sg_init (test , bufsize , false, & data );
1195+
1196+ xarray = iov_kunit_create_xarray (test );
1197+ iov_kunit_load_xarray (test , & iter , READ , xarray , data .pages ,
1198+ data .npages );
1199+
1200+ iov_kunit_iter_to_sg_check (test , & iter , bufsize , & data );
1201+ }
1202+
1203+ static void __init iov_kunit_iter_to_sg_ubuf (struct kunit * test )
1204+ {
1205+ struct iov_kunit_iter_to_sg_data data ;
1206+ struct iov_iter iter ;
1207+ size_t bufsize ;
1208+
1209+ bufsize = 0x100000 ;
1210+ iov_kunit_iter_to_sg_init (test , bufsize , true, & data );
1211+
1212+ iov_iter_ubuf (& iter , READ , data .ubuf , bufsize );
1213+
1214+ iov_kunit_iter_to_sg_check (test , & iter , bufsize , & data );
1215+ }
1216+
10191217static struct kunit_case __refdata iov_kunit_cases [] = {
10201218 KUNIT_CASE (iov_kunit_copy_to_kvec ),
10211219 KUNIT_CASE (iov_kunit_copy_from_kvec ),
@@ -1029,6 +1227,11 @@ static struct kunit_case __refdata iov_kunit_cases[] = {
10291227 KUNIT_CASE (iov_kunit_extract_pages_bvec ),
10301228 KUNIT_CASE (iov_kunit_extract_pages_folioq ),
10311229 KUNIT_CASE (iov_kunit_extract_pages_xarray ),
1230+ KUNIT_CASE (iov_kunit_iter_to_sg_kvec ),
1231+ KUNIT_CASE (iov_kunit_iter_to_sg_bvec ),
1232+ KUNIT_CASE (iov_kunit_iter_to_sg_folioq ),
1233+ KUNIT_CASE (iov_kunit_iter_to_sg_xarray ),
1234+ KUNIT_CASE (iov_kunit_iter_to_sg_ubuf ),
10321235 {}
10331236};
10341237
0 commit comments