View | Details | Raw Unified | Return to bug 267539
Collapse All | Expand All

(-)b/sys/dev/virtio/scsi/virtio_scsi.c (-1 / +51 lines)
Lines 66-71 __FBSDID("$FreeBSD$"); Link Here
66
#include <dev/virtio/scsi/virtio_scsi.h>
66
#include <dev/virtio/scsi/virtio_scsi.h>
67
#include <dev/virtio/scsi/virtio_scsivar.h>
67
#include <dev/virtio/scsi/virtio_scsivar.h>
68
68
69
#include <sys/types.h>
70
#include <machine/atomic.h>
71
69
#include "virtio_if.h"
72
#include "virtio_if.h"
70
73
71
static int	vtscsi_modevent(module_t, int, void *);
74
static int	vtscsi_modevent(module_t, int, void *);
Lines 1629-1634 vtscsi_set_request_lun(struct ccb_hdr *ccbh, uint8_t lun[]) Link Here
1629
	lun[3] = ccbh->target_lun & 0xFF;
1632
	lun[3] = ccbh->target_lun & 0xFF;
1630
}
1633
}
1631
1634
1635
static uint32_t counter = 0;
1636
1632
static void
1637
static void
1633
vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio,
1638
vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio,
1634
    struct virtio_scsi_cmd_req *cmd_req)
1639
    struct virtio_scsi_cmd_req *cmd_req)
Lines 1650-1657 vtscsi_init_scsi_cmd_req(struct vtscsi_softc *sc, struct ccb_scsiio *csio, Link Here
1650
		break;
1655
		break;
1651
	}
1656
	}
1652
1657
1658
	// This code used to use the csio pointer as tag, but
1659
	// CTL truncates the tag to 32 bit which resulted in
1660
	// overlapping tags under load. Cargo cult the iSCSI
1661
	// tag handling.
1662
	// The iSCSI code assumes that operations won't be pending
1663
	// long enough to still to witness the 32 bit counter
1664
	// wrapping. The maximum value was reserved.
1665
	// The reservation could be an iSCSI only special case,
1666
	// but it shouldn't hurt performance to increment twice
1667
	// once every 2**32 commands.
1668
	//
1669
	// As I'm just hacking on this code without a sufficient
1670
	// understanding of its threading and locking I used an
1671
	// attomic fetchadd to increment the tag counter.
1672
	// The fetchadd operation is an atomic *post*-increment
1673
	// aka it returns the old tag value.
1674
	//
1675
	// TODO: Have this reviewed by someone with an understand of the
1676
	// SCSI specifications, VirtIO, and CAM.
1677
	// 
1678
	// Questions:
1679
	//   * The old code used the csio pointer as tag. Are there places
1680
	//     expecting to map a tag back to the csio pointer?
1681
	//     (Shouldn't have worked on 64 bit systems anyway).
1682
	//
1683
	//   * Does the tag have to be stable for csio's lifetime e.g.
1684
	//     during retries?
1685
	//
1686
	// Observations:
1687
	//   * This change alone didn't prevent the (0x4D, 0xNN)
1688
	//     overlapping tag.
1689
	uintptr_t tag;
1690
	do {
1691
		tag = atomic_fetchadd_32(&counter, 1);
1692
	} while ( __builtin_expect(tag == UINT32_MAX, false) );
1693
1653
	vtscsi_set_request_lun(&csio->ccb_h, cmd_req->lun);
1694
	vtscsi_set_request_lun(&csio->ccb_h, cmd_req->lun);
1654
	cmd_req->tag = vtscsi_gtoh64(sc, (uintptr_t) csio);
1695
	cmd_req->tag = vtscsi_gtoh64(sc, tag);
1655
	cmd_req->task_attr = attr;
1696
	cmd_req->task_attr = attr;
1656
1697
1657
	memcpy(cmd_req->cdb,
1698
	memcpy(cmd_req->cdb,
Lines 1664-1669 static void Link Here
1664
vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *sc, struct ccb_hdr *ccbh,
1705
vtscsi_init_ctrl_tmf_req(struct vtscsi_softc *sc, struct ccb_hdr *ccbh,
1665
    uint32_t subtype, uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req)
1706
    uint32_t subtype, uintptr_t tag, struct virtio_scsi_ctrl_tmf_req *tmf_req)
1666
{
1707
{
1708
	// I don't know what if anything I'm breaking by silently replacing
1709
	// the tag value with a second atomic 32 bit counter.
1710
	//
1711
	// Silence compiler warnings about unused arguments.
1712
	(void)tag;
1713
1714
	do {
1715
		tag = atomic_fetchadd_32(&counter, 1);
1716
	} while ( __builtin_expect(tag == UINT32_MAX, false) );
1667
1717
1668
	vtscsi_set_request_lun(ccbh, tmf_req->lun);
1718
	vtscsi_set_request_lun(ccbh, tmf_req->lun);
1669
1719

Return to bug 267539