Since free space we report in statfs is file size which should
fit to the FS - change the way we calculate free space and use
leb_overhead instead of dark_wm in calculations.
Results of "freespace" test (120MiB volume, 16KiB LEB size,
512 bytes page size). Before the change:
freespace: Test 1: fill the space we have 3 times
freespace: was free:
85204992 bytes 81.3 MiB, wrote:
96489472 bytes 92.0 MiB, delta:
11284480 bytes 10.8 MiB, wrote 13.2% more than predicted
freespace: was free:
83554304 bytes 79.7 MiB, wrote:
96489472 bytes 92.0 MiB, delta:
12935168 bytes 12.3 MiB, wrote 15.5% more than predicted
freespace: was free:
83554304 bytes 79.7 MiB, wrote:
96493568 bytes 92.0 MiB, delta:
12939264 bytes 12.3 MiB, wrote 15.5% more than predicted
freespace: Test 1 finished
freespace: Test 2: gradually lessen amount of free space and fill the FS
freespace: do 10 steps, lessen free space by
7596218 bytes 7.2 MiB each time
freespace: was free:
78675968 bytes 75.0 MiB, wrote:
88903680 bytes 84.8 MiB, delta:
10227712 bytes 9.8 MiB, wrote 13.0% more than predicted
freespace: was free:
72015872 bytes 68.7 MiB, wrote:
81514496 bytes 77.7 MiB, delta:
9498624 bytes 9.1 MiB, wrote 13.2% more than predicted
freespace: was free:
63938560 bytes 61.0 MiB, wrote:
72589312 bytes 69.2 MiB, delta:
8650752 bytes 8.2 MiB, wrote 13.5% more than predicted
freespace: was free:
56127488 bytes 53.5 MiB, wrote:
63762432 bytes 60.8 MiB, delta:
7634944 bytes 7.3 MiB, wrote 13.6% more than predicted
freespace: was free:
48336896 bytes 46.1 MiB, wrote:
54935552 bytes 52.4 MiB, delta:
6598656 bytes 6.3 MiB, wrote 13.7% more than predicted
freespace: was free:
40587264 bytes 38.7 MiB, wrote:
46157824 bytes 44.0 MiB, delta:
5570560 bytes 5.3 MiB, wrote 13.7% more than predicted
freespace: was free:
32841728 bytes 31.3 MiB, wrote:
37384192 bytes 35.7 MiB, delta:
4542464 bytes 4.3 MiB, wrote 13.8% more than predicted
freespace: was free:
25100288 bytes 23.9 MiB, wrote:
28618752 bytes 27.3 MiB, delta:
3518464 bytes 3.4 MiB, wrote 14.0% more than predicted
freespace: was free:
17342464 bytes 16.5 MiB, wrote:
19841024 bytes 18.9 MiB, delta:
2498560 bytes 2.4 MiB, wrote 14.4% more than predicted
freespace: was free:
9605120 bytes 9.2 MiB, wrote:
11063296 bytes 10.6 MiB, delta:
1458176 bytes 1.4 MiB, wrote 15.2% more than predicted
freespace: Test 2 finished
freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS
freespace: do 10 steps, lessen free space by
7606272 bytes 7.3 MiB each time
freespace: trashing: was free:
83668992 bytes 79.8 MiB, need free:
7606272 bytes 7.3 MiB, files created: 248297, delete 225724 (90.9% of them)
freespace: was free:
70803456 bytes 67.5 MiB, wrote:
82485248 bytes 78.7 MiB, delta:
11681792 bytes 11.1 MiB, wrote 16.5% more than predicted
freespace: trashing: was free:
81080320 bytes 77.3 MiB, need free:
15212544 bytes 14.5 MiB, files created: 248711, delete 202047 (81.2% of them)
freespace: was free:
59867136 bytes 57.1 MiB, wrote:
71897088 bytes 68.6 MiB, delta:
12029952 bytes 11.5 MiB, wrote 20.1% more than predicted
freespace: trashing: was free:
82243584 bytes 78.4 MiB, need free:
22818816 bytes 21.8 MiB, files created: 248866, delete 179817 (72.3% of them)
freespace: was free:
50905088 bytes 48.5 MiB, wrote:
63168512 bytes 60.2 MiB, delta:
12263424 bytes 11.7 MiB, wrote 24.1% more than predicted
freespace: trashing: was free:
83402752 bytes 79.5 MiB, need free:
30425088 bytes 29.0 MiB, files created: 248920, delete 158114 (63.5% of them)
freespace: was free:
42651648 bytes 40.7 MiB, wrote:
55406592 bytes 52.8 MiB, delta:
12754944 bytes 12.2 MiB, wrote 29.9% more than predicted
freespace: trashing: was free:
84402176 bytes 80.5 MiB, need free:
38031360 bytes 36.3 MiB, files created: 248709, delete 136641 (54.9% of them)
freespace: was free:
35233792 bytes 33.6 MiB, wrote:
48250880 bytes 46.0 MiB, delta:
13017088 bytes 12.4 MiB, wrote 36.9% more than predicted
freespace: trashing: was free:
82530304 bytes 78.7 MiB, need free:
45637632 bytes 43.5 MiB, files created: 248778, delete 111208 (44.7% of them)
freespace: was free:
27287552 bytes 26.0 MiB, wrote:
40267776 bytes 38.4 MiB, delta:
12980224 bytes 12.4 MiB, wrote 47.6% more than predicted
freespace: trashing: was free:
85114880 bytes 81.2 MiB, need free:
53243904 bytes 50.8 MiB, files created: 248508, delete 93052 (37.4% of them)
freespace: was free:
22437888 bytes 21.4 MiB, wrote:
35328000 bytes 33.7 MiB, delta:
12890112 bytes 12.3 MiB, wrote 57.4% more than predicted
freespace: trashing: was free:
84103168 bytes 80.2 MiB, need free:
60850176 bytes 58.0 MiB, files created: 248637, delete 68743 (27.6% of them)
freespace: was free:
15536128 bytes 14.8 MiB, wrote:
28319744 bytes 27.0 MiB, delta:
12783616 bytes 12.2 MiB, wrote 82.3% more than predicted
freespace: trashing: was free:
84357120 bytes 80.4 MiB, need free:
68456448 bytes 65.3 MiB, files created: 248567, delete 46852 (18.8% of them)
freespace: was free:
9015296 bytes 8.6 MiB, wrote:
22044672 bytes 21.0 MiB, delta:
13029376 bytes 12.4 MiB, wrote 144.5% more than predicted
freespace: trashing: was free:
84942848 bytes 81.0 MiB, need free:
76062720 bytes 72.5 MiB, files created: 248636, delete 25993 (10.5% of them)
freespace: was free:
6086656 bytes 5.8 MiB, wrote:
8331264 bytes 7.9 MiB, delta:
2244608 bytes 2.1 MiB, wrote 36.9% more than predicted
freespace: Test 3 finished
freespace: finished successfully
After the change:
freespace: Test 1: fill the space we have 3 times
freespace: was free:
94048256 bytes 89.7 MiB, wrote:
96489472 bytes 92.0 MiB, delta:
2441216 bytes 2.3 MiB, wrote 2.6% more than predicted
freespace: was free:
92246016 bytes 88.0 MiB, wrote:
96493568 bytes 92.0 MiB, delta:
4247552 bytes 4.1 MiB, wrote 4.6% more than predicted
freespace: was free:
92254208 bytes 88.0 MiB, wrote:
96489472 bytes 92.0 MiB, delta:
4235264 bytes 4.0 MiB, wrote 4.6% more than predicted
freespace: Test 1 finished
freespace: Test 2: gradually lessen amount of free space and fill the FS
freespace: do 10 steps, lessen free space by
8386001 bytes 8.0 MiB each time
freespace: was free:
86605824 bytes 82.6 MiB, wrote:
88252416 bytes 84.2 MiB, delta:
1646592 bytes 1.6 MiB, wrote 1.9% more than predicted
freespace: was free:
78667776 bytes 75.0 MiB, wrote:
80715776 bytes 77.0 MiB, delta:
2048000 bytes 2.0 MiB, wrote 2.6% more than predicted
freespace: was free:
69615616 bytes 66.4 MiB, wrote:
71630848 bytes 68.3 MiB, delta:
2015232 bytes 1.9 MiB, wrote 2.9% more than predicted
freespace: was free:
61018112 bytes 58.2 MiB, wrote:
62783488 bytes 59.9 MiB, delta:
1765376 bytes 1.7 MiB, wrote 2.9% more than predicted
freespace: was free:
52424704 bytes 50.0 MiB, wrote:
53968896 bytes 51.5 MiB, delta:
1544192 bytes 1.5 MiB, wrote 2.9% more than predicted
freespace: was free:
43880448 bytes 41.8 MiB, wrote:
45199360 bytes 43.1 MiB, delta:
1318912 bytes 1.3 MiB, wrote 3.0% more than predicted
freespace: was free:
35332096 bytes 33.7 MiB, wrote:
36425728 bytes 34.7 MiB, delta:
1093632 bytes 1.0 MiB, wrote 3.1% more than predicted
freespace: was free:
26771456 bytes 25.5 MiB, wrote:
27643904 bytes 26.4 MiB, delta: 872448 bytes 852.0 KiB, wrote 3.3% more than predicted
freespace: was free:
18231296 bytes 17.4 MiB, wrote:
18878464 bytes 18.0 MiB, delta: 647168 bytes 632.0 KiB, wrote 3.5% more than predicted
freespace: was free:
9674752 bytes 9.2 MiB, wrote:
10088448 bytes 9.6 MiB, delta: 413696 bytes 404.0 KiB, wrote 4.3% more than predicted
freespace: Test 2 finished
freespace: Test 3: gradually lessen amount of free space by trashing and fill the FS
freespace: do 10 steps, lessen free space by
8397544 bytes 8.0 MiB each time
freespace: trashing: was free:
92372992 bytes 88.1 MiB, need free:
8397552 bytes 8.0 MiB, files created: 248296, delete 225723 (90.9% of them)
freespace: was free:
71909376 bytes 68.6 MiB, wrote:
82472960 bytes 78.7 MiB, delta:
10563584 bytes 10.1 MiB, wrote 14.7% more than predicted
freespace: trashing: was free:
88989696 bytes 84.9 MiB, need free:
16795096 bytes 16.0 MiB, files created: 248794, delete 201838 (81.1% of them)
freespace: was free:
60354560 bytes 57.6 MiB, wrote:
71782400 bytes 68.5 MiB, delta:
11427840 bytes 10.9 MiB, wrote 18.9% more than predicted
freespace: trashing: was free:
90304512 bytes 86.1 MiB, need free:
25192640 bytes 24.0 MiB, files created: 248733, delete 179342 (72.1% of them)
freespace: was free:
51187712 bytes 48.8 MiB, wrote:
62943232 bytes 60.0 MiB, delta:
11755520 bytes 11.2 MiB, wrote 23.0% more than predicted
freespace: trashing: was free:
91209728 bytes 87.0 MiB, need free:
33590184 bytes 32.0 MiB, files created: 248779, delete 157160 (63.2% of them)
freespace: was free:
42704896 bytes 40.7 MiB, wrote:
55050240 bytes 52.5 MiB, delta:
12345344 bytes 11.8 MiB, wrote 28.9% more than predicted
freespace: trashing: was free:
92700672 bytes 88.4 MiB, need free:
41987728 bytes 40.0 MiB, files created: 248848, delete 136135 (54.7% of them)
freespace: was free:
35250176 bytes 33.6 MiB, wrote:
48115712 bytes 45.9 MiB, delta:
12865536 bytes 12.3 MiB, wrote 36.5% more than predicted
freespace: trashing: was free:
93986816 bytes 89.6 MiB, need free:
50385272 bytes 48.1 MiB, files created: 248723, delete 115385 (46.4% of them)
freespace: was free:
29995008 bytes 28.6 MiB, wrote:
41582592 bytes 39.7 MiB, delta:
11587584 bytes 11.1 MiB, wrote 38.6% more than predicted
freespace: trashing: was free:
91881472 bytes 87.6 MiB, need free:
58782816 bytes 56.1 MiB, files created: 248645, delete 89569 (36.0% of them)
freespace: was free:
22511616 bytes 21.5 MiB, wrote:
34705408 bytes 33.1 MiB, delta:
12193792 bytes 11.6 MiB, wrote 54.2% more than predicted
freespace: trashing: was free:
91774976 bytes 87.5 MiB, need free:
67180360 bytes 64.1 MiB, files created: 248580, delete 66616 (26.8% of them)
freespace: was free:
16908288 bytes 16.1 MiB, wrote:
26898432 bytes 25.7 MiB, delta:
9990144 bytes 9.5 MiB, wrote 59.1% more than predicted
freespace: trashing: was free:
92450816 bytes 88.2 MiB, need free:
75577904 bytes 72.1 MiB, files created: 248654, delete 45381 (18.3% of them)
freespace: was free:
10170368 bytes 9.7 MiB, wrote:
19111936 bytes 18.2 MiB, delta:
8941568 bytes 8.5 MiB, wrote 87.9% more than predicted
freespace: trashing: was free:
93282304 bytes 89.0 MiB, need free:
83975448 bytes 80.1 MiB, files created: 248513, delete 24794 (10.0% of them)
freespace: was free:
3911680 bytes 3.7 MiB, wrote:
7872512 bytes 7.5 MiB, delta:
3960832 bytes 3.8 MiB, wrote 101.3% more than predicted
freespace: Test 3 finished
freespace: finished successfully
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
}
/**
- * ubifs_budg_get_free_space - return amount of free space.
+ * ubifs_get_free_space - return amount of free space.
* @c: UBIFS file-system description object
*
- * This function returns amount of free space on the file-system.
+ * This function calculates amount of free space to report to user-space.
+ *
+ * Because UBIFS may introduce substantial overhead (the index, node headers,
+ * alighment, wastage at the end of eraseblocks, etc), it cannot report real
+ * amount of free flash space it has (well, because not all dirty space is
+ * reclamable, UBIFS does not actually know the real amount). If UBIFS did so,
+ * it would bread user expectetion about what free space is. Users seem to
+ * accustomed to assume that if the file-system reports N bytes of free space,
+ * they would be able to fit a file of N bytes to the FS. This almost works for
+ * traditional file-systems, because they have way less overhead than UBIFS.
+ * So, to keep users happy, UBIFS tries to take the overhead into account.
*/
-long long ubifs_budg_get_free_space(struct ubifs_info *c)
+long long ubifs_get_free_space(struct ubifs_info *c)
{
- int min_idx_lebs;
+ int min_idx_lebs, rsvd_idx_lebs, lebs;
long long available, outstanding, free;
spin_lock(&c->space_lock);
}
available = ubifs_calc_available(c, min_idx_lebs);
+
+ /*
+ * When reporting free space to user-space, UBIFS guarantees that it is
+ * possible to write a file of free space size. This means that for
+ * empty LEBs we may use more precise calculations than
+ * 'ubifs_calc_available()' is using. Namely, we know that in empty
+ * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm.
+ * Thus, amend the available space.
+ *
+ * Note, the calculations below are similar to what we have in
+ * 'do_budget_space()', so refer there for comments.
+ */
+ if (min_idx_lebs > c->lst.idx_lebs)
+ rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs;
+ else
+ rsvd_idx_lebs = 0;
+ lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt -
+ c->lst.taken_empty_lebs;
+ lebs -= rsvd_idx_lebs;
+ available += lebs * (c->dark_wm - c->leb_overhead);
spin_unlock(&c->space_lock);
if (available > outstanding)
struct ubifs_info *c = dentry->d_sb->s_fs_info;
unsigned long long free;
- free = ubifs_budg_get_free_space(c);
+ free = ubifs_get_free_space(c);
dbg_gen("free space %lld bytes (%lld blocks)",
free, free >> UBIFS_BLOCK_SHIFT);
* internally because it does not make much sense for UBIFS, but it is
* necessary to report something for the 'statfs()' call.
*
- * Subtract the LEB reserved for GC and the LEB which is reserved for
- * deletions.
+ * Subtract the LEB reserved for GC, the LEB which is reserved for
+ * deletions, and assume only one journal head is available.
*/
- tmp64 = c->main_lebs - 2;
- tmp64 *= (uint64_t)c->leb_size - c->dark_wm;
+ tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1;
+ tmp64 *= (uint64_t)c->leb_size - c->leb_overhead;
tmp64 = ubifs_reported_space(c, tmp64);
c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
struct ubifs_budget_req *req);
void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode,
struct ubifs_budget_req *req);
-long long ubifs_budg_get_free_space(struct ubifs_info *c);
+long long ubifs_get_free_space(struct ubifs_info *c);
int ubifs_calc_min_idx_lebs(struct ubifs_info *c);
void ubifs_convert_page_budget(struct ubifs_info *c);
long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free);