In this mode we are nearly full.
Cleaning just goes for the segment with the most space
even if it is quite new.
Allocation failures return ENOSPC rather than EAGAIN
We clean even if it doesn't look like it will help much.
The heuristic for switching in an out is rather odd...
Signed-off-by: NeilBrown <neilb@suse.de>
if (err == 0)
return 0;
- if (alloc_type == NewSpace)
- return -ENOSPC;
+ if (alloc_type == NewSpace) {
+ if (test_bit(EmergencyClean, &fs->fsstate))
+ return -ENOSPC;
+ return -EAGAIN;
+ }
if (alloc_type == ReleaseSpace)
return -EAGAIN;
LAFS_BUG(1, b);
dprintk("C=%llu F=%llu T=%llu\n", C, F, T);
if ((F < C || C * F >= T * (F - C)) &&
+ !test_bit(EmergencyClean, &fs->fsstate) &&
!test_bit(CleanerBlocks, &fs->fsstate)) {
dprintk("CLEANER: enough cleaning with %d segments\n",
i);
spin_unlock(&fs->lock);
segdelete(fs->segtrack, ss);
+ if (ss->usage < (fs->devs[ss->dev].segment_size - 4) * 126 / 128)
+ /* weird heuristic ?? */
+ clear_bit(EmergencyClean, &fs->fsstate);
+ else if (ss->usage >= (fs->devs[ss->dev].segment_size - 4) * 127 / 128)
+ set_bit(EmergencyClean, &fs->fsstate);
+
+
ssm = segsum_find(fs, ss->segment, ss->dev, 0);
putdref(ssm->ssblk, MKREF(intable));
putdref(ssm->youthblk, MKREF(intable));
return rv;
}
- score = youth * usage / segsize;
+ if (test_bit(EmergencyClean, &fs->fsstate))
+ score = usage;
+ else
+ score = youth * usage / segsize + 0x10000;
spin_lock(&fs->lock);
* cleaner to progress - cleaner.need blocks are
* needed.
*/
+#define EmergencyClean 7/* Cleaner is in emergency mode and will clean
+ * the segment with the most space no matter
+ * how young it is. The fs is considered to
+ * be full and new allocation requests get
+ * -ENOSPC
+ */
struct work_struct done_work; /* used for handling
* refile after write completes */