Linux s390 Architecture development
 help / color / mirror / Atom feed
From: Eric Farman <farman@linux.ibm.com>
To: Matthew Rosato <mjrosato@linux.ibm.com>,
	linux-s390@vger.kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org
Cc: Halil Pasic <pasic@linux.ibm.com>,
	Christian Borntraeger <borntraeger@linux.ibm.com>,
	stable@vger.kernel.org
Subject: Re: [PATCH v7 08/10] s390/vfio_ccw: move cp cleanup out of not operational
Date: Mon, 27 Jul 2026 20:54:18 -0400	[thread overview]
Message-ID: <59a72d98-5f33-4bda-88cd-4e89ba237b9a@linux.ibm.com> (raw)
In-Reply-To: <1819d316-62b9-48c7-abaa-f40681e22abf@linux.ibm.com>



On 7/27/26 5:54 PM, Matthew Rosato wrote:
> On 7/27/26 3:22 PM, Eric Farman wrote:
>> The fsm_notoper() routine is called when the device has been
>> lost, and is (by definition) no longer operational. Since this
>> can happen asynchronously from the normal behavior of the
>> driver, the cleanup may happen when holding other locks
>> in the calling sequence (notably, the cio subchannel lock).
>>
>> Push the cleanup of the private->cp resources to a workqueue,
>> where it can be done out from under that lock sequence and
>> (soon) under its own serialization mechanism.
> 
> This part of the commit message needs updating now that you are not
> introducing a cp_mutex.
> 
>>
>> Fixes: 204b394a23ad ("vfio/ccw: Move FSM open/close to MDEV open/close")
>> Cc: stable@vger.kernel.org
>> Signed-off-by: Eric Farman <farman@linux.ibm.com>
>> ---
>>   drivers/s390/cio/vfio_ccw_drv.c     | 9 +++++++++
>>   drivers/s390/cio/vfio_ccw_fsm.c     | 3 +--
>>   drivers/s390/cio/vfio_ccw_ops.c     | 3 +++
>>   drivers/s390/cio/vfio_ccw_private.h | 3 +++
>>   4 files changed, 16 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c
>> index 1a095085bc72..c197ad5ab580 100644
>> --- a/drivers/s390/cio/vfio_ccw_drv.c
>> +++ b/drivers/s390/cio/vfio_ccw_drv.c
>> @@ -125,6 +125,15 @@ void vfio_ccw_crw_todo(struct work_struct *work)
>>   		eventfd_signal(private->crw_trigger);
>>   }
>>   
>> +void vfio_ccw_notoper_todo(struct work_struct *work)
>> +{
>> +	struct vfio_ccw_private *private;
>> +
>> +	private = container_of(work, struct vfio_ccw_private, notoper_work);
>> +
>> +	cp_free(&private->cp);
>> +}
>> +
>>   /*
>>    * Css driver callbacks
>>    */
>> diff --git a/drivers/s390/cio/vfio_ccw_fsm.c b/drivers/s390/cio/vfio_ccw_fsm.c
>> index 4d7988ea47ef..4d47a3c7b9a0 100644
>> --- a/drivers/s390/cio/vfio_ccw_fsm.c
>> +++ b/drivers/s390/cio/vfio_ccw_fsm.c
>> @@ -170,8 +170,7 @@ static void fsm_notoper(struct vfio_ccw_private *private,
>>   	css_sched_sch_todo(sch, SCH_TODO_UNREG);
>>   	private->state = VFIO_CCW_STATE_NOT_OPER;
>>   
>> -	/* This is usually handled during CLOSE event */
>> -	cp_free(&private->cp);
>> +	queue_work(vfio_ccw_work_q, &private->notoper_work);
>>   }
>>   
>>   /*
>> diff --git a/drivers/s390/cio/vfio_ccw_ops.c b/drivers/s390/cio/vfio_ccw_ops.c
>> index bd488e40e153..8ec6b175d991 100644
>> --- a/drivers/s390/cio/vfio_ccw_ops.c
>> +++ b/drivers/s390/cio/vfio_ccw_ops.c
>> @@ -54,6 +54,7 @@ static int vfio_ccw_mdev_init_dev(struct vfio_device *vdev)
>>   	INIT_LIST_HEAD(&private->crw);
>>   	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);
>>   	INIT_WORK(&private->crw_work, vfio_ccw_crw_todo);
>> +	INIT_WORK(&private->notoper_work, vfio_ccw_notoper_todo);
>>   
>>   	private->cp.guest_cp = kzalloc_objs(struct ccw1, CCWCHAIN_LEN_MAX);
>>   	if (!private->cp.guest_cp)
>> @@ -139,6 +140,7 @@ static void vfio_ccw_mdev_release_dev(struct vfio_device *vdev)
>>   	/* Should be empty, but just in case */
>>   	cancel_work_sync(&private->io_work);
>>   	cancel_work_sync(&private->crw_work);
>> +	cancel_work_sync(&private->notoper_work);
> 
> Sashiko mentions (and I agree) that you can accidentally leak the cp
> resources if you manage to cancel the pending notoper_work before it runs.
> 
> Since you are not running on a workqueue thread, it should be OK to
> flush instead to make sure that the pending item is executed.
> 
> A subsequent cancel should not be necessary, since we know that only 1
> instance of vfio_ccw_notoper_todo() will ever be queued because we queue
> it on the first time the device goes NOT_OPER.  Based on the FSM, once
> the device goes NOT_OPER, subsequent transitions into NOT_OPER are
> treated as a NOP and there is no way to transition to a different state
> other than NOT_OPER until the device is released, so you can't go from
> NOT_OPER->x->NOT_OPER.

