@@ -133,6 +133,11 @@ struct vhost_scsi_cmd {
133133 struct se_cmd tvc_se_cmd ;
134134 /* Sense buffer that will be mapped into outgoing status */
135135 unsigned char tvc_sense_buf [TRANSPORT_SENSE_BUFFER ];
136+ /*
137+ * Dirty write descriptors of this command.
138+ */
139+ struct vhost_log * tvc_log ;
140+ unsigned int tvc_log_num ;
136141 /* Completed commands list, serviced from vhost worker thread */
137142 struct llist_node tvc_completion_list ;
138143 /* Used to track inflight cmd */
@@ -362,6 +367,45 @@ static int vhost_scsi_check_prot_fabric_only(struct se_portal_group *se_tpg)
362367 return tpg -> tv_fabric_prot_type ;
363368}
364369
370+ static int vhost_scsi_copy_cmd_log (struct vhost_virtqueue * vq ,
371+ struct vhost_scsi_cmd * cmd ,
372+ struct vhost_log * log ,
373+ unsigned int log_num )
374+ {
375+ if (!cmd -> tvc_log )
376+ cmd -> tvc_log = kmalloc_array (vq -> dev -> iov_limit ,
377+ sizeof (* cmd -> tvc_log ),
378+ GFP_KERNEL );
379+
380+ if (unlikely (!cmd -> tvc_log )) {
381+ vq_err (vq , "Failed to alloc tvc_log\n" );
382+ return - ENOMEM ;
383+ }
384+
385+ memcpy (cmd -> tvc_log , log , sizeof (* cmd -> tvc_log ) * log_num );
386+ cmd -> tvc_log_num = log_num ;
387+
388+ return 0 ;
389+ }
390+
391+ static void vhost_scsi_log_write (struct vhost_virtqueue * vq ,
392+ struct vhost_log * log ,
393+ unsigned int log_num )
394+ {
395+ if (likely (!vhost_has_feature (vq , VHOST_F_LOG_ALL )))
396+ return ;
397+
398+ if (likely (!log_num || !log ))
399+ return ;
400+
401+ /*
402+ * vhost-scsi doesn't support VIRTIO_F_ACCESS_PLATFORM.
403+ * No requirement for vq->iotlb case.
404+ */
405+ WARN_ON_ONCE (unlikely (vq -> iotlb ));
406+ vhost_log_write (vq , log , log_num , U64_MAX , NULL , 0 );
407+ }
408+
365409static void vhost_scsi_release_cmd_res (struct se_cmd * se_cmd )
366410{
367411 struct vhost_scsi_cmd * tv_cmd = container_of (se_cmd ,
@@ -660,6 +704,9 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
660704 } else
661705 pr_err ("Faulted on virtio_scsi_cmd_resp\n" );
662706
707+ vhost_scsi_log_write (cmd -> tvc_vq , cmd -> tvc_log ,
708+ cmd -> tvc_log_num );
709+
663710 vhost_scsi_release_cmd_res (se_cmd );
664711 }
665712
@@ -676,6 +723,7 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, u64 scsi_tag)
676723 struct vhost_scsi_virtqueue , vq );
677724 struct vhost_scsi_cmd * cmd ;
678725 struct scatterlist * sgl , * prot_sgl ;
726+ struct vhost_log * log ;
679727 int tag ;
680728
681729 tag = sbitmap_get (& svq -> scsi_tags );
@@ -687,9 +735,11 @@ vhost_scsi_get_cmd(struct vhost_virtqueue *vq, u64 scsi_tag)
687735 cmd = & svq -> scsi_cmds [tag ];
688736 sgl = cmd -> sgl ;
689737 prot_sgl = cmd -> prot_sgl ;
738+ log = cmd -> tvc_log ;
690739 memset (cmd , 0 , sizeof (* cmd ));
691740 cmd -> sgl = sgl ;
692741 cmd -> prot_sgl = prot_sgl ;
742+ cmd -> tvc_log = log ;
693743 cmd -> tvc_se_cmd .map_tag = tag ;
694744 cmd -> inflight = vhost_scsi_get_inflight (vq );
695745
@@ -1225,6 +1275,8 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
12251275 u8 task_attr ;
12261276 bool t10_pi = vhost_has_feature (vq , VIRTIO_SCSI_F_T10_PI );
12271277 u8 * cdb ;
1278+ struct vhost_log * vq_log ;
1279+ unsigned int log_num ;
12281280
12291281 mutex_lock (& vq -> mutex );
12301282 /*
@@ -1240,8 +1292,11 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
12401292
12411293 vhost_disable_notify (& vs -> dev , vq );
12421294
1295+ vq_log = unlikely (vhost_has_feature (vq , VHOST_F_LOG_ALL )) ?
1296+ vq -> log : NULL ;
1297+
12431298 do {
1244- ret = vhost_scsi_get_desc (vs , vq , & vc , NULL , NULL );
1299+ ret = vhost_scsi_get_desc (vs , vq , & vc , vq_log , & log_num );
12451300 if (ret )
12461301 goto err ;
12471302
@@ -1390,6 +1445,14 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
13901445 goto err ;
13911446 }
13921447
1448+ if (unlikely (vq_log && log_num )) {
1449+ ret = vhost_scsi_copy_cmd_log (vq , cmd , vq_log , log_num );
1450+ if (unlikely (ret )) {
1451+ vhost_scsi_release_cmd_res (& cmd -> tvc_se_cmd );
1452+ goto err ;
1453+ }
1454+ }
1455+
13931456 pr_debug ("vhost_scsi got command opcode: %#02x, lun: %d\n" ,
13941457 cdb [0 ], lun );
13951458 pr_debug ("cmd: %p exp_data_len: %d, prot_bytes: %d data_direction:"
@@ -1425,11 +1488,14 @@ vhost_scsi_handle_vq(struct vhost_scsi *vs, struct vhost_virtqueue *vq)
14251488 */
14261489 if (ret == - ENXIO )
14271490 break ;
1428- else if (ret == - EIO )
1491+ else if (ret == - EIO ) {
14291492 vhost_scsi_send_bad_target (vs , vq , & vc , TYPE_IO_CMD );
1430- else if (ret == - ENOMEM )
1493+ vhost_scsi_log_write (vq , vq_log , log_num );
1494+ } else if (ret == - ENOMEM ) {
14311495 vhost_scsi_send_status (vs , vq , & vc ,
14321496 SAM_STAT_TASK_SET_FULL );
1497+ vhost_scsi_log_write (vq , vq_log , log_num );
1498+ }
14331499 } while (likely (!vhost_exceeds_weight (vq , ++ c , 0 )));
14341500out :
14351501 mutex_unlock (& vq -> mutex );
@@ -1760,6 +1826,24 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
17601826 wait_for_completion (& vs -> old_inflight [i ]-> comp );
17611827}
17621828
1829+ static void vhost_scsi_destroy_vq_log (struct vhost_virtqueue * vq )
1830+ {
1831+ struct vhost_scsi_virtqueue * svq = container_of (vq ,
1832+ struct vhost_scsi_virtqueue , vq );
1833+ struct vhost_scsi_cmd * tv_cmd ;
1834+ unsigned int i ;
1835+
1836+ if (!svq -> scsi_cmds )
1837+ return ;
1838+
1839+ for (i = 0 ; i < svq -> max_cmds ; i ++ ) {
1840+ tv_cmd = & svq -> scsi_cmds [i ];
1841+ kfree (tv_cmd -> tvc_log );
1842+ tv_cmd -> tvc_log = NULL ;
1843+ tv_cmd -> tvc_log_num = 0 ;
1844+ }
1845+ }
1846+
17631847static void vhost_scsi_destroy_vq_cmds (struct vhost_virtqueue * vq )
17641848{
17651849 struct vhost_scsi_virtqueue * svq = container_of (vq ,
@@ -1779,6 +1863,7 @@ static void vhost_scsi_destroy_vq_cmds(struct vhost_virtqueue *vq)
17791863
17801864 sbitmap_free (& svq -> scsi_tags );
17811865 kfree (svq -> upages );
1866+ vhost_scsi_destroy_vq_log (vq );
17821867 kfree (svq -> scsi_cmds );
17831868 svq -> scsi_cmds = NULL ;
17841869}
@@ -2088,6 +2173,7 @@ vhost_scsi_clear_endpoint(struct vhost_scsi *vs,
20882173static int vhost_scsi_set_features (struct vhost_scsi * vs , u64 features )
20892174{
20902175 struct vhost_virtqueue * vq ;
2176+ bool is_log , was_log ;
20912177 int i ;
20922178
20932179 if (features & ~VHOST_SCSI_FEATURES )
@@ -2100,12 +2186,39 @@ static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
21002186 return - EFAULT ;
21012187 }
21022188
2189+ if (!vs -> dev .nvqs )
2190+ goto out ;
2191+
2192+ is_log = features & (1 << VHOST_F_LOG_ALL );
2193+ /*
2194+ * All VQs should have same feature.
2195+ */
2196+ was_log = vhost_has_feature (& vs -> vqs [0 ].vq , VHOST_F_LOG_ALL );
2197+
21032198 for (i = 0 ; i < vs -> dev .nvqs ; i ++ ) {
21042199 vq = & vs -> vqs [i ].vq ;
21052200 mutex_lock (& vq -> mutex );
21062201 vq -> acked_features = features ;
21072202 mutex_unlock (& vq -> mutex );
21082203 }
2204+
2205+ /*
2206+ * If VHOST_F_LOG_ALL is removed, free tvc_log after
2207+ * vq->acked_features is committed.
2208+ */
2209+ if (!is_log && was_log ) {
2210+ for (i = VHOST_SCSI_VQ_IO ; i < vs -> dev .nvqs ; i ++ ) {
2211+ if (!vs -> vqs [i ].scsi_cmds )
2212+ continue ;
2213+
2214+ vq = & vs -> vqs [i ].vq ;
2215+ mutex_lock (& vq -> mutex );
2216+ vhost_scsi_destroy_vq_log (vq );
2217+ mutex_unlock (& vq -> mutex );
2218+ }
2219+ }
2220+
2221+ out :
21092222 mutex_unlock (& vs -> dev .mutex );
21102223 return 0 ;
21112224}
0 commit comments