From 7725c45682abd7a6590676c33c35a7bdfdec6db5 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Fri, 29 May 2026 11:03:10 -0700 Subject: ata: libata: Document when host->eh_mutex should be held Annotate the following functions with __must_hold(&host->eh_mutex): * All ata_port_operations.error_handler() implementations. * ata_eh_reset() and ata_eh_recover() because these functions call ata_eh_release() and ata_eh_acquire(). * All callers of ata_eh_reset() and ata_eh_recover(). Enable Clang's context analysis. This will cause the build to fail if e.g. a locking bug would be introduced in an error path. This patch should not affect the generated assembler code. Signed-off-by: Bart Van Assche [cassel: drop note about clang 23 from commit log] Signed-off-by: Niklas Cassel --- include/linux/libata.h | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 127229fbd1a6..7091bc903c05 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -984,7 +984,8 @@ struct ata_port_operations { void (*thaw)(struct ata_port *ap); struct ata_reset_operations reset; struct ata_reset_operations pmp_reset; - void (*error_handler)(struct ata_port *ap); + void (*error_handler)(struct ata_port *ap) + __must_hold(&ap->host->eh_mutex); void (*lost_interrupt)(struct ata_port *ap); void (*post_internal_cmd)(struct ata_queued_cmd *qc); void (*sched_eh)(struct ata_port *ap); @@ -1419,7 +1420,8 @@ extern void ata_eh_thaw_port(struct ata_port *ap); extern void ata_eh_qc_complete(struct ata_queued_cmd *qc); extern void ata_eh_qc_retry(struct ata_queued_cmd *qc); -extern void ata_std_error_handler(struct ata_port *ap); +extern void ata_std_error_handler(struct ata_port *ap) + __must_hold(&ap->host->eh_mutex); extern void ata_std_sched_eh(struct ata_port *ap); extern void ata_std_end_eh(struct ata_port *ap); extern int ata_link_nr_enabled(struct ata_link *link); @@ -1999,7 +2001,8 @@ extern void ata_timing_merge(const struct ata_timing *, extern const struct ata_port_operations sata_pmp_port_ops; extern int sata_pmp_qc_defer_cmd_switch(struct ata_queued_cmd *qc); -extern void sata_pmp_error_handler(struct ata_port *ap); +extern void sata_pmp_error_handler(struct ata_port *ap) + __must_hold(&ap->host->eh_mutex); #else /* CONFIG_SATA_PMP */ @@ -2063,7 +2066,8 @@ extern int sata_sff_hardreset(struct ata_link *link, unsigned int *class, unsigned long deadline); extern void ata_sff_postreset(struct ata_link *link, unsigned int *classes); extern void ata_sff_drain_fifo(struct ata_queued_cmd *qc); -extern void ata_sff_error_handler(struct ata_port *ap); +extern void ata_sff_error_handler(struct ata_port *ap) + __must_hold(&ap->host->eh_mutex); extern void ata_sff_std_ports(struct ata_ioports *ioaddr); #ifdef CONFIG_PCI extern int ata_pci_sff_init_host(struct ata_host *host); @@ -2093,7 +2097,8 @@ extern enum ata_completion_errors ata_bmdma_dumb_qc_prep(struct ata_queued_cmd * extern unsigned int ata_bmdma_port_intr(struct ata_port *ap, struct ata_queued_cmd *qc); extern irqreturn_t ata_bmdma_interrupt(int irq, void *dev_instance); -extern void ata_bmdma_error_handler(struct ata_port *ap); +extern void ata_bmdma_error_handler(struct ata_port *ap) + __must_hold(&ap->host->eh_mutex); extern void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc); extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_setup(struct ata_queued_cmd *qc); -- cgit v1.2.3 From 042f5526cf2c44eac17ed2fa57a9a6e8d30d6279 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Thu, 28 May 2026 19:28:59 +0200 Subject: ata: Annotate functions in the issuing path with __must_hold() Annotate the following functions used in the issuing path: ata_qc_issue(), ata_sas_queuecmd(), ata_scsi_qc_issue(), ata_scsi_translate(), __ata_scsi_queuecmd() These functions are all used in the issuing path, so context analysis will be able to verify that the ap lock is held, from it is taken in sas_queuecommand() or ata_scsi_queuecmd() all the way down to ata_qc_issue(). Commenting out the spin_lock_irqsave() successfully results in a compiler error on Clang 23. Signed-off-by: Bart Van Assche Co-developed-by: Niklas Cassel Reviewed-by: Hannes Reinecke Signed-off-by: Niklas Cassel --- include/linux/libata.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index 7091bc903c05..96e626d6a7ca 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1315,7 +1315,8 @@ extern int ata_tport_add(struct device *parent, struct ata_port *ap); extern void ata_tport_delete(struct ata_port *ap); int ata_sas_sdev_configure(struct scsi_device *sdev, struct queue_limits *lim, struct ata_port *ap); -extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap); +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap) + __must_hold(ap->lock); extern void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis); extern void ata_tf_from_fis(const u8 *fis, struct ata_taskfile *tf); -- cgit v1.2.3