> 2022年6月6日 16:45,mingzhe.zou@xxxxxxxxxxxx 写道: > > From: mingzhe <mingzhe.zou@xxxxxxxxxxxx> > > [snipped] > We want to use those invalid_uuid slots carefully. Because, the bkey of the inode > may still exist in the btree. So, we need to check the btree before reuse it. > > Signed-off-by: mingzhe <mingzhe.zou@xxxxxxxxxxxx> > --- > drivers/md/bcache/btree.c | 35 +++++++++++++++++++++++++++++++++++ > drivers/md/bcache/btree.h | 1 + > drivers/md/bcache/super.c | 15 ++++++++++++++- > 3 files changed, 50 insertions(+), 1 deletion(-) > > diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c > index e136d6edc1ed..a5d54af73111 100644 > --- a/drivers/md/bcache/btree.c > +++ b/drivers/md/bcache/btree.c > @@ -2755,6 +2755,41 @@ struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c, > return ret; > } > > +static bool check_pred(struct keybuf *buf, struct bkey *k) > +{ > + return true; > +} > + > +bool bch_btree_can_inode_reuse(struct cache_set *c, size_t inode) > +{ > + bool ret = true; > + struct keybuf_key *k; > + struct bkey end_key = KEY(inode, MAX_KEY_OFFSET, 0); > + struct keybuf *keys = kzalloc(sizeof(struct keybuf), GFP_KERNEL); > + > + if (!keys) { > + ret = false; > + goto out; > + } > + > + bch_keybuf_init(keys); > + keys->last_scanned = KEY(inode, 0, 0); > + > + while (ret) { > + k = bch_keybuf_next_rescan(c, keys, &end_key, check_pred); > + if (!k) This is a single thread iteration, for a large filled cache device it can be very slow. I observed 40+ minutes during my testing. Coly Li > + break; > + > + if (KEY_INODE(&k->key) == inode) > + ret = false; > + bch_keybuf_del(keys, k); > + } > + > + kfree(keys); > +out: > + return ret; > +} > + > void bch_keybuf_init(struct keybuf *buf) > { > buf->last_scanned = MAX_KEY; > diff --git a/drivers/md/bcache/btree.h b/drivers/md/bcache/btree.h > index 1b5fdbc0d83e..c3e6094adb62 100644 > --- a/drivers/md/bcache/btree.h > +++ b/drivers/md/bcache/btree.h > @@ -413,4 +413,5 @@ struct keybuf_key *bch_keybuf_next_rescan(struct cache_set *c, > struct bkey *end, > keybuf_pred_fn *pred); > void bch_update_bucket_in_use(struct cache_set *c, struct gc_stat *stats); > +bool bch_btree_can_inode_reuse(struct cache_set *c, size_t inode); > #endif > diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c > index 3563d15dbaf2..31f7aa347561 100644 > --- a/drivers/md/bcache/super.c > +++ b/drivers/md/bcache/super.c > @@ -544,11 +544,24 @@ static struct uuid_entry *uuid_find(struct cache_set *c, const char *uuid) > return NULL; > } > > +static struct uuid_entry *uuid_find_reuse(struct cache_set *c) > +{ > + struct uuid_entry *u; > + > + for (u = c->uuids; u < c->uuids + c->nr_uuids; u++) > + if (!memcmp(u->uuid, invalid_uuid, 16) && > + bch_btree_can_inode_reuse(c, u - c->uuids)) > + return u; > + > + return NULL; > +} > + > static struct uuid_entry *uuid_find_empty(struct cache_set *c) > { > static const char zero_uuid[16] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; > + struct uuid_entry *u = uuid_find(c, zero_uuid); > > - return uuid_find(c, zero_uuid); > + return u ? u : uuid_find_reuse(c); > } > > /* > -- > 2.17.1 >