While this shouldn't happen, the value of free_blocks isn't really
valid until the first segment scan completes. If something gets
subtracted before that it could go negative temporarily.
We really want to handle that sort of situation gracefully.
So make it a 'signed' value.
Signed-off-by: NeilBrown <neilb@suse.de>
int rv = 0;
spin_lock(&fs->alloc_lock);
while (fs->clean_reserved < max * fs->max_segment &&
int rv = 0;
spin_lock(&fs->alloc_lock);
while (fs->clean_reserved < max * fs->max_segment &&
- fs->free_blocks > (fs->clean_reserved
- + fs->allocated_blocks
- + watermark)) {
+ fs->free_blocks > 0 &&
+ (u64)fs->free_blocks > (fs->clean_reserved
+ + fs->allocated_blocks
+ + watermark)) {
fs->clean_reserved += fs->max_segment;
fs->free_blocks -= fs->max_segment;
rv++;
fs->clean_reserved += fs->max_segment;
fs->free_blocks -= fs->max_segment;
rv++;
* completed. FIXME once it has completed we need to
* check and invalidate the FS if there was a problem.
*/
* completed. FIXME once it has completed we need to
* check and invalidate the FS if there was a problem.
*/
- if (fs->free_blocks < fs->allocated_blocks
- + credits + watermark)
+ if (fs->free_blocks < 0 ||
+ (u64)fs->free_blocks < (fs->allocated_blocks
+ + credits + watermark))
credits = 0; /* Sorry, no room */
}
if (fs->rolled && watermark == 0) {
/* When including the clean_reserved space, there should
* be room for these controlled allocations
*/
credits = 0; /* Sorry, no room */
}
if (fs->rolled && watermark == 0) {
/* When including the clean_reserved space, there should
* be room for these controlled allocations
*/
+ BUG_ON(fs->free_blocks < 0);
if (fs->free_blocks + fs->clean_reserved <
fs->allocated_blocks + credits)
BUG();
if (fs->free_blocks + fs->clean_reserved <
fs->allocated_blocks + credits)
BUG();
i++;
}
printk("--------\n");
i++;
}
printk("--------\n");
- printk("free_blocks=%llu allocated=%llu max_seg=%llu clean_reserved=%llu\n",
+ printk("free_blocks=%lld allocated=%llu max_seg=%llu clean_reserved=%llu\n",
dfs->free_blocks, dfs->allocated_blocks, dfs->max_segment,
dfs->clean_reserved);
}
dfs->free_blocks, dfs->allocated_blocks, dfs->max_segment,
dfs->clean_reserved);
}
/* counters for (pre)allocating space. */
spinlock_t alloc_lock;
/* counters for (pre)allocating space. */
spinlock_t alloc_lock;
- u64 free_blocks; /* initialised from free segment info */
+ s64 free_blocks; /* initialised from free segment info */
u64 allocated_blocks; /* Blocks that have been (pre)allocated */
u64 clean_reserved; /* Blocks reserved for cleaner segments */
u64 max_segment; /* largest segment size */
u64 allocated_blocks; /* Blocks that have been (pre)allocated */
u64 clean_reserved; /* Blocks reserved for cleaner segments */
u64 max_segment; /* largest segment size */