@@ -130,7 +130,7 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr)
130
130
return virtqueue_add_sgs (vq , sgs , num_out , num_in , vbr , GFP_ATOMIC );
131
131
}
132
132
133
- static int virtblk_setup_discard_write_zeroes (struct request * req , bool unmap )
133
+ static int virtblk_setup_discard_write_zeroes_erase (struct request * req , bool unmap )
134
134
{
135
135
unsigned short segments = blk_rq_nr_discard_segments (req );
136
136
unsigned short n = 0 ;
@@ -240,6 +240,9 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
240
240
type = VIRTIO_BLK_T_WRITE_ZEROES ;
241
241
unmap = !(req -> cmd_flags & REQ_NOUNMAP );
242
242
break ;
243
+ case REQ_OP_SECURE_ERASE :
244
+ type = VIRTIO_BLK_T_SECURE_ERASE ;
245
+ break ;
243
246
case REQ_OP_DRV_IN :
244
247
type = VIRTIO_BLK_T_GET_ID ;
245
248
break ;
@@ -251,8 +254,9 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
251
254
vbr -> out_hdr .type = cpu_to_virtio32 (vdev , type );
252
255
vbr -> out_hdr .ioprio = cpu_to_virtio32 (vdev , req_get_ioprio (req ));
253
256
254
- if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES ) {
255
- if (virtblk_setup_discard_write_zeroes (req , unmap ))
257
+ if (type == VIRTIO_BLK_T_DISCARD || type == VIRTIO_BLK_T_WRITE_ZEROES ||
258
+ type == VIRTIO_BLK_T_SECURE_ERASE ) {
259
+ if (virtblk_setup_discard_write_zeroes_erase (req , unmap ))
256
260
return BLK_STS_RESOURCE ;
257
261
}
258
262
@@ -888,6 +892,8 @@ static int virtblk_probe(struct virtio_device *vdev)
888
892
int err , index ;
889
893
890
894
u32 v , blk_size , max_size , sg_elems , opt_io_size ;
895
+ u32 max_discard_segs = 0 ;
896
+ u32 discard_granularity = 0 ;
891
897
u16 min_io_size ;
892
898
u8 physical_block_exp , alignment_offset ;
893
899
unsigned int queue_depth ;
@@ -1045,27 +1051,14 @@ static int virtblk_probe(struct virtio_device *vdev)
1045
1051
1046
1052
if (virtio_has_feature (vdev , VIRTIO_BLK_F_DISCARD )) {
1047
1053
virtio_cread (vdev , struct virtio_blk_config ,
1048
- discard_sector_alignment , & v );
1049
- if (v )
1050
- q -> limits .discard_granularity = v << SECTOR_SHIFT ;
1051
- else
1052
- q -> limits .discard_granularity = blk_size ;
1054
+ discard_sector_alignment , & discard_granularity );
1053
1055
1054
1056
virtio_cread (vdev , struct virtio_blk_config ,
1055
1057
max_discard_sectors , & v );
1056
1058
blk_queue_max_discard_sectors (q , v ? v : UINT_MAX );
1057
1059
1058
1060
virtio_cread (vdev , struct virtio_blk_config , max_discard_seg ,
1059
- & v );
1060
-
1061
- /*
1062
- * max_discard_seg == 0 is out of spec but we always
1063
- * handled it.
1064
- */
1065
- if (!v )
1066
- v = sg_elems ;
1067
- blk_queue_max_discard_segments (q ,
1068
- min (v , MAX_DISCARD_SEGMENTS ));
1061
+ & max_discard_segs );
1069
1062
}
1070
1063
1071
1064
if (virtio_has_feature (vdev , VIRTIO_BLK_F_WRITE_ZEROES )) {
@@ -1074,6 +1067,85 @@ static int virtblk_probe(struct virtio_device *vdev)
1074
1067
blk_queue_max_write_zeroes_sectors (q , v ? v : UINT_MAX );
1075
1068
}
1076
1069
1070
+ /* The discard and secure erase limits are combined since the Linux
1071
+ * block layer uses the same limit for both commands.
1072
+ *
1073
+ * If both VIRTIO_BLK_F_SECURE_ERASE and VIRTIO_BLK_F_DISCARD features
1074
+ * are negotiated, we will use the minimum between the limits.
1075
+ *
1076
+ * discard sector alignment is set to the minimum between discard_sector_alignment
1077
+ * and secure_erase_sector_alignment.
1078
+ *
1079
+ * max discard sectors is set to the minimum between max_discard_seg and
1080
+ * max_secure_erase_seg.
1081
+ */
1082
+ if (virtio_has_feature (vdev , VIRTIO_BLK_F_SECURE_ERASE )) {
1083
+
1084
+ virtio_cread (vdev , struct virtio_blk_config ,
1085
+ secure_erase_sector_alignment , & v );
1086
+
1087
+ /* secure_erase_sector_alignment should not be zero, the device should set a
1088
+ * valid number of sectors.
1089
+ */
1090
+ if (!v ) {
1091
+ dev_err (& vdev -> dev ,
1092
+ "virtio_blk: secure_erase_sector_alignment can't be 0\n" );
1093
+ err = - EINVAL ;
1094
+ goto out_cleanup_disk ;
1095
+ }
1096
+
1097
+ discard_granularity = min_not_zero (discard_granularity , v );
1098
+
1099
+ virtio_cread (vdev , struct virtio_blk_config ,
1100
+ max_secure_erase_sectors , & v );
1101
+
1102
+ /* max_secure_erase_sectors should not be zero, the device should set a
1103
+ * valid number of sectors.
1104
+ */
1105
+ if (!v ) {
1106
+ dev_err (& vdev -> dev ,
1107
+ "virtio_blk: max_secure_erase_sectors can't be 0\n" );
1108
+ err = - EINVAL ;
1109
+ goto out_cleanup_disk ;
1110
+ }
1111
+
1112
+ blk_queue_max_secure_erase_sectors (q , v );
1113
+
1114
+ virtio_cread (vdev , struct virtio_blk_config ,
1115
+ max_secure_erase_seg , & v );
1116
+
1117
+ /* max_secure_erase_seg should not be zero, the device should set a
1118
+ * valid number of segments
1119
+ */
1120
+ if (!v ) {
1121
+ dev_err (& vdev -> dev ,
1122
+ "virtio_blk: max_secure_erase_seg can't be 0\n" );
1123
+ err = - EINVAL ;
1124
+ goto out_cleanup_disk ;
1125
+ }
1126
+
1127
+ max_discard_segs = min_not_zero (max_discard_segs , v );
1128
+ }
1129
+
1130
+ if (virtio_has_feature (vdev , VIRTIO_BLK_F_DISCARD ) ||
1131
+ virtio_has_feature (vdev , VIRTIO_BLK_F_SECURE_ERASE )) {
1132
+ /* max_discard_seg and discard_granularity will be 0 only
1133
+ * if max_discard_seg and discard_sector_alignment fields in the virtio
1134
+ * config are 0 and VIRTIO_BLK_F_SECURE_ERASE feature is not negotiated.
1135
+ * In this case, we use default values.
1136
+ */
1137
+ if (!max_discard_segs )
1138
+ max_discard_segs = sg_elems ;
1139
+
1140
+ blk_queue_max_discard_segments (q ,
1141
+ min (max_discard_segs , MAX_DISCARD_SEGMENTS ));
1142
+
1143
+ if (discard_granularity )
1144
+ q -> limits .discard_granularity = discard_granularity << SECTOR_SHIFT ;
1145
+ else
1146
+ q -> limits .discard_granularity = blk_size ;
1147
+ }
1148
+
1077
1149
virtblk_update_capacity (vblk , false);
1078
1150
virtio_device_ready (vdev );
1079
1151
@@ -1169,13 +1241,15 @@ static unsigned int features_legacy[] = {
1169
1241
VIRTIO_BLK_F_RO , VIRTIO_BLK_F_BLK_SIZE ,
1170
1242
VIRTIO_BLK_F_FLUSH , VIRTIO_BLK_F_TOPOLOGY , VIRTIO_BLK_F_CONFIG_WCE ,
1171
1243
VIRTIO_BLK_F_MQ , VIRTIO_BLK_F_DISCARD , VIRTIO_BLK_F_WRITE_ZEROES ,
1244
+ VIRTIO_BLK_F_SECURE_ERASE ,
1172
1245
}
1173
1246
;
1174
1247
static unsigned int features [] = {
1175
1248
VIRTIO_BLK_F_SEG_MAX , VIRTIO_BLK_F_SIZE_MAX , VIRTIO_BLK_F_GEOMETRY ,
1176
1249
VIRTIO_BLK_F_RO , VIRTIO_BLK_F_BLK_SIZE ,
1177
1250
VIRTIO_BLK_F_FLUSH , VIRTIO_BLK_F_TOPOLOGY , VIRTIO_BLK_F_CONFIG_WCE ,
1178
1251
VIRTIO_BLK_F_MQ , VIRTIO_BLK_F_DISCARD , VIRTIO_BLK_F_WRITE_ZEROES ,
1252
+ VIRTIO_BLK_F_SECURE_ERASE ,
1179
1253
};
1180
1254
1181
1255
static struct virtio_driver virtio_blk = {
0 commit comments