Started prototyping best-effort fsinfo.known_free/inuse fields
The idea here was that we could provide best-effort known in-use/free
block info (and eventually pre-erased and bad block info) as a cheaper
alternative to lfs3_fs_usage. It's probably still not what users expect
from lfs3_fs_stat, but may be useful as debug/diagnostic info:
- fsinfo.known_free - Number of known free blocks
- fsinfo.known_inuse - Number of known in-use blocks
- fsinfo.known_preerased* - Number of pre-erased blocks
- fsinfo.known_bad* - Number of bad blocks
- fsinfo.block_count-(all of the above) - Number of unknown blocks
But while known_free/known_inuse is easy enough to find from the
lookahead buffer, it's surprisingly tricky from the gbmap. The best
option I can think of requires scanning the gbmap in O(d log_b d) either
(1) during mount, (2) during mkconsistent, or (3) during lookahead
scans. And that much extra work for debug/diagnostic info seems like a
poor tradeoff.
Note, though, that after scanning once, in theory the info would be
~free to maintain during gbmap rebuilds.
Will revert.
Code changes:
code stack ctx
before: 35160 2136 660
after: 35220 (+0.2%) 2136 (+0.0%) 660 (+0.0%)
code stack ctx
gbmap before: 38020 2152 772
gbmap after: 38116 (+0.3%) 2152 (+0.0%) 776 (+0.5%)
This commit is contained in:
@@ -10459,6 +10459,8 @@ eot:;
|
||||
static void lfs3_gbmap_init(lfs3_gbmap_t *gbmap) {
|
||||
gbmap->window = 0;
|
||||
gbmap->known = 0;
|
||||
// we lazily populate this during lookahead scans
|
||||
gbmap->known_free = -1;
|
||||
lfs3_btree_init(&gbmap->b);
|
||||
lfs3_btree_init(&gbmap->b_p);
|
||||
}
|
||||
@@ -16069,6 +16071,7 @@ failed:;
|
||||
|
||||
/// Other filesystem things ///
|
||||
|
||||
// note lfs3_fs_stat should never go to disk
|
||||
int lfs3_fs_stat(lfs3_t *lfs3, struct lfs3_fsinfo *fsinfo) {
|
||||
// return various filesystem flags
|
||||
fsinfo->flags = lfs3->flags & (
|
||||
@@ -16099,6 +16102,34 @@ int lfs3_fs_stat(lfs3_t *lfs3, struct lfs3_fsinfo *fsinfo) {
|
||||
fsinfo->name_limit = lfs3->name_limit;
|
||||
fsinfo->file_limit = lfs3->file_limit;
|
||||
|
||||
// return best effort knowledge of block usage
|
||||
|
||||
// if we have a gbmap, we choose whichever allocator has more
|
||||
// information, otherwise we fall back to the lookahead buffer
|
||||
if (LFS3_IFDEF_GBMAP(
|
||||
lfs3_f_isgbmap(lfs3->flags)
|
||||
// known_free=-1 indicates we don't know the free/inuse
|
||||
// breakdown yet
|
||||
&& lfs3->gbmap.known_free != -1
|
||||
&& lfs3->gbmap.known >= lfs3->lookahead.known,
|
||||
false)) {
|
||||
#ifdef LFS3_GBMAP
|
||||
fsinfo->known_free = lfs3->gbmap.known_free;
|
||||
fsinfo->known_inuse = lfs3->gbmap.known - lfs3->gbmap.known_free;
|
||||
#endif
|
||||
|
||||
} else {
|
||||
lfs3_block_t free = 0;
|
||||
for (lfs3_size_t i = 0; i < lfs3->lookahead.known; i++) {
|
||||
if (!(lfs3->lookahead.buffer[(lfs3->lookahead.off+i) / 8]
|
||||
& (1 << ((lfs3->lookahead.off+i) % 8)))) {
|
||||
free += 1;
|
||||
}
|
||||
}
|
||||
fsinfo->known_free = free;
|
||||
fsinfo->known_inuse = lfs3->lookahead.known - free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -687,6 +687,16 @@ struct lfs3_fsinfo {
|
||||
|
||||
// Upper limit on the size of files in bytes.
|
||||
lfs3_off_t file_limit;
|
||||
|
||||
// Number of known free blocks
|
||||
//
|
||||
// Note this is limited by lookahead/gbmap
|
||||
lfs3_block_t known_free;
|
||||
|
||||
// Number of known in-use blocks
|
||||
//
|
||||
// Note this is limited by lookahead/gbmap
|
||||
lfs3_block_t known_inuse;
|
||||
};
|
||||
|
||||
// Traversal info structure
|
||||
@@ -1221,6 +1231,7 @@ typedef struct lfs3_grm {
|
||||
typedef struct lfs3_gbmap {
|
||||
lfs3_block_t window;
|
||||
lfs3_block_t known;
|
||||
lfs3_sblock_t known_free;
|
||||
lfs3_btree_t b;
|
||||
lfs3_btree_t b_p;
|
||||
} lfs3_gbmap_t;
|
||||
@@ -1276,7 +1287,7 @@ typedef struct lfs3 {
|
||||
struct lfs3_lookahead {
|
||||
lfs3_block_t window;
|
||||
lfs3_block_t off;
|
||||
lfs3_block_t known;
|
||||
lfs3_size_t known;
|
||||
lfs3_block_t ckpoint;
|
||||
uint8_t *buffer;
|
||||
} lookahead;
|
||||
|
||||
Reference in New Issue
Block a user