[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 2/2] nbd: Clean up clients more efficiently
From: |
Eric Blake |
Subject: |
Re: [PATCH v3 2/2] nbd: Clean up clients more efficiently |
Date: |
Tue, 6 Aug 2024 07:58:07 -0500 |
User-agent: |
NeoMutt/20240425 |
On Tue, Aug 06, 2024 at 10:32:54AM GMT, Daniel P. Berrangé wrote:
> On Mon, Aug 05, 2024 at 09:21:36PM -0500, Eric Blake wrote:
> > Since an NBD server may be long-living, serving clients that
> > repeatedly connect and disconnect, it can be more efficient to clean
> > up after each client disconnects, rather than storing a list of
> > resources to clean up when the server exits. Rewrite the list of
> > known clients to be double-linked so that we can get O(1) deletion to
> > keep the list pruned to size as clients exit. This in turn requires
> > each client to track an opaque pointer of owner information (although
> > qemu-nbd doesn't need to refer to it).
>
> I tend to feel that this needs to be squashed into the previous
> patch. The previous patch effectively creates unbounded memory
> usage in the NBD server. ie consider a client that connects and
> immediately disconnects, not sending any data, in a tight loop.
> It will "leak" NBDConn & QIOChanelSocket pointers for each
> iteration of the loop, only to be cleaned up when the NBD Server
> is shutdown.
>
> Especially given that we tagged the previous commit with a CVE
> and not this commit, people could be misled into backporting
> only the former commit leaving them open to the leak.
Makes sense. Will respin v4 along those lines; although I plan to
refactor slightly: have patch 1 pick up the part of this patch that
allows server.c to track a client's owner, then patch 2 be the CVE fix
creating the doubly-linked list of QIOSocketChannel wrappers as
owners. Also, I realized that nbd_server->connections == 0 is now
effectively redundant with QLIST_EMPTY(&nbd_server->conns), so that's
another cleanup to squash in.
> > @@ -103,14 +112,9 @@ static void nbd_server_free(NBDServerData *server)
> > */
> > qio_net_listener_disconnect(server->listener);
> > object_unref(OBJECT(server->listener));
> > - while (!QSLIST_EMPTY(&server->conns)) {
> > - NBDConn *conn = QSLIST_FIRST(&server->conns);
> > -
> > + QLIST_FOREACH_SAFE(conn, &server->conns, next, tmp) {
> > qio_channel_shutdown(QIO_CHANNEL(conn->cioc),
> > QIO_CHANNEL_SHUTDOWN_BOTH,
> > NULL);
> > - object_unref(OBJECT(conn->cioc));
> > - QSLIST_REMOVE_HEAD(&server->conns, next);
> > - g_free(conn);
> > }
> >
> > AIO_WAIT_WHILE_UNLOCKED(NULL, server->connections > 0);
--
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization: qemu.org | libguestfs.org