qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: liu ping fan <qemulist@gmail.com>
Cc: Stefan Hajnoczi <stefanha@gmail.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	qemu-devel@nongnu.org, Anthony Liguori <anthony@codemonkey.ws>,
	mdroth <mdroth@linux.vnet.ibm.com>
Subject: Re: [Qemu-devel] [PATCH v2 4/5] net: introduce lock to protect NetClientState's peer's access
Date: Wed, 13 Mar 2013 11:39:25 +0100	[thread overview]
Message-ID: <5140575D.7050507@redhat.com> (raw)
In-Reply-To: <CAJnKYQ=dOEShj1WD+n+KOv70XinDkcAZ=SJCHY+rQ8jNVpMgTw@mail.gmail.com>

Il 13/03/2013 02:26, liu ping fan ha scritto:
> On Tue, Mar 12, 2013 at 4:55 PM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>> Il 07/03/2013 03:53, Liu Ping Fan ha scritto:
>>> From: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
>>>
>>> Introduce nc->send_lock, it shield off the race of nc->peer's reader and
>>> deleter. With it, after deleter finish, no new qemu_send_packet_xx()
>>> can reach ->send_queue, so no new reference(packet->sender) to nc will
>>> be appended to nc->peer->send_queue.
>>>
>>> Signed-off-by: Liu Ping Fan <pingfank@linux.vnet.ibm.com>
>>> ---
>>>  include/net/net.h |    4 +++
>>>  net/hub.c         |   18 ++++++++++++
>>>  net/net.c         |   77 ++++++++++++++++++++++++++++++++++++++++++++++++++---
>>>  net/queue.c       |    4 +-
>>>  4 files changed, 97 insertions(+), 6 deletions(-)
>>>
>>> diff --git a/include/net/net.h b/include/net/net.h
>>> index 9c2b357..45779d2 100644
>>> --- a/include/net/net.h
>>> +++ b/include/net/net.h
>>> @@ -66,6 +66,8 @@ struct NetClientState {
>>>      NetClientInfo *info;
>>>      int link_down;
>>>      QTAILQ_ENTRY(NetClientState) next;
>>> +    /* protect the race access of peer between deleter and sender */
>>> +    QemuMutex send_lock;
>>>      NetClientState *peer;
>>>      NetQueue *send_queue;
>>>      char *model;
>>> @@ -78,6 +80,7 @@ struct NetClientState {
>>>
>>>  typedef struct NICState {
>>>      NetClientState *ncs;
>>> +    NetClientState **pending_peer;
>>>      NICConf *conf;
>>>      void *opaque;
>>>      bool peer_deleted;
>>> @@ -105,6 +108,7 @@ NetClientState *qemu_find_vlan_client_by_name(Monitor *mon, int vlan_id,
>>>                                                const char *client_str);
>>>  typedef void (*qemu_nic_foreach)(NICState *nic, void *opaque);
>>>  void qemu_foreach_nic(qemu_nic_foreach func, void *opaque);
>>> +int qemu_can_send_packet_nolock(NetClientState *sender);
>>>  int qemu_can_send_packet(NetClientState *nc);
>>>  ssize_t qemu_sendv_packet(NetClientState *nc, const struct iovec *iov,
>>>                            int iovcnt);
>>> diff --git a/net/hub.c b/net/hub.c
>>> index 47fe72c..d953a99 100644
>>> --- a/net/hub.c
>>> +++ b/net/hub.c
>>> @@ -57,8 +57,14 @@ static ssize_t net_hub_receive(NetHub *hub, NetHubPort *source_port,
>>>              continue;
>>>          }
>>>
>>> +        qemu_mutex_lock(&port->nc.send_lock);
>>> +        if (!port->nc.peer) {
>>> +            qemu_mutex_unlock(&port->nc.send_lock);
>>> +            continue;
>>> +        }
>>>          qemu_net_queue_append(port->nc.peer->send_queue, &port->nc,
>>>                              QEMU_NET_PACKET_FLAG_NONE, buf, len, NULL);
>>> +        qemu_mutex_unlock(&port->nc.send_lock);
>>
>> Do you really need to lock everything?  Can you just wrap the peer with
>> a ref/unref, like
>>
>> NetClientState *net_client_get_peer(NetClientState *nc)
>> {
>>     NetClientState *peer;
>>     qemu_mutex_lock(&nc->send_lock);
>>     peer = nc->peer;
>>     if (peer) {
>>         net_client_ref(peer);
>>     }
>>     qemu_mutex_unlock(&nc->send_lock);
>>     return peer;
>> }
>>
>> and then
>>
>> -        qemu_net_queue_append(port->nc.peer->send_queue, &port->nc,
>> +        peer = net_client_get_peer(&port->nc);
>> +        if (!peer) {
>> +            continue;
>> +        }
>> +        qemu_net_queue_append(peer->send_queue, &port->nc,
>>                              QEMU_NET_PACKET_FLAG_NONE, buf, len, NULL);
>> +        net_client_unref(peer);
>>
> Oh, seems that I do not explain very clearly in the commit log.  The
> lock does not only protect against the reclaimer( and this can be
> achieved by refcnt as your codes),  but also sync between remover and
> sender.   If the NetClientState being removed, the remover will be
> like:
>              nc->peer = NULL;
>               ----------> Here opens the gap for in-flight sender, and
> refcnt can not work
>              flush out reference from its peer's send_queue;

What's the problem if the dying peer is still used momentarily?  The
next unref will drop the last reference and qemu_del_net_queue will free
the packet that was just appended.

Paolo

  reply	other threads:[~2013-03-13 10:40 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-07  2:53 [Qemu-devel] [PATCH v2 0/5] make netlayer re-entrant Liu Ping Fan
2013-03-07  2:53 ` [Qemu-devel] [PATCH v2 1/5] net: spread hub on AioContexts Liu Ping Fan
2013-03-12  8:50   ` Paolo Bonzini
2013-03-13  2:26     ` liu ping fan
2013-03-13 10:37       ` Paolo Bonzini
2013-03-07  2:53 ` [Qemu-devel] [PATCH v2 2/5] net: hub use lock to protect ports list Liu Ping Fan
2013-03-12  8:56   ` Paolo Bonzini
2013-03-07  2:53 ` [Qemu-devel] [PATCH v2 3/5] net: introduce lock to protect NetQueue Liu Ping Fan
2013-03-07  2:53 ` [Qemu-devel] [PATCH v2 4/5] net: introduce lock to protect NetClientState's peer's access Liu Ping Fan
2013-03-12  8:55   ` Paolo Bonzini
2013-03-13  1:26     ` liu ping fan
2013-03-13 10:39       ` Paolo Bonzini [this message]
2013-03-14  2:14         ` liu ping fan
2013-03-07  2:53 ` [Qemu-devel] [PATCH v2 5/5] net: make netclient re-entrant with refcnt Liu Ping Fan
2013-03-12  8:45   ` Paolo Bonzini

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=5140575D.7050507@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=mst@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemulist@gmail.com \
    --cc=stefanha@gmail.com \
    /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;
as well as URLs for NNTP newsgroup(s).