Re: [RFC v3 05/15] mm, swap: add xswap cluster grow via VM_SPARSE vmalloc

From: Baoquan He

Date: Sun Aug 16 2026 - 20:46:56 EST


On 08/15/26 at 01:09am, Klara Modin wrote:
> Hi,
>
> On 2026-08-13 18:48:44 +0800, Baoquan He wrote:
> > Implement dynamic cluster_info array growth for xswap devices using a
> > VM_SPARSE vmalloc area:
> >
......snip....
> > @@ -3562,6 +3757,64 @@ static int setup_swap_clusters_info(struct swap_info_struct *si,
> > int err = -ENOMEM;
> > unsigned long i;
> >
> > +#ifdef CONFIG_XSWAP
> > + if (si->flags & SWP_XSWAP) {
> > + unsigned long size = PAGE_ALIGN(nr_clusters * sizeof(*cluster_info));
> > + struct vm_struct *vm;
> > +
> > + vm = get_vm_area(size, VM_SPARSE);
> > + if (!vm)
> > + goto err;
> > +
> > + cluster_info = vm->addr;
> > + si->cluster_vm = vm;
> > + si->nr_clusters = nr_clusters;
> > + si->cluster_info = cluster_info;
>
> Should probably initialise the mutex here instead since
> xswap_map_clusters() uses it?

Many thanks for reviewing, and you are absolutely right. A real bug is
caught, I will wrap up the fix in the next version as you suggested.

Thanks
Baoquan
>
> > +
> > + /* Map the initial chunk (at least cluster 0) */
> > + if (xswap_map_clusters(si, 0, min_t(unsigned long,
> > + XSWAP_GROW_CLUSTERS, nr_clusters)))
> > + goto err_free_vm;
>
> > +
> > + /* xswap: only cluster 0 slot 0 is bad */
> > + err = swap_cluster_setup_bad_slot(si, cluster_info, 0, false);
> > + if (err)
> > + goto err_unmap;
> > +
> > + INIT_LIST_HEAD(&si->free_clusters);
> > + INIT_LIST_HEAD(&si->full_clusters);
> > + INIT_LIST_HEAD(&si->discard_clusters);
> > + for (i = 0; i < SWAP_NR_ORDERS; i++) {
> > + INIT_LIST_HEAD(&si->nonfull_clusters[i]);
> > + INIT_LIST_HEAD(&si->frag_clusters[i]);
> > + }
> > +
> > + /* Mark mapped clusters: cluster 0 has 1 bad slot, rest free */
> > + for (i = 0; i < si->nr_clusters_mapped; i++) {
> > + struct swap_cluster_info *ci = &cluster_info[i];
> > +
> > + if (i == 0) {
> > + ci->flags = CLUSTER_FLAG_NONFULL;
> > + list_add_tail(&ci->list, &si->nonfull_clusters[0]);
> > + } else {
> > + ci->flags = CLUSTER_FLAG_FREE;
> > + list_add_tail(&ci->list, &si->free_clusters);
> > + }
> > + }
> > +
> > + mutex_init(&si->xswap_lock);
> > + return 0;
> > +
> > +err_unmap:
> > + xswap_unmap_clusters(si, 0, si->nr_clusters_mapped);
> > +err_free_vm:
> > + free_vm_area(si->cluster_vm);
> > + si->cluster_vm = NULL;
> > + si->cluster_info = NULL;
> > + return err;
> > + }
> > +#endif /* CONFIG_XSWAP */
> > +
> > cluster_info = kvzalloc_objs(*cluster_info, nr_clusters);
> > if (!cluster_info)
> > goto err;
> > --
> > 2.54.0
> >
>
> Regards,
> Klara Modin