drivers/scsi/scsi_bsg.c
Source file repositories/reference/linux-study-clean/drivers/scsi/scsi_bsg.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/scsi/scsi_bsg.c- Extension
.c- Size
- 7641 bytes
- Lines
- 278
- Domain
- Driver Families
- Bucket
- drivers/scsi
- Inferred role
- Driver Families: implementation source
- Status
- source 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.
- 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.
- Touches user memory; correctness depends on fault-safe copying and privilege boundary handling.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/bsg.hlinux/io_uring/cmd.hscsi/scsi.hscsi/scsi_ioctl.hscsi/scsi_cmnd.hscsi/scsi_device.hscsi/sg.hscsi_priv.h
Detected Declarations
struct scsi_bsg_uring_cmd_pdufunction scsi_bsg_uring_task_cbfunction scsi_bsg_uring_cmd_donefunction scsi_bsg_map_user_bufferfunction scsi_bsg_uring_cmdfunction scsi_bsg_sg_io_fn
Annotated Snippet
struct scsi_bsg_uring_cmd_pdu {
struct bio *bio; /* mapped user buffer, unmap in task work */
struct request *req; /* block request, freed in task work */
u64 response_addr; /* user space response buffer address */
};
static_assert(sizeof(struct scsi_bsg_uring_cmd_pdu) <= sizeof_field(struct io_uring_cmd, pdu));
static inline struct scsi_bsg_uring_cmd_pdu *scsi_bsg_uring_cmd_pdu(
struct io_uring_cmd *ioucmd)
{
return io_uring_cmd_to_pdu(ioucmd, struct scsi_bsg_uring_cmd_pdu);
}
/* Task work: build res2 (layout in uapi/linux/bsg.h) and copy sense to user. */
static void scsi_bsg_uring_task_cb(struct io_tw_req tw_req, io_tw_token_t tw)
{
struct io_uring_cmd *ioucmd = io_uring_cmd_from_tw(tw_req);
struct scsi_bsg_uring_cmd_pdu *pdu = scsi_bsg_uring_cmd_pdu(ioucmd);
struct request *rq = pdu->req;
struct scsi_cmnd *scmd = blk_mq_rq_to_pdu(rq);
u64 res2;
int ret = 0;
u8 driver_status = 0;
u8 sense_len_wr = 0;
if (pdu->bio)
blk_rq_unmap_user(pdu->bio);
if (scsi_status_is_check_condition(scmd->result)) {
driver_status = DRIVER_SENSE;
if (pdu->response_addr)
sense_len_wr = min_t(u8, scmd->sense_len,
SCSI_SENSE_BUFFERSIZE);
}
if (sense_len_wr) {
if (copy_to_user(uptr64(pdu->response_addr), scmd->sense_buffer,
sense_len_wr))
ret = -EFAULT;
}
res2 = bsg_scsi_res2_build(status_byte(scmd->result), driver_status,
host_byte(scmd->result), sense_len_wr,
scmd->resid_len);
blk_mq_free_request(rq);
io_uring_cmd_done32(ioucmd, ret, res2,
IO_URING_CMD_TASK_WORK_ISSUE_FLAGS);
}
static enum rq_end_io_ret scsi_bsg_uring_cmd_done(struct request *req,
blk_status_t status,
const struct io_comp_batch *iocb)
{
struct io_uring_cmd *ioucmd = req->end_io_data;
io_uring_cmd_do_in_task_lazy(ioucmd, scsi_bsg_uring_task_cb);
return RQ_END_IO_NONE;
}
static int scsi_bsg_map_user_buffer(struct request *req,
struct io_uring_cmd *ioucmd,
unsigned int issue_flags, gfp_t gfp_mask)
{
const struct bsg_uring_cmd *cmd = io_uring_sqe128_cmd(ioucmd->sqe, struct bsg_uring_cmd);
bool is_write = cmd->dout_xfer_len > 0;
u64 buf_addr = is_write ? cmd->dout_xferp : cmd->din_xferp;
unsigned long buf_len = is_write ? cmd->dout_xfer_len : cmd->din_xfer_len;
struct iov_iter iter;
int ret;
if (ioucmd->flags & IORING_URING_CMD_FIXED) {
ret = io_uring_cmd_import_fixed(buf_addr, buf_len,
is_write ? WRITE : READ,
&iter, ioucmd, issue_flags);
if (ret < 0)
return ret;
ret = blk_rq_map_user_iov(req->q, req, NULL, &iter, gfp_mask);
} else {
ret = blk_rq_map_user(req->q, req, NULL, uptr64(buf_addr),
buf_len, gfp_mask);
}
return ret;
}
static int scsi_bsg_uring_cmd(struct request_queue *q, struct io_uring_cmd *ioucmd,
unsigned int issue_flags, bool open_for_write)
{
struct scsi_bsg_uring_cmd_pdu *pdu = scsi_bsg_uring_cmd_pdu(ioucmd);
Annotation
- Immediate include surface: `linux/bsg.h`, `linux/io_uring/cmd.h`, `scsi/scsi.h`, `scsi/scsi_ioctl.h`, `scsi/scsi_cmnd.h`, `scsi/scsi_device.h`, `scsi/sg.h`, `scsi_priv.h`.
- Detected declarations: `struct scsi_bsg_uring_cmd_pdu`, `function scsi_bsg_uring_task_cb`, `function scsi_bsg_uring_cmd_done`, `function scsi_bsg_map_user_buffer`, `function scsi_bsg_uring_cmd`, `function scsi_bsg_sg_io_fn`.
- Atlas domain: Driver Families / drivers/scsi.
- Implementation status: source implementation candidate.
- This snippet crosses the user/kernel memory boundary; validate fault handling and access checks before translating the pattern.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.