Agreed, this should be flush not cancel.

Though, the piece where that's important is the call in close_dev, which 
is the counterpart to the open_device path which allows a cp to be 
queued in the first place. A close will have preceded a release, which 
means there will no longer be any cp's outstanding, and userspace will 
have been unable to submit new ones without performing another open.

The other two elements (io_work and crw_work) would be queued in 
response to a hardware event (an interrupt and a CRW, respectively), 
which could come asynchronously from all of this, so needs to be in both 
close and release.

> 
> Would probably be good to include a (less verbose) comment to that
> effect along with the flush.
> 

Agreed; thanks.

>>   
>>   	kmem_cache_free(vfio_ccw_crw_region, private->crw_region);
>>   	kmem_cache_free(vfio_ccw_schib_region, private->schib_region);
>> @@ -209,6 +211,7 @@ static void vfio_ccw_mdev_close_device(struct vfio_device *vdev)
>>   
>>   	cancel_work_sync(&private->io_work);
>>   	cancel_work_sync(&private->crw_work);
>> +	cancel_work_sync(&private->notoper_work);
>>   
>>   	vfio_ccw_unregister_dev_regions(private);
>>   }
>> diff --git a/drivers/s390/cio/vfio_ccw_private.h b/drivers/s390/cio/vfio_ccw_private.h
>> index 0501d4bbcdbd..e2256402b089 100644
>> --- a/drivers/s390/cio/vfio_ccw_private.h
>> +++ b/drivers/s390/cio/vfio_ccw_private.h
>> @@ -102,6 +102,7 @@ struct vfio_ccw_parent {
>>    * @req_trigger: eventfd ctx for signaling userspace to return device
>>    * @io_work: work for deferral process of I/O handling
>>    * @crw_work: work for deferral process of CRW handling
>> + * @notoper_work: work for deferred processing in not-operational state
>>    */
>>   struct vfio_ccw_private {
>>   	struct vfio_device vdev;
>> @@ -125,11 +126,13 @@ struct vfio_ccw_private {
>>   	struct eventfd_ctx	*req_trigger;
>>   	struct work_struct	io_work;
>>   	struct work_struct	crw_work;
>> +	struct work_struct	notoper_work;
>>   } __aligned(8);
>>   
>>   int vfio_ccw_sch_quiesce(struct subchannel *sch);
>>   void vfio_ccw_sch_io_todo(struct work_struct *work);
>>   void vfio_ccw_crw_todo(struct work_struct *work);
>> +void vfio_ccw_notoper_todo(struct work_struct *work);
>>   
>>   extern struct mdev_driver vfio_ccw_mdev_driver;
>>   
> 


  reply	other threads:[~2026-07-28  0:54 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-27 19:22 [PATCH v7 00/10] s390/vfio_ccw fixes Eric Farman
2026-07-27 19:22 ` [PATCH v7 01/10] s390/vfio_ccw: free all memory if cp_init() fails Eric Farman
2026-07-27 19:58   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 02/10] s390/vfio_ccw: limit the number of channel program segments Eric Farman
2026-07-27 19:52   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 03/10] s390/vfio_ccw: fix out of bounds check on CCW array Eric Farman
2026-07-27 19:53   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 04/10] s390/vfio_ccw: ensure first IDAW remains constant Eric Farman
2026-07-27 19:59   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 05/10] s390/vfio_ccw: calculate idal length based on idaw type Eric Farman
2026-07-27 19:54   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 06/10] s390/vfio_ccw: ensure index for read/write regions are within range Eric Farman
2026-07-27 20:03   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 07/10] s390/vfio_ccw: cancel existing workqueues Eric Farman
2026-07-27 20:02   ` sashiko-bot
2026-07-27 21:54   ` Matthew Rosato
2026-07-27 19:22 ` [PATCH v7 08/10] s390/vfio_ccw: move cp cleanup out of not operational Eric Farman
2026-07-27 20:04   ` sashiko-bot
2026-07-27 21:54   ` Matthew Rosato
2026-07-28  0:54     ` Eric Farman [this message]
2026-07-27 19:22 ` [PATCH v7 09/10] s390/vfio_ccw: selectively expand io_mutex Eric Farman
2026-07-27 20:12   ` sashiko-bot
2026-07-27 19:22 ` [PATCH v7 10/10] s390/vfio_ccw: implement a crw lock Eric Farman
2026-07-27 20:07   ` sashiko-bot
2026-07-27 21:35   ` Farhan Ali

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=59a72d98-5f33-4bda-88cd-4e89ba237b9a@linux.ibm.com \
    --to=farman@linux.ibm.com \
    --cc=borntraeger@linux.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    --cc=mjrosato@linux.ibm.com \
    --cc=pasic@linux.ibm.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox