T -= 4 * fs->max_segment;
max_segs = lafs_alloc_cleaner_segs(fs, 4);
- if (max_segs < 1)
- /* if we can only clean to main segment, do it
- * but only do one segment at a time
+ if (max_segs < 1) {
+ /* If we can only clean to main segment, we may
+ * have to. However:
+ * - only do one segment at a time
+ * - if there is any clean_reserved, then use it
+ * - if there are no 'clean' segments, then clean.
+ * - if CleanerBlocks, then clean.
+ * otherwise don't.
*/
- max_segs = 1;
+ if (fs->clean_reserved
+ || fs->segtrack->clean.cnt == 0
+ || test_bit(CleanerBlocks, &fs->fsstate))
+ max_segs = 1;
+ }
for (i = 0; i < max_segs; i++) {
struct toclean *tc = &fs->cleaner.seg[i];
u64 C = fs->free_blocks + fs->clean_reserved
close_segment(fs, cnum);
- /* FIXME if clean_reserve is too small, maybe
- * clear it completely.
- */
- if ((cnum && fs->clean_reserved < fs->max_segment))
- return -ENOSPC;
+ if (cnum && fs->clean_reserved < fs->max_segment) {
+ /* we have reached the end of the last cleaner
+ * segment. The remainder of clean_reserved
+ * is of no value (if there even is any
+ */
+ if (fs->clean_reserved) {
+ spin_lock(&fs->alloc_lock);
+ fs->free_blocks += fs->clean_reserved;
+ fs->clean_reserved = 0;
+ spin_unlock(&fs->alloc_lock);
+ }
+ return -ENOSPC;
+ }
/* This gets a reference on the 'segsum' */
lafs_free_get(fs, &dev, &seg, 0);
seg_setpos(fs, &wc->seg, segtovirt(fs, dev, seg));