Commit 780f0e6a authored by Mike Rapoport's avatar Mike Rapoport Committed by Andrei Vagin

lazy-pages: replace crappy num_children with simple reference counting

The purpose of the num_children field in 'struct lazy_pages_info' was to
prevent closing the page-read while there are still active processes that
share it. It did work for the case when handling of the child processes
finished before the parent process. However, if the parent lpi is closed
first, we've got a dangling pointer at lpi->parent.
The obvious solution is to use simple reference counting.
Signed-off-by: 's avatarMike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: 's avatarAndrei Vagin <avagin@virtuozzo.com>
parent 1d85ec97
......@@ -85,7 +85,7 @@ struct lazy_pages_info {
struct list_head reqs;
struct lazy_pages_info *parent;
unsigned num_children;
unsigned ref_cnt;
struct page_read pr;
......@@ -127,6 +127,7 @@ static struct lazy_pages_info *lpi_init(void)
INIT_LIST_HEAD(&lpi->l);
lpi->lpfd.read_event = handle_uffd_event;
lpi->xfer_len = DEFAULT_XFER_LEN;
lpi->ref_cnt = 1;
return lpi;
}
......@@ -146,6 +147,20 @@ static void free_iovs(struct lazy_pages_info *lpi)
}
}
static void lpi_fini(struct lazy_pages_info *lpi);
static inline void lpi_put(struct lazy_pages_info *lpi)
{
lpi->ref_cnt--;
if (!lpi->ref_cnt)
lpi_fini(lpi);
}
static inline void lpi_get(struct lazy_pages_info *lpi)
{
lpi->ref_cnt++;
}
static void lpi_fini(struct lazy_pages_info *lpi)
{
if (!lpi)
......@@ -155,12 +170,13 @@ static void lpi_fini(struct lazy_pages_info *lpi)
if (lpi->lpfd.fd > 0)
close(lpi->lpfd.fd);
if (lpi->parent)
lpi->parent->num_children--;
if (!lpi->parent && !lpi->num_children && lpi->pr.close)
lpi_put(lpi->parent);
if (!lpi->parent && lpi->pr.close)
lpi->pr.close(&lpi->pr);
xfree(lpi);
}
static int prepare_sock_addr(struct sockaddr_un *saddr)
{
int len;
......@@ -1077,7 +1093,7 @@ static int handle_fork(struct lazy_pages_info *parent_lpi, struct uffd_msg *msg)
dup_page_read(&lpi->parent->pr, &lpi->pr);
lpi->parent->num_children++;
lpi_get(lpi->parent);
return 1;
......@@ -1251,7 +1267,7 @@ static int handle_requests(int epollfd, struct epoll_event *events, int nr_fds)
if (list_empty(&lpi->reqs)) {
lazy_pages_summary(lpi);
list_del(&lpi->l);
lpi_fini(lpi);
lpi_put(lpi);
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment