Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib: kunit_iov_iter: add tests for extract_iter_to_sg

Add test cases that test extract_iter_to_sg.

For each iterator type an iterator is loaded with a suitable buffer. The
iterator is then extracted to a scatterlist with multiple calls to
extract_iter_to_sg. The final scatterlist is copied into a scratch
buffer.

The test passes if the scratch buffer contains the same data as the
original buffer.

The new tests demonstrate bugs in extract_iter_to_sg for kvec and user
iterators that are fixed by the previous commits.

Link: https://lkml.kernel.org/r/20260326214905.818170-6-lk@c--e.de
Signed-off-by: Christian A. Ehrhardt <lk@c--e.de>
Cc: David Howells <dhowells@redhat.com>
Cc: David Gow <davidgow@google.com>
Cc: Kees Cook <kees@kernel.org>
Cc: Petr Mladek <pmladek@suse.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Christian A. Ehrhardt and committed by
Andrew Morton
0913b755 7278aa84

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