Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

lib/group_cpus: Let group_cpu_evenly() return the number of initialized masks

group_cpu_evenly() might have allocated less groups then requested:

group_cpu_evenly()
__group_cpus_evenly()
alloc_nodes_groups()
# allocated total groups may be less than numgrps when
# active total CPU number is less then numgrps

In this case, the caller will do an out of bound access because the
caller assumes the masks returned has numgrps.

Return the number of groups created so the caller can limit the access
range accordingly.

Acked-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Ming Lei <ming.lei@redhat.com>
Signed-off-by: Daniel Wagner <wagi@kernel.org>
Reviewed-by: Chaitanya Kulkarni <kch@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Link: https://lore.kernel.org/r/20250617-isolcpus-queue-counters-v1-1-13923686b54b@kernel.org
Signed-off-by: Jens Axboe <axboe@kernel.dk>

authored by

Daniel Wagner and committed by
Jens Axboe
b6139a6a 857f4318

+25 -25
+3 -3
block/blk-mq-cpumap.c
··· 19 19 void blk_mq_map_queues(struct blk_mq_queue_map *qmap) 20 20 { 21 21 const struct cpumask *masks; 22 - unsigned int queue, cpu; 22 + unsigned int queue, cpu, nr_masks; 23 23 24 - masks = group_cpus_evenly(qmap->nr_queues); 24 + masks = group_cpus_evenly(qmap->nr_queues, &nr_masks); 25 25 if (!masks) { 26 26 for_each_possible_cpu(cpu) 27 27 qmap->mq_map[cpu] = qmap->queue_offset; ··· 29 29 } 30 30 31 31 for (queue = 0; queue < qmap->nr_queues; queue++) { 32 - for_each_cpu(cpu, &masks[queue]) 32 + for_each_cpu(cpu, &masks[queue % nr_masks]) 33 33 qmap->mq_map[cpu] = qmap->queue_offset + queue; 34 34 } 35 35 kfree(masks);
+5 -4
drivers/virtio/virtio_vdpa.c
··· 329 329 330 330 for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) { 331 331 unsigned int this_vecs = affd->set_size[i]; 332 + unsigned int nr_masks; 332 333 int j; 333 - struct cpumask *result = group_cpus_evenly(this_vecs); 334 + struct cpumask *result = group_cpus_evenly(this_vecs, &nr_masks); 334 335 335 336 if (!result) { 336 337 kfree(masks); 337 338 return NULL; 338 339 } 339 340 340 - for (j = 0; j < this_vecs; j++) 341 + for (j = 0; j < nr_masks; j++) 341 342 cpumask_copy(&masks[curvec + j], &result[j]); 342 343 kfree(result); 343 344 344 - curvec += this_vecs; 345 - usedvecs += this_vecs; 345 + curvec += nr_masks; 346 + usedvecs += nr_masks; 346 347 } 347 348 348 349 /* Fill out vectors at the end that don't need affinity */
+3 -3
fs/fuse/virtio_fs.c
··· 862 862 static void virtio_fs_map_queues(struct virtio_device *vdev, struct virtio_fs *fs) 863 863 { 864 864 const struct cpumask *mask, *masks; 865 - unsigned int q, cpu; 865 + unsigned int q, cpu, nr_masks; 866 866 867 867 /* First attempt to map using existing transport layer affinities 868 868 * e.g. PCIe MSI-X ··· 882 882 return; 883 883 fallback: 884 884 /* Attempt to map evenly in groups over the CPUs */ 885 - masks = group_cpus_evenly(fs->num_request_queues); 885 + masks = group_cpus_evenly(fs->num_request_queues, &nr_masks); 886 886 /* If even this fails we default to all CPUs use first request queue */ 887 887 if (!masks) { 888 888 for_each_possible_cpu(cpu) ··· 891 891 } 892 892 893 893 for (q = 0; q < fs->num_request_queues; q++) { 894 - for_each_cpu(cpu, &masks[q]) 894 + for_each_cpu(cpu, &masks[q % nr_masks]) 895 895 fs->mq_map[cpu] = q + VQ_REQUEST; 896 896 } 897 897 kfree(masks);
+1 -1
include/linux/group_cpus.h
··· 9 9 #include <linux/kernel.h> 10 10 #include <linux/cpu.h> 11 11 12 - struct cpumask *group_cpus_evenly(unsigned int numgrps); 12 + struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks); 13 13 14 14 #endif
+5 -6
kernel/irq/affinity.c
··· 69 69 * have multiple sets, build each sets affinity mask separately. 70 70 */ 71 71 for (i = 0, usedvecs = 0; i < affd->nr_sets; i++) { 72 - unsigned int this_vecs = affd->set_size[i]; 73 - int j; 74 - struct cpumask *result = group_cpus_evenly(this_vecs); 72 + unsigned int nr_masks, this_vecs = affd->set_size[i]; 73 + struct cpumask *result = group_cpus_evenly(this_vecs, &nr_masks); 75 74 76 75 if (!result) { 77 76 kfree(masks); 78 77 return NULL; 79 78 } 80 79 81 - for (j = 0; j < this_vecs; j++) 80 + for (int j = 0; j < nr_masks; j++) 82 81 cpumask_copy(&masks[curvec + j].mask, &result[j]); 83 82 kfree(result); 84 83 85 - curvec += this_vecs; 86 - usedvecs += this_vecs; 84 + curvec += nr_masks; 85 + usedvecs += nr_masks; 87 86 } 88 87 89 88 /* Fill out vectors at the end that don't need affinity */
+8 -8
lib/group_cpus.c
··· 332 332 /** 333 333 * group_cpus_evenly - Group all CPUs evenly per NUMA/CPU locality 334 334 * @numgrps: number of groups 335 + * @nummasks: number of initialized cpumasks 335 336 * 336 337 * Return: cpumask array if successful, NULL otherwise. And each element 337 - * includes CPUs assigned to this group 338 + * includes CPUs assigned to this group. nummasks contains the number 339 + * of initialized masks which can be less than numgrps. 338 340 * 339 341 * Try to put close CPUs from viewpoint of CPU and NUMA locality into 340 342 * same group, and run two-stage grouping: ··· 346 344 * We guarantee in the resulted grouping that all CPUs are covered, and 347 345 * no same CPU is assigned to multiple groups 348 346 */ 349 - struct cpumask *group_cpus_evenly(unsigned int numgrps) 347 + struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks) 350 348 { 351 349 unsigned int curgrp = 0, nr_present = 0, nr_others = 0; 352 350 cpumask_var_t *node_to_cpumask; ··· 391 389 ret = __group_cpus_evenly(curgrp, numgrps, node_to_cpumask, 392 390 npresmsk, nmsk, masks); 393 391 if (ret < 0) 394 - goto fail_build_affinity; 392 + goto fail_node_to_cpumask; 395 393 nr_present = ret; 396 394 397 395 /* ··· 410 408 if (ret >= 0) 411 409 nr_others = ret; 412 410 413 - fail_build_affinity: 414 - if (ret >= 0) 415 - WARN_ON(nr_present + nr_others < numgrps); 416 - 417 411 fail_node_to_cpumask: 418 412 free_node_to_cpumask(node_to_cpumask); 419 413 ··· 422 424 kfree(masks); 423 425 return NULL; 424 426 } 427 + *nummasks = min(nr_present + nr_others, numgrps); 425 428 return masks; 426 429 } 427 430 #else /* CONFIG_SMP */ 428 - struct cpumask *group_cpus_evenly(unsigned int numgrps) 431 + struct cpumask *group_cpus_evenly(unsigned int numgrps, unsigned int *nummasks) 429 432 { 430 433 struct cpumask *masks; 431 434 ··· 439 440 440 441 /* assign all CPUs(cpu 0) to the 1st group only */ 441 442 cpumask_copy(&masks[0], cpu_possible_mask); 443 + *nummasks = 1; 442 444 return masks; 443 445 } 444 446 #endif /* CONFIG_SMP */