> -----Original Message----- > From: Coly Li <colyli@xxxxxxx> > Sent: Wednesday, December 16, 2020 6:50 PM > To: Ren, Qiaowei <qiaowei.ren@xxxxxxxxx> > Cc: linux-bcache@xxxxxxxxxxxxxxx; Ma, Jianpeng <jianpeng.ma@xxxxxxxxx> > Subject: Re: [RFC PATCH 7/8] bcache: persist owner info when alloc/free > pages. > > On 12/3/20 6:53 PM, Qiaowei Ren wrote: > > This patch implement persist owner info on nvdimm device when > > alloc/free pages. > > > > Signed-off-by: Jianpeng Ma <jianpeng.ma@xxxxxxxxx> > > Signed-off-by: Qiaowei Ren <qiaowei.ren@xxxxxxxxx> > > Reviwed-by: Coly Li <colyli@xxxxxxx> > > > This patch can be improved, but the current shape is OK to me as a start. > Yes, in fact we need two function: one which sync all owner list and one only sync one owner_list by owner_uuid. Thanks! Jianpeng. > Thanks. > > Coly Li > > > --- > > drivers/md/bcache/nvm-pages.c | 86 > > +++++++++++++++++++++++++++++++++++ > > 1 file changed, 86 insertions(+) > > > > diff --git a/drivers/md/bcache/nvm-pages.c > > b/drivers/md/bcache/nvm-pages.c index e8765b0b3398..ba1ff0582b20 > > 100644 > > --- a/drivers/md/bcache/nvm-pages.c > > +++ b/drivers/md/bcache/nvm-pages.c > > @@ -197,6 +197,17 @@ static struct nvm_namespace > *find_nvm_by_addr(void *addr, int order) > > return NULL; > > } > > > > +static void init_pgalloc_recs(struct nvm_pgalloc_recs *recs, const > > +char *owner_uuid) { > > + memset(recs, 0, sizeof(struct nvm_pgalloc_recs)); > > + memcpy(recs->owner_uuid, owner_uuid, 16); } > > + > > +static pgoff_t vaddr_to_nvm_pgoff(struct nvm_namespace *ns, void > > +*kaddr) { > > + return (kaddr - ns->kaddr - ns->pages_offset) / PAGE_SIZE; } > > + > > static int remove_extent(struct nvm_alloced_recs *alloced_recs, void > > *addr, int order) { > > struct list_head *list = alloced_recs->extent_head.next; @@ -275,6 > > +286,77 @@ static void __free_space(struct nvm_namespace *ns, void > *addr, int order) > > ns->free += add_pages; > > } > > > > +#define RECS_LEN (sizeof(struct nvm_pgalloc_recs)) > > + > > +static void write_owner_info(void) > > +{ > > + struct owner_list *owner_list; > > + struct nvm_pages_owner_head *owner_head; > > + struct nvm_pgalloc_recs *recs; > > + struct extent *extent; > > + struct nvm_namespace *ns = only_set->nss[0]; > > + struct owner_list_head *owner_list_head; > > + bool update_owner = false; > > + u64 recs_pos = NVM_PAGES_SYS_RECS_HEAD_OFFSET; > > + struct list_head *list; > > + int i, j; > > + > > + owner_list_head = kzalloc(sizeof(struct owner_list_head), > GFP_KERNEL); > > + recs = kmalloc(RECS_LEN, GFP_KERNEL); > > + > > + // in-memory owner maybe not contain alloced-pages. > > + for (i = 0; i < only_set->owner_list_size; i++) { > > + owner_head = &owner_list_head->heads[owner_list_head- > >size]; > > + owner_list = only_set->owner_lists[i]; > > + > > + for (j = 0; j < only_set->total_namespaces_nr; j++) { > > + struct nvm_alloced_recs *extents = owner_list- > >alloced_recs[j]; > > + > > + if (!extents || !extents->size) > > + continue; > > + > > + init_pgalloc_recs(recs, owner_list->owner_uuid); > > + > > + BUG_ON(recs_pos >= NVM_PAGES_OFFSET); > > + owner_head->recs[j] = (struct nvm_pgalloc_recs > *)recs_pos; > > + > > + for (list = extents->extent_head.next; > > + list != &extents->extent_head; > > + list = list->next) { > > + extent = container_of(list, struct extent, list); > > + > > + if (recs->size == MAX_RECORD) { > > + BUG_ON(recs_pos >= NVM_PAGES_OFFSET); > > + recs->next = > > + (struct nvm_pgalloc_recs *)(recs_pos + > RECS_LEN); > > + memcpy_flushcache(ns->kaddr + recs_pos, > recs, RECS_LEN); > > + init_pgalloc_recs(recs, owner_list- > >owner_uuid); > > + recs_pos += RECS_LEN; > > + } > > + > > + recs->recs[recs->size].pgoff = > > + vaddr_to_nvm_pgoff(only_set->nss[j], extent- > >kaddr); > > + recs->recs[recs->size].nr = extent->nr; > > + recs->size++; > > + } > > + > > + update_owner = true; > > + memcpy_flushcache(ns->kaddr + recs_pos, recs, > RECS_LEN); > > + recs_pos += sizeof(struct nvm_pgalloc_recs); > > + } > > + > > + if (update_owner) { > > + memcpy(owner_head->uuid, owner_list->owner_uuid, > 16); > > + owner_list_head->size++; > > + update_owner = false; > > + } > > + } > > + > > + memcpy_flushcache(ns->kaddr + > NVM_PAGES_OWNER_LIST_HEAD_OFFSET, > > + (void *)owner_list_head, sizeof(struct > owner_list_head)); > > + kfree(owner_list_head); > > +} > > + > > void nvm_free_pages(void *addr, int order, const char *owner_uuid) { > > struct nvm_namespace *ns; > > @@ -309,6 +391,7 @@ void nvm_free_pages(void *addr, int order, const > char *owner_uuid) > > } > > > > __free_space(ns, addr, order); > > + write_owner_info(); > > > > unlock: > > mutex_unlock(&only_set->lock); > > @@ -368,7 +451,10 @@ void *nvm_alloc_pages(int order, const char > *owner_uuid) > > } > > } > > > > + if (kaddr) > > + write_owner_info(); > > mutex_unlock(&only_set->lock); > > + > > return kaddr; > > } > > EXPORT_SYMBOL_GPL(nvm_alloc_pages); > >