mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	lib/sbitmap: Fix invalid loop in __sbitmap_queue_get_batch()
1. Getting next index before continue branch.
2. Checking free bits when setting the target bits. Otherwise,
it may reuse the busying bits.
Signed-off-by: wuchi <wuchi.zero@gmail.com>
Reviewed-by: Martin Wilck <mwilck@suse.com>
Link: https://lore.kernel.org/r/20220605145835.26916-1-wuchi.zero@gmail.com
Fixes: 9672b0d437 ("sbitmap: add __sbitmap_queue_get_batch()")
Signed-off-by: Jens Axboe <axboe@kernel.dk>
			
			
This commit is contained in:
		
							parent
							
								
									e531485a0a
								
							
						
					
					
						commit
						fbb564a557
					
				
					 1 changed files with 4 additions and 1 deletions
				
			
		| 
						 | 
					@ -528,7 +528,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sbitmap_deferred_clear(map);
 | 
							sbitmap_deferred_clear(map);
 | 
				
			||||||
		if (map->word == (1UL << (map_depth - 1)) - 1)
 | 
							if (map->word == (1UL << (map_depth - 1)) - 1)
 | 
				
			||||||
			continue;
 | 
								goto next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		nr = find_first_zero_bit(&map->word, map_depth);
 | 
							nr = find_first_zero_bit(&map->word, map_depth);
 | 
				
			||||||
		if (nr + nr_tags <= map_depth) {
 | 
							if (nr + nr_tags <= map_depth) {
 | 
				
			||||||
| 
						 | 
					@ -539,6 +539,8 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
 | 
				
			||||||
			get_mask = ((1UL << map_tags) - 1) << nr;
 | 
								get_mask = ((1UL << map_tags) - 1) << nr;
 | 
				
			||||||
			do {
 | 
								do {
 | 
				
			||||||
				val = READ_ONCE(map->word);
 | 
									val = READ_ONCE(map->word);
 | 
				
			||||||
 | 
									if ((val & ~get_mask) != val)
 | 
				
			||||||
 | 
										goto next;
 | 
				
			||||||
				ret = atomic_long_cmpxchg(ptr, val, get_mask | val);
 | 
									ret = atomic_long_cmpxchg(ptr, val, get_mask | val);
 | 
				
			||||||
			} while (ret != val);
 | 
								} while (ret != val);
 | 
				
			||||||
			get_mask = (get_mask & ~ret) >> nr;
 | 
								get_mask = (get_mask & ~ret) >> nr;
 | 
				
			||||||
| 
						 | 
					@ -549,6 +551,7 @@ unsigned long __sbitmap_queue_get_batch(struct sbitmap_queue *sbq, int nr_tags,
 | 
				
			||||||
				return get_mask;
 | 
									return get_mask;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					next:
 | 
				
			||||||
		/* Jump to next index. */
 | 
							/* Jump to next index. */
 | 
				
			||||||
		if (++index >= sb->map_nr)
 | 
							if (++index >= sb->map_nr)
 | 
				
			||||||
			index = 0;
 | 
								index = 0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue