On Thu, Jul 09, 2026 at 04:45:51PM +0800, Richard Cheng wrote: > On Tue, Jun 30, 2026 at 05:18:38PM +0800, Gregory Price wrote: > > +/** > > + * offline_and_remove_memory_ranges - offline and remove multiple memory > > ranges > > + * @ranges: array of physical address ranges to offline and remove > > + * @nr_ranges: number of entries in @ranges > > + * > > + * Offline and remove several memory ranges as one operation, serialized > > + * against other hotplug operations by a single lock_device_hotplug(). > > + * > > + * This offlines all ranges before removing any of them. If offlining any > > + * range fails, the entire process is reverted and nothing is removed. > > + * This provides a fully atomic semantic for unplugging an entire device. > > + * > > + * Each range must be memory-block aligned in start and size. > > + * > > + * Return: 0 on success, negative errno otherwise. On failure no range has > > + * been removed. > > + */ > > I think this can return 1, and it shouldn't. > device_offline() returns 1 when a block is already offline, and phase 1 > passes that value through as-is. > > Easy to hit with patch 0, offline one memory block via memoryN/state, then > write > "unplugged" to daxX.Y/state. The store returns 1, userspace treats it as a > partial write of 1 byte, > and retries the write with the rest of the string. > > Maybe > """ > if (rc > 0) > rc = -EBUSY; > """
Oh weird, I thought I'd solved this problem at some point. I must have botched a rebase or something. Good catch. I'd originaly had some tests that race memoryN/state and dax/state, but I dropped them because it caused long testing cycles (mostly because i was testing force unplugging). Maybe I'll re-introduce some of these partial tests and just avoid the destructive ones. ~Gregory

