diff options
author | jimharris <jimharris@FreeBSD.org> | 2015-11-23 17:26:20 +0000 |
---|---|---|
committer | jimharris <jimharris@FreeBSD.org> | 2015-11-23 17:26:20 +0000 |
commit | e7b87655f99a1ecf09ab62b98b6c0fe5c00ada72 (patch) | |
tree | b63b1016a1ab94ed058f0146bd4a0de25adb661c /sys/dev | |
parent | d2f61b2025b492fdac9e1367f9953e02f2808c54 (diff) | |
download | FreeBSD-src-e7b87655f99a1ecf09ab62b98b6c0fe5c00ada72.zip FreeBSD-src-e7b87655f99a1ecf09ab62b98b6c0fe5c00ada72.tar.gz |
MFC r290198:
nvme: fix race condition in split bio completion path
Sponsored by: Intel
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/nvme/nvme_ns.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/sys/dev/nvme/nvme_ns.c b/sys/dev/nvme/nvme_ns.c index 84a1980..c6a00df 100644 --- a/sys/dev/nvme/nvme_ns.c +++ b/sys/dev/nvme/nvme_ns.c @@ -239,7 +239,7 @@ static void nvme_bio_child_inbed(struct bio *parent, int bio_error) { struct nvme_completion parent_cpl; - int inbed; + int children, inbed; if (bio_error != 0) { parent->bio_flags |= BIO_ERROR; @@ -248,10 +248,13 @@ nvme_bio_child_inbed(struct bio *parent, int bio_error) /* * atomic_fetchadd will return value before adding 1, so we still - * must add 1 to get the updated inbed number. + * must add 1 to get the updated inbed number. Save bio_children + * before incrementing to guard against race conditions when + * two children bios complete on different queues. */ + children = atomic_load_acq_int(&parent->bio_children); inbed = atomic_fetchadd_int(&parent->bio_inbed, 1) + 1; - if (inbed == parent->bio_children) { + if (inbed == children) { bzero(&parent_cpl, sizeof(parent_cpl)); if (parent->bio_flags & BIO_ERROR) parent_cpl.status.sc = NVME_SC_DATA_TRANSFER_ERROR; |