From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752301AbbCLBzH (ORCPT ); Wed, 11 Mar 2015 21:55:07 -0400 Received: from ozlabs.org ([103.22.144.67]:38364 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751549AbbCLBzE (ORCPT ); Wed, 11 Mar 2015 21:55:04 -0400 From: Rusty Russell To: "Michael S. Tsirkin" , linux-kernel@vger.kernel.org Cc: virtualization@lists.linux-foundation.org, Eric Van Hensbergen , Ron Minnich , Latchesar Ionkov , "David S. Miller" , v9fs-developer@lists.sourceforge.net, netdev@vger.kernel.org Subject: Re: [PATCH] 9p/trans_virtio: fix hot-unplug In-Reply-To: <20150309154814-mutt-send-email-mst@redhat.com> References: <20150309154814-mutt-send-email-mst@redhat.com> User-Agent: Notmuch/0.17 (http://notmuchmail.org) Emacs/24.3.1 (x86_64-pc-linux-gnu) Date: Thu, 12 Mar 2015 11:54:10 +1030 Message-ID: <874mprxb2d.fsf@rustcorp.com.au> MIME-Version: 1.0 Content-Type: text/plain Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org "Michael S. Tsirkin" writes: > On device hot-unplug, 9p/virtio currently will kfree channel while > it might still be in use. > > Of course, it might stay used forever, so it's an extremely ugly hack, > but it seems better than use-after-free that we have now. > > Signed-off-by: Michael S. Tsirkin I'll apply it, but it looks like a bandaid. The right answer would seem to be: 1) Use reference counting: 1 for client, 1 for transport. 2) When hot unplug, complete (ie. fail) all outstanding requests. 3) From then on, fail all incoming requests. 4) When refcount hits 0, free the structure. Thanks, Rusty. > --- > net/9p/trans_virtio.c | 25 +++++++++++++++++++++---- > 1 file changed, 21 insertions(+), 4 deletions(-) > > diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c > index d8e376a..d1b2f306 100644 > --- a/net/9p/trans_virtio.c > +++ b/net/9p/trans_virtio.c > @@ -658,14 +658,31 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) > static void p9_virtio_remove(struct virtio_device *vdev) > { > struct virtio_chan *chan = vdev->priv; > - > - if (chan->inuse) > - p9_virtio_close(chan->client); > - vdev->config->del_vqs(vdev); > + unsigned long warning_time; > + bool inuse; > > mutex_lock(&virtio_9p_lock); > + > + /* Remove self from list so we don't get new users. */ > list_del(&chan->chan_list); > + warning_time = jiffies; > + > + /* Wait for existing users to close. */ > + while (chan->inuse) { > + mutex_unlock(&virtio_9p_lock); > + msleep(250); > + if (time_after(jiffies, warning_time + 10 * HZ)) { > + dev_emerg(&vdev->dev, "p9_virtio_remove: " > + "waiting for device in use.\n"); > + warning_time = jiffies; > + } > + mutex_lock(&virtio_9p_lock); > + } > + > mutex_unlock(&virtio_9p_lock); > + > + vdev->config->del_vqs(vdev); > + > sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); > kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); > kfree(chan->tag); > -- > MST