On 4/10/25 5:15 AM, Benjamin Marzinski wrote:
>>> @@ -1873,11 +1898,17 @@ int dm_table_set_restrictions(struct dm_table *t, 
>>> struct request_queue *q,
>>>             limits->features &= ~BLK_FEAT_DAX;
>>>  
>>>     /* For a zoned table, setup the zone related queue attributes. */
>>> -   if (IS_ENABLED(CONFIG_BLK_DEV_ZONED) &&
>>> -       (limits->features & BLK_FEAT_ZONED)) {
>>> -           r = dm_set_zones_restrictions(t, q, limits);
>>> -           if (r)
>>> -                   return r;
>>> +   if (IS_ENABLED(CONFIG_BLK_DEV_ZONED)) {
>>> +           if (limits->features & BLK_FEAT_ZONED) {
>>> +                   r = dm_set_zones_restrictions(t, q, limits);
>>> +                   if (r)
>>> +                           return r;
>>> +           } else if (dm_has_zone_plugs(t->md)) {
>>> +                   DMWARN("%s: device has zone write plug resources. "
>>> +                          "Cannot switch to non-zoned table.",
>>> +                          dm_device_name(t->md));
>>> +                   return -EINVAL;
>>> +           }
>>
>> I am confused with this one. We can only have zone write plugs if the device 
>> is
>> zoned. So it seems that the check for "if (dm_has_zone_plugs(t->md)" should
>> really be inside dm_set_zones_restrictions(). Or is this trying to detect a
>> table change that would switch the device from zoned to non-zoned ? If that 
>> is
>> the case, regardless of the zone write plug initialization state, we should
>> never allow such change.

And I was wrong on this one: using dm-linear to map only conventional zones of
an SMR HDD, the DM device will *not* be zoned but the underlying device is. So
this check is fine since the dm device will not have wplugs in that case.

> I don't think that, for instance, allowing a linear device stacked on
> top of a zoned device to get remapped to stack on top of a non-zoned
> device runs much more risk than allowing a linear device to get remapped
> in any other case? This is currently allowed, and I don't believe anyone
> has complained about it. I would rather assume that the user knows what
> they are doing, instead of disallowing things that aren't obviously
> wrong, and won't cause system problems if they are (aside from the
> problems that naturally result from putting the wrong device in your
> table line). But if Mikulas and Mike think it would be better to
> disallow this, then I'm fine with that.

OK. Let's leave things as you have now.

>>> +   if (get_capacity(disk) && dm_has_zone_plugs(t->md)) {
>>> +           if (q->limits.chunk_sectors != lim->chunk_sectors) {
>>> +                   DMWARN("%s: device has zone write plug resources. "
>>> +                          "Cannot change zone size",
>>> +                          disk->disk_name);
>>> +                   return -EINVAL;
>>> +           }
>>> +           if (lim->max_hw_zone_append_sectors != 0 &&
>>> +               !dm_table_is_wildcard(t)) {
>>> +                   DMWARN("%s: device has zone write plug resources. "
>>> +                          "New table must emulate zone append",
>>> +                          disk->disk_name);
>>> +                   return -EINVAL;
>>> +           }
>>> +   }
>>
>> I have some concerns about this: what if the new table has the same capacity
>> and the same zone size but the types of zones changed ? We are not checking
>> this here and we cannot actually check that without doing a report zones. So 
>> I
>> really think we should just use the big hammer here and simply only allow the
>> wildcard target and no other change.
> 
> I don't see how this could lead to accessing invalid memory, which was
> my big concern, with these patches. The worst that could happen in an IO
> error, AFAICS. Disallowing all table loads except for the error target
> would keep people from being able from things like changing options on
> the dm-crypt target. Again, that is just my preference, and I'll defer
> to Mike and Mikulas on how this should be handled.

Yeah, but these IO errors that can happen would be hard to debug/understand...
But as you said, given that this has never been checked/prevented before and
that no one complained, let's keep this as is. Your example for dm-crypt is
indeed a valid case.

>>>     /*
>>>      * Warn once (when the capacity is not yet set) if the mapped device is
>>>      * partially using zone resources of the target devices as that leads to
>>> diff --git a/drivers/md/dm.c b/drivers/md/dm.c
>>> index 292414da871d..240f6dab8dda 100644
>>> --- a/drivers/md/dm.c
>>> +++ b/drivers/md/dm.c
>>> @@ -2429,6 +2429,12 @@ static struct dm_table *__bind(struct mapped_device 
>>> *md, struct dm_table *t,
>>>     size = dm_table_get_size(t);
>>>  
>>>     old_size = dm_get_size(md);
>>> +
>>> +   if (!dm_table_supports_size_change(t, old_size, size)) {
>>> +           old_map = ERR_PTR(-EINVAL);
>>> +           goto out;
>>> +   }
>>
>> And I guess we could probably move the "wildcard-only is allowed" change 
>> check
>> here as that would further simplify the revalidation code. No ?
> 
> If we are disallowing any zoned device to reload its table to something
> other than an error target, then yes. It can go here. If we only care
> about zoned devices that emulate zoned append, when we need to wait till
> dm_set_zones_restrictions() where we determine that. Since we already
> need to handle failures in dm_table_set_restrictions(), moving it
> doesn't simplify the code much.

OK. So with the commit message typos fixed, feel free to add:

Reviewed-by: Damien Le Moal <dlem...@kernel.org>


-- 
Damien Le Moal
Western Digital Research

Reply via email to