Re: [PATCH 11/12] device-dax: Add dis-contiguous resource support

From: Joao Martins
Date: Mon Apr 06 2020 - 06:46:10 EST


On 3/23/20 11:55 PM, Dan Williams wrote:

[...]

> static ssize_t dev_dax_resize(struct dax_region *dax_region,
> struct dev_dax *dev_dax, resource_size_t size)
> {
> resource_size_t avail = dax_region_avail_size(dax_region), to_alloc;
> - resource_size_t dev_size = range_len(&dev_dax->range);
> + resource_size_t dev_size = dev_dax_size(dev_dax);
> struct resource *region_res = &dax_region->res;
> struct device *dev = &dev_dax->dev;
> - const char *name = dev_name(dev);
> struct resource *res, *first;
> + resource_size_t alloc = 0;
> + int rc;
>
> if (dev->driver)
> return -EBUSY;
> @@ -684,38 +766,47 @@ static ssize_t dev_dax_resize(struct dax_region *dax_region,
> * allocating a new resource.
> */
> first = region_res->child;
> - if (!first)
> - return __alloc_dev_dax_range(dev_dax, dax_region->res.start,
> - to_alloc);
> - for (res = first; to_alloc && res; res = res->sibling) {
> +retry:
> + rc = -ENOSPC;
> + for (res = first; res; res = res->sibling) {
> struct resource *next = res->sibling;
> - resource_size_t free;
>
> /* space at the beginning of the region */
> - free = 0;
> - if (res == first && res->start > dax_region->res.start)
> - free = res->start - dax_region->res.start;
> - if (free >= to_alloc && dev_size == 0)
> - return __alloc_dev_dax_range(dev_dax,
> - dax_region->res.start, to_alloc);
> -
> - free = 0;
> + if (res == first && res->start > dax_region->res.start) {
> + alloc = min(res->start - dax_region->res.start,
> + to_alloc);
> + rc = __alloc_dev_dax_range(dev_dax,
> + dax_region->res.start, alloc);

You might be missing:

first = region_res->child;

(...) right after returning from __alloc_dev_dax_range(). Alternatively, perhaps
even moving the 'retry' label to right before the @first initialization.

In the case that you pick space from the beginning, the child resource of the
dax region will point to first occupied region, and that changes after you pick
this space. So, IIUC, you want to adjust where you start searching free space
otherwise you end up wrongly picking that same space twice.

If it helps, the bug can be reproduced in this unit test below, see
daxctl_test3() test:

https://lore.kernel.org/linux-nvdimm/20200403205900.18035-11-joao.m.martins@xxxxxxxxxx/

> + break;
> + }
> +

[...]