drivers/scsi/scsi_debug.c

Source file repositories/reference/linux-study-clean/drivers/scsi/scsi_debug.c

File Facts

System
Linux kernel
Corpus path
drivers/scsi/scsi_debug.c
Extension
.c
Size
281582 bytes
Lines
9691
Domain
Driver Families
Bucket
drivers/scsi
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct bus_type pseudo_lld_bus;

static struct device_driver sdebug_driverfs_driver = {
	.name 		= sdebug_proc_name,
	.bus		= &pseudo_lld_bus,
};

static const int check_condition_result =
	SAM_STAT_CHECK_CONDITION;

static const int illegal_condition_result =
	(DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;

static const int device_qfull_result =
	(DID_ABORT << 16) | SAM_STAT_TASK_SET_FULL;

static const int condition_met_result = SAM_STAT_CONDITION_MET;

static struct dentry *sdebug_debugfs_root;
static ASYNC_DOMAIN_EXCLUSIVE(sdebug_async_domain);

static u32 sdebug_get_devsel(struct scsi_device *sdp)
{
	unsigned char devtype = sdp->type;
	u32 devsel;

	if (devtype < 32)
		devsel = (1 << devtype);
	else
		devsel = DS_ALL;

	return devsel;
}

static void sdebug_err_free(struct rcu_head *head)
{
	struct sdebug_err_inject *inject =
		container_of(head, typeof(*inject), rcu);

	kfree(inject);
}

static void sdebug_err_add(struct scsi_device *sdev, struct sdebug_err_inject *new)
{
	struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata;
	struct sdebug_err_inject *err;

	spin_lock(&devip->list_lock);
	list_for_each_entry_rcu(err, &devip->inject_err_list, list) {
		if (err->type == new->type && err->cmd == new->cmd) {
			list_del_rcu(&err->list);
			call_rcu(&err->rcu, sdebug_err_free);
		}
	}

	list_add_tail_rcu(&new->list, &devip->inject_err_list);
	spin_unlock(&devip->list_lock);
}

static int sdebug_err_remove(struct scsi_device *sdev, const char *buf, size_t count)
{
	struct sdebug_dev_info *devip = (struct sdebug_dev_info *)sdev->hostdata;
	struct sdebug_err_inject *err;
	int type;
	unsigned char cmd;

	if (sscanf(buf, "- %d %hhx", &type, &cmd) != 2) {
		kfree(buf);
		return -EINVAL;
	}

	spin_lock(&devip->list_lock);
	list_for_each_entry_rcu(err, &devip->inject_err_list, list) {
		if (err->type == type && err->cmd == cmd) {
			list_del_rcu(&err->list);
			call_rcu(&err->rcu, sdebug_err_free);
			spin_unlock(&devip->list_lock);
			kfree(buf);
			return count;
		}
	}
	spin_unlock(&devip->list_lock);

	kfree(buf);
	return -EINVAL;
}

static int sdebug_error_show(struct seq_file *m, void *p)
{
	struct scsi_device *sdev = (struct scsi_device *)m->private;

Annotation

Implementation Notes