@@ -130,7 +130,7 @@ static int virtblk_add_req(struct virtqueue *vq, struct virtblk_req *vbr)
130130 return virtqueue_add_sgs (vq , sgs , num_out , num_in , vbr , GFP_ATOMIC );
131131}
132132
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 )
134134{
135135 unsigned short segments = blk_rq_nr_discard_segments (req );
136136 unsigned short n = 0 ;
@@ -240,6 +240,9 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
240240 type = VIRTIO_BLK_T_WRITE_ZEROES ;
241241 unmap = !(req -> cmd_flags & REQ_NOUNMAP );
242242 break ;
243+ case REQ_OP_SECURE_ERASE :
244+ type = VIRTIO_BLK_T_SECURE_ERASE ;
245+ break ;
243246 case REQ_OP_DRV_IN :
244247 type = VIRTIO_BLK_T_GET_ID ;
245248 break ;
@@ -251,8 +254,9 @@ static blk_status_t virtblk_setup_cmd(struct virtio_device *vdev,
251254 vbr -> out_hdr .type = cpu_to_virtio32 (vdev , type );
252255 vbr -> out_hdr .ioprio = cpu_to_virtio32 (vdev , req_get_ioprio (req ));
253256
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 ))
256260 return BLK_STS_RESOURCE ;
257261 }
258262
@@ -888,6 +892,8 @@ static int virtblk_probe(struct virtio_device *vdev)
888892 int err , index ;
889893
890894 u32 v , blk_size , max_size , sg_elems , opt_io_size ;
895+ u32 max_discard_segs = 0 ;
896+ u32 discard_granularity = 0 ;
891897 u16 min_io_size ;
892898 u8 physical_block_exp , alignment_offset ;
893899 unsigned int queue_depth ;
@@ -1045,27 +1051,14 @@ static int virtblk_probe(struct virtio_device *vdev)
10451051
10461052 if (virtio_has_feature (vdev , VIRTIO_BLK_F_DISCARD )) {
10471053 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 );
10531055
10541056 virtio_cread (vdev , struct virtio_blk_config ,
10551057 max_discard_sectors , & v );
10561058 blk_queue_max_discard_sectors (q , v ? v : UINT_MAX );
10571059
10581060 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 );
10691062 }
10701063
10711064 if (virtio_has_feature (vdev , VIRTIO_BLK_F_WRITE_ZEROES )) {
@@ -1074,6 +1067,85 @@ static int virtblk_probe(struct virtio_device *vdev)
10741067 blk_queue_max_write_zeroes_sectors (q , v ? v : UINT_MAX );
10751068 }
10761069
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+
10771149 virtblk_update_capacity (vblk , false);
10781150 virtio_device_ready (vdev );
10791151
@@ -1169,13 +1241,15 @@ static unsigned int features_legacy[] = {
11691241 VIRTIO_BLK_F_RO , VIRTIO_BLK_F_BLK_SIZE ,
11701242 VIRTIO_BLK_F_FLUSH , VIRTIO_BLK_F_TOPOLOGY , VIRTIO_BLK_F_CONFIG_WCE ,
11711243 VIRTIO_BLK_F_MQ , VIRTIO_BLK_F_DISCARD , VIRTIO_BLK_F_WRITE_ZEROES ,
1244+ VIRTIO_BLK_F_SECURE_ERASE ,
11721245}
11731246;
11741247static unsigned int features [] = {
11751248 VIRTIO_BLK_F_SEG_MAX , VIRTIO_BLK_F_SIZE_MAX , VIRTIO_BLK_F_GEOMETRY ,
11761249 VIRTIO_BLK_F_RO , VIRTIO_BLK_F_BLK_SIZE ,
11771250 VIRTIO_BLK_F_FLUSH , VIRTIO_BLK_F_TOPOLOGY , VIRTIO_BLK_F_CONFIG_WCE ,
11781251 VIRTIO_BLK_F_MQ , VIRTIO_BLK_F_DISCARD , VIRTIO_BLK_F_WRITE_ZEROES ,
1252+ VIRTIO_BLK_F_SECURE_ERASE ,
11791253};
11801254
11811255static struct virtio_driver virtio_blk = {
0 commit comments