diff options
| -rw-r--r-- | fs/ubifs/budget.c | 38 | ||||
| -rw-r--r-- | fs/ubifs/super.c | 10 | ||||
| -rw-r--r-- | fs/ubifs/ubifs.h | 2 |
3 files changed, 40 insertions, 10 deletions
diff --git a/fs/ubifs/budget.c b/fs/ubifs/budget.c index 7851480a6cea..101d278c591d 100644 --- a/fs/ubifs/budget.c +++ b/fs/ubifs/budget.c | |||
| @@ -747,14 +747,24 @@ long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free) | |||
| 747 | } | 747 | } |
| 748 | 748 | ||
| 749 | /** | 749 | /** |
| 750 | * ubifs_budg_get_free_space - return amount of free space. | 750 | * ubifs_get_free_space - return amount of free space. |
| 751 | * @c: UBIFS file-system description object | 751 | * @c: UBIFS file-system description object |
| 752 | * | 752 | * |
| 753 | * This function returns amount of free space on the file-system. | 753 | * This function calculates amount of free space to report to user-space. |
| 754 | * | ||
| 755 | * Because UBIFS may introduce substantial overhead (the index, node headers, | ||
| 756 | * alighment, wastage at the end of eraseblocks, etc), it cannot report real | ||
| 757 | * amount of free flash space it has (well, because not all dirty space is | ||
| 758 | * reclamable, UBIFS does not actually know the real amount). If UBIFS did so, | ||
| 759 | * it would bread user expectetion about what free space is. Users seem to | ||
| 760 | * accustomed to assume that if the file-system reports N bytes of free space, | ||
| 761 | * they would be able to fit a file of N bytes to the FS. This almost works for | ||
| 762 | * traditional file-systems, because they have way less overhead than UBIFS. | ||
| 763 | * So, to keep users happy, UBIFS tries to take the overhead into account. | ||
| 754 | */ | 764 | */ |
| 755 | long long ubifs_budg_get_free_space(struct ubifs_info *c) | 765 | long long ubifs_get_free_space(struct ubifs_info *c) |
| 756 | { | 766 | { |
| 757 | int min_idx_lebs; | 767 | int min_idx_lebs, rsvd_idx_lebs, lebs; |
| 758 | long long available, outstanding, free; | 768 | long long available, outstanding, free; |
| 759 | 769 | ||
| 760 | spin_lock(&c->space_lock); | 770 | spin_lock(&c->space_lock); |
| @@ -771,6 +781,26 @@ long long ubifs_budg_get_free_space(struct ubifs_info *c) | |||
| 771 | } | 781 | } |
| 772 | 782 | ||
| 773 | available = ubifs_calc_available(c, min_idx_lebs); | 783 | available = ubifs_calc_available(c, min_idx_lebs); |
| 784 | |||
| 785 | /* | ||
| 786 | * When reporting free space to user-space, UBIFS guarantees that it is | ||
| 787 | * possible to write a file of free space size. This means that for | ||
| 788 | * empty LEBs we may use more precise calculations than | ||
| 789 | * 'ubifs_calc_available()' is using. Namely, we know that in empty | ||
| 790 | * LEBs we would waste only @c->leb_overhead bytes, not @c->dark_wm. | ||
| 791 | * Thus, amend the available space. | ||
| 792 | * | ||
| 793 | * Note, the calculations below are similar to what we have in | ||
| 794 | * 'do_budget_space()', so refer there for comments. | ||
| 795 | */ | ||
| 796 | if (min_idx_lebs > c->lst.idx_lebs) | ||
| 797 | rsvd_idx_lebs = min_idx_lebs - c->lst.idx_lebs; | ||
| 798 | else | ||
| 799 | rsvd_idx_lebs = 0; | ||
| 800 | lebs = c->lst.empty_lebs + c->freeable_cnt + c->idx_gc_cnt - | ||
| 801 | c->lst.taken_empty_lebs; | ||
| 802 | lebs -= rsvd_idx_lebs; | ||
| 803 | available += lebs * (c->dark_wm - c->leb_overhead); | ||
| 774 | spin_unlock(&c->space_lock); | 804 | spin_unlock(&c->space_lock); |
| 775 | 805 | ||
| 776 | if (available > outstanding) | 806 | if (available > outstanding) |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index be23fd3cfd84..1207bd51eadd 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -371,7 +371,7 @@ static int ubifs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 371 | struct ubifs_info *c = dentry->d_sb->s_fs_info; | 371 | struct ubifs_info *c = dentry->d_sb->s_fs_info; |
| 372 | unsigned long long free; | 372 | unsigned long long free; |
| 373 | 373 | ||
| 374 | free = ubifs_budg_get_free_space(c); | 374 | free = ubifs_get_free_space(c); |
| 375 | dbg_gen("free space %lld bytes (%lld blocks)", | 375 | dbg_gen("free space %lld bytes (%lld blocks)", |
| 376 | free, free >> UBIFS_BLOCK_SHIFT); | 376 | free, free >> UBIFS_BLOCK_SHIFT); |
| 377 | 377 | ||
| @@ -653,11 +653,11 @@ static int init_constants_late(struct ubifs_info *c) | |||
| 653 | * internally because it does not make much sense for UBIFS, but it is | 653 | * internally because it does not make much sense for UBIFS, but it is |
| 654 | * necessary to report something for the 'statfs()' call. | 654 | * necessary to report something for the 'statfs()' call. |
| 655 | * | 655 | * |
| 656 | * Subtract the LEB reserved for GC and the LEB which is reserved for | 656 | * Subtract the LEB reserved for GC, the LEB which is reserved for |
| 657 | * deletions. | 657 | * deletions, and assume only one journal head is available. |
| 658 | */ | 658 | */ |
| 659 | tmp64 = c->main_lebs - 2; | 659 | tmp64 = c->main_lebs - 2 - c->jhead_cnt + 1; |
| 660 | tmp64 *= (uint64_t)c->leb_size - c->dark_wm; | 660 | tmp64 *= (uint64_t)c->leb_size - c->leb_overhead; |
| 661 | tmp64 = ubifs_reported_space(c, tmp64); | 661 | tmp64 = ubifs_reported_space(c, tmp64); |
| 662 | c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; | 662 | c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT; |
| 663 | 663 | ||
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 57e58541de28..17c620b93eec 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h | |||
| @@ -1443,7 +1443,7 @@ void ubifs_release_ino_dirty(struct ubifs_info *c, struct inode *inode, | |||
| 1443 | struct ubifs_budget_req *req); | 1443 | struct ubifs_budget_req *req); |
| 1444 | void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, | 1444 | void ubifs_cancel_ino_op(struct ubifs_info *c, struct inode *inode, |
| 1445 | struct ubifs_budget_req *req); | 1445 | struct ubifs_budget_req *req); |
| 1446 | long long ubifs_budg_get_free_space(struct ubifs_info *c); | 1446 | long long ubifs_get_free_space(struct ubifs_info *c); |
| 1447 | int ubifs_calc_min_idx_lebs(struct ubifs_info *c); | 1447 | int ubifs_calc_min_idx_lebs(struct ubifs_info *c); |
| 1448 | void ubifs_convert_page_budget(struct ubifs_info *c); | 1448 | void ubifs_convert_page_budget(struct ubifs_info *c); |
| 1449 | long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); | 1449 | long long ubifs_reported_space(const struct ubifs_info *c, uint64_t free); |
