nvme: add context annotations for nvme_subsystem::lock

Several helpers access or traverse data structures protected by
nvme_subsystem::lock and therefore require callers to hold the lock.
Annotate nvme_mpath_unfreeze(), nvme_mpath_wait_freeze(),
nvme_mpath_start_freeze(), nvme_find_ns_head(), nvme_alloc_ns_head()
and nvme_subsys_check_duplicate_ids() with __must_hold(&subsys->lock)
so that Clang's lock context analysis can validate the locking
requirements at compile time.

Also annotate nvme_subsystem::nsheads and
nvme_ns_head::delayed_removal_secs with __guarded_by(&subsys->lock),
as both are protected by the subsystem lock.

Annotate nvme_init_subsystem() with __context_unsafe(), as it
initializes these lock-protected members before the object is published,
suppressing a false positive from Clang's context analysis.

Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Nilay Shroff <nilay@linux.ibm.com>
Signed-off-by: Keith Busch <kbusch@kernel.org>
This commit is contained in:
Nilay Shroff 2026-07-13 17:24:12 +05:30 committed by Keith Busch
parent 9c65eeeb26
commit d1fdf49b5f
2 changed files with 14 additions and 5 deletions

View File

@ -3287,6 +3287,7 @@ static bool nvme_validate_cntlid(struct nvme_subsystem *subsys,
}
static int nvme_init_subsystem(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
__context_unsafe(/* initialize unpublished/lock-guarded variables */)
{
struct nvme_subsystem *subsys, *found;
int ret;
@ -3858,6 +3859,7 @@ static const struct file_operations nvme_dev_fops = {
static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
unsigned nsid)
__must_hold(&ctrl->subsys->lock)
{
struct nvme_ns_head *h;
@ -3880,6 +3882,7 @@ static struct nvme_ns_head *nvme_find_ns_head(struct nvme_ctrl *ctrl,
static int nvme_subsys_check_duplicate_ids(struct nvme_subsystem *subsys,
struct nvme_ns_ids *ids)
__must_hold(&subsys->lock)
{
bool has_uuid = !uuid_is_null(&ids->uuid);
bool has_nguid = memchr_inv(ids->nguid, 0, sizeof(ids->nguid));
@ -3988,6 +3991,7 @@ static void nvme_add_ns_cdev(struct nvme_ns *ns)
static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,
struct nvme_ns_info *info)
__must_hold(&ctrl->subsys->lock)
{
struct nvme_ns_head *head;
size_t size = sizeof(*head);

View File

@ -496,7 +496,8 @@ struct nvme_subsystem {
struct list_head entry;
struct mutex lock;
struct list_head ctrls;
struct list_head nsheads;
struct list_head nsheads
__guarded_by(&lock);
char subnqn[NVMF_NQN_SIZE];
char serial[20];
char model[40];
@ -569,7 +570,8 @@ struct nvme_ns_head {
struct mutex lock;
unsigned long flags;
struct delayed_work remove_work;
unsigned int delayed_removal_secs;
unsigned int delayed_removal_secs
__guarded_by(&subsys->lock);
atomic_long_t io_requeue_no_usable_path_count;
atomic_long_t io_fail_no_available_path_count;
#define NVME_NSHEAD_DISK_LIVE 0
@ -1042,9 +1044,12 @@ static inline bool nvme_ctrl_use_ana(struct nvme_ctrl *ctrl)
return ctrl->ana_log_buf != NULL;
}
void nvme_mpath_unfreeze(struct nvme_subsystem *subsys);
void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys);
void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
void nvme_mpath_unfreeze(struct nvme_subsystem *subsys)
__must_hold(&subsys->lock);
void nvme_mpath_wait_freeze(struct nvme_subsystem *subsys)
__must_hold(&subsys->lock);
void nvme_mpath_start_freeze(struct nvme_subsystem *subsys)
__must_hold(&subsys->lock);
void nvme_mpath_default_iopolicy(struct nvme_subsystem *subsys);
void nvme_failover_req(struct request *req);
void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);