Re: [PATCH v5 14/17] s390/dasd: Detect ESE volumes from the on-disk format label
[email protected] Fri, 31 Jul 2026 16:43:36 +0000
| Newsgroups | org.kernel.vger.linux-s390 |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider: New issues: - [High] Unconditional dereference of `device->private` in `dasd_eckd_is_ese()` causes a kernel panic when accessed via the `full_track_bias` sysfs attribute on an initializing or offline device. - [High] Valid on-disk ESE label cache is incorrectly invalidated on early format failures, breaking thin-provisioning state. - [Medium] Concurrent execution of dasdfmt and sysfs reads leads to data races and torn reads on the 512-byte `ese_label` structure. - [Medium] The `ese_label_valid` cache is not invalidated when track 0 is formatted with LDL (intensity 0x00) or invalidate-track, leaving stale in-memory state. Pre-existing issues: - [High] The `dasd_release_space()` ioctl helper triggers a NULL pointer dereference when called on a device whose discipline does not implement the `is_ese()` callback (e.g., FBA devices). -- --- Patch [14]: [PATCH v5 14/17] s390/dasd: Detect ESE volumes from the on-disk format label --- commit 6689b09c2730c7fa8fae2e18e3bbf4f3671425e2 Author: Stefan Haberland <[email protected]> s390/dasd: Detect ESE volumes from the on-disk format label This commit reads the format label from track 0 record 4 at device bring-up and caches it to determine if a volume is ESE. It also updates sysfs attributes and format handling to reflect the cached label state, ensuring volumes copied off ESE storage are still handled as thin. > diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c > --- a/drivers/s390/block/dasd_eckd.c > +++ b/drivers/s390/block/dasd_eckd.c > @@ -1686,6 +1687,49 @@ static int dasd_eckd_is_ese(struct dasd_device *device) > return private->vsq.vol_info.ese; > } > > +/* > + * Whether the volume is to be handled as ESE (thin). This reflects the state > + * of the data, not the hardware: a volume copied off ESE storage onto other > + * hardware still needs ESE handling. The on-disk format label is authoritative > + * when present; without it (e.g. a volume formatted by an older driver) fall > + * back to the hardware ESE field. > + * > + * Only the F_ESE flag gates this. An ESE volume is thin regardless of whether > + * it was quick- or full-formatted (tracks are allocated on write, and discard > + * re-thins a full one). > + */ > +static int dasd_eckd_is_ese(struct dasd_device *device) > +{ > + struct dasd_eckd_private *private = device->private; > + > + if (private->ese_label_valid) [Severity: High] Can this cause a NULL pointer dereference if device->private is not yet allocated? The full_track_bias_store() sysfs function can indirectly call dasd_eckd_is_ese() during the initialization window before private is allocated, or if allocation fails: full_track_bias_store() dasd_ft_bias_apply() dasd_eckd_is_ese() private->ese_label_valid > + return !!(private->ese_label.flags & DASD_ESE_LABEL_F_ESE); > + > + return dasd_eckd_ese_capable(device); > +} [ ... ] > @@ -2730,7 +2843,12 @@ static void dasd_eckd_fill_format_label(struct dasd_device *device, void *data, > label->format_tod = get_tod_clock(); > strscpy(label->kernel_version, init_utsname()->release, > sizeof(label->kernel_version)); > + > + /* > + * Populate the cache directly from the bytes just computed instead of > + * synchronously reading them back from disk after the write lands. > + */ > + private->ese_label = *label; > + private->ese_label_valid = true; > } [Severity: Medium] Does this introduce a data race that could lead to torn reads? Sysfs readers accessing on_demand_formatting or full_track_bias can call dasd_eckd_is_ese(), which reads private->ese_label.flags locklessly. If a format is concurrently updating this 512-byte structure here, could a reader observe ese_label_valid == true but see stale or partially written flags? [ ... ] > @@ -3224,23 +3349,35 @@ static int dasd_eckd_format_device(struct dasd_device *base, > struct dasd_eckd_private *private = base->private; > int rc; > > rc = dasd_eckd_format_process_data(base, fdata, enable_pav, 0, NULL, > 0, NULL); > + if (fdata->start_unit != 0) > + return rc; > + > + if (rc) { > + /* > + * The format failed, so the label cached speculatively during > + * CCW build may not match the disk; drop it so is_ese() falls > + * back to the hardware field until the next successful format > + * or bring-up. > + */ > + private->ese_label_valid = false; > + return rc; > + } [Severity: High] Does this incorrectly drop the valid in-memory label state on early format failures? If dasd_eckd_format_process_data() fails early due to sanity checks (like invalid parameters where stop_unit is out of bounds) before any I/O is issued, rc will be non-zero and the cache is cleared. Would this cause subsequent writes to unallocated tracks to fail with 'No Record Found' instead of triggering on-demand formatting? [Severity: Medium] Does this leave a stale cache in memory if the format succeeds but destroys the on-disk label? If track 0 is formatted using the LDL format mode (intensity == 0x00), it skips writing the label but rc will be 0. Would this leave the old ese_label_valid state incorrectly set to true? [ ... ] While reviewing these changes, I also noticed a pre-existing issue in the dasd ioctl handling: [Severity: High] This is a pre-existing issue, but can dasd_release_space() in drivers/s390/block/dasd_ioctl.c trigger a NULL pointer dereference? If a device lacks the is_ese callback (such as dasd_fba), this logic: if (!device->discipline->is_ese && !device->discipline->is_ese(device)) return -ENOTSUPP; evaluates to true for the first condition when the pointer is NULL, and then attempts to call the NULL pointer in the second condition. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=14