diff options
Diffstat (limited to 'fs/ubifs')
-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); |