WRITE SAME bios have a payload that contain a single page. When cloning WRITE SAME bios DM has no need to modify the bi_io_vec attributes (and doing so would be detrimental). DM need only alter the start and end of the WRITE SAME bio accordingly. Rather than duplicate __clone_and_map_discard, factor out a common function that is also used by __clone_and_map_write_same.
Unified · Split
| @@ -1174,7 +1174,28 @@ static void __clone_and_map_simple(struct clone_info *ci, struct dm_target *ti) · 1173 unmodified lines | |||
| 1174 | ci->sector_count = 0; | 1174 | ci->sector_count = 0; |
| 1175 | } | 1175 | } |
| 1176 | 1176 | ||
| 1177 | static int __clone_and_map_discard(struct clone_info *ci) | 1177 | typedef unsigned (*get_num_requests_fn)(struct dm_target *ti); |
| 1178 | |||
| 1179 | static unsigned get_num_discard_requests(struct dm_target *ti) | ||
| 1180 | { | ||
| 1181 | return ti->num_discard_requests; | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | static unsigned get_num_write_same_requests(struct dm_target *ti) | ||
| 1185 | { | ||
| 1186 | return ti->num_write_same_requests; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | typedef bool (*is_split_required_fn)(struct dm_target *ti); | ||
| 1190 | |||
| 1191 | static bool is_split_required_for_discard(struct dm_target *ti) | ||
| 1192 | { | ||
| 1193 | return ti->split_discard_requests; | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static int __clone_and_map_changing_extent_only(struct clone_info *ci, | ||
| 1197 | get_num_requests_fn get_num_requests, | ||
| 1198 | is_split_required_fn is_split_required) | ||
| 1178 | { | 1199 | { |
| 1179 | struct dm_target *ti; | 1200 | struct dm_target *ti; |
| 1180 | sector_t len; | 1201 | sector_t len; |
| @@ -1185,15 +1206,15 @@ static int __clone_and_map_discard(struct clone_info *ci) · 4 unmodified lines | |||
| 1185 | return -EIO; | 1206 | return -EIO; |
| 1186 | 1207 | ||
| 1187 | /* | 1208 | /* |
| 1188 | * Even though the device advertised discard support, | 1209 | * Even though the device advertised support for this type of |
| 1189 | * that does not mean every target supports it, and | 1210 | * request, that does not mean every target supports it, and |
| 1190 | * reconfiguration might also have changed that since the | 1211 | * reconfiguration might also have changed that since the |
| 1191 | * check was performed. | 1212 | * check was performed. |
| 1192 | */ | 1213 | */ |
| 1193 | if (!ti->num_discard_requests) | 1214 | if (!get_num_requests || !get_num_requests(ti)) |
| 1194 | return -EOPNOTSUPP; | 1215 | return -EOPNOTSUPP; |
| 1195 | 1216 | ||
| 1196 | if (!ti->split_discard_requests) | 1217 | if (is_split_required && !is_split_required(ti)) |
| 1197 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); | 1218 | len = min(ci->sector_count, max_io_len_target_boundary(ci->sector, ti)); |
| 1198 | else | 1219 | else |
| 1199 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); | 1220 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); |
| @@ -1206,6 +1227,17 @@ static int __clone_and_map_discard(struct clone_info *ci) · 6 unmodified lines | |||
| 1206 | return 0; | 1227 | return 0; |
| 1207 | } | 1228 | } |
| 1208 | 1229 | ||
| 1230 | static int __clone_and_map_discard(struct clone_info *ci) | ||
| 1231 | { | ||
| 1232 | return __clone_and_map_changing_extent_only(ci, get_num_discard_requests, | ||
| 1233 | is_split_required_for_discard); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | static int __clone_and_map_write_same(struct clone_info *ci) | ||
| 1237 | { | ||
| 1238 | return __clone_and_map_changing_extent_only(ci, get_num_write_same_requests, NULL); | ||
| 1239 | } | ||
| 1240 | |||
| 1209 | static int __clone_and_map(struct clone_info *ci) | 1241 | static int __clone_and_map(struct clone_info *ci) |
| 1210 | { | 1242 | { |
| 1211 | struct bio *bio = ci->bio; | 1243 | struct bio *bio = ci->bio; |
| @@ -1215,6 +1247,8 @@ static int __clone_and_map(struct clone_info *ci) · 3 unmodified lines | |||
| 1215 | 1247 | ||
| 1216 | if (unlikely(bio->bi_rw & REQ_DISCARD)) | 1248 | if (unlikely(bio->bi_rw & REQ_DISCARD)) |
| 1217 | return __clone_and_map_discard(ci); | 1249 | return __clone_and_map_discard(ci); |
| 1250 | else if (unlikely(bio->bi_rw & REQ_WRITE_SAME)) | ||
| 1251 | return __clone_and_map_write_same(ci); | ||
| 1218 | 1252 | ||
| 1219 | ti = dm_table_find_target(ci->map, ci->sector); | 1253 | ti = dm_table_find_target(ci->map, ci->sector); |
| 1220 | if (!dm_target_is_valid(ti)) | 1254 | if (!dm_target_is_valid(ti)) |