Received: by 2002:ad5:474a:0:0:0:0:0 with SMTP id i10csp8634372imu; Tue, 4 Dec 2018 11:31:01 -0800 (PST) X-Google-Smtp-Source: AFSGD/UyucePCASIyiaIgJiPoRMA/IMKRxmG73rRJwh8JRhTFvZYiIUpOQsgO7MdzIs8RcpD0ejh X-Received: by 2002:a17:902:4324:: with SMTP id i33mr14565094pld.227.1543951861431; Tue, 04 Dec 2018 11:31:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1543951861; cv=none; d=google.com; s=arc-20160816; b=nuGFrqSrkUNzdWIdNYS1fKlvAgfkD55whji8eEkkZ/VjFf+qn9Vj8aKJe0QkjyEGrY vmzOQYlQRpcxyMUlXS2+vrjRrMujxgnQ8MZE2CMnGw4FSmKtEV567fCcubcyFPTJ+ppz EcihPbddivPTs/xA3XA7JdGH6AywnuC2TVmm0nYM02O/f2p207ePUMkCZz72LtyQzDym dhlkMeSp11WsG9c6xpfZDqu7MqBJ+YVlYPNZqLTKkSVmslSfyMI+sVC0spYBbzoIAqUO s9WU4aSVHhKty8LZNO+EjmIF+3yFjiKsm7xt1oZ0vgFxIEIa+6Qq98iRFFSOnsXLzWPL npIQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :message-id:in-reply-to:subject:cc:to:from:date:dkim-signature; bh=yIXH0gr4P5epReAG2Mk7IUlvo6B1DkJOfNyWdIRGQwM=; b=pJHnwqq+JrEX4LKuYECtC0TM+sXUdwlyyadDqUD53c953RKIUenXcCu9ZIA6W1Zb5f jUasri19OK8Um91lYqcPm2uV8/JlCiDcCx9fzHhBgQjUV5O2GENs3QwTtEyJQS4e6BDs AiCIK1mpIWh8di2nWwELL9mhQQC3kWsBnwGZVao0QRu5e6EROOGlqp8hdusQaC+lurjJ r/OUKn858YS32sIEbH8MsycuLYEjEeLrqSdt4G2hVbIgbzWOgoqQrT1aNFjLyKAsHwFJ Xl0eD+r4wJ+CGUgcmjKoIyMUmFewqWkOLLclJGa0+xMUbokKn4YyUci1N2RDhPAFyQUj 2MMQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lGXuJuWI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g15si16399893pgl.141.2018.12.04.11.30.46; Tue, 04 Dec 2018 11:31:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lGXuJuWI; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726246AbeLDT3s (ORCPT + 99 others); Tue, 4 Dec 2018 14:29:48 -0500 Received: from mail.kernel.org ([198.145.29.99]:39242 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725841AbeLDT3r (ORCPT ); Tue, 4 Dec 2018 14:29:47 -0500 Received: from localhost (c-67-164-102-47.hsd1.ca.comcast.net [67.164.102.47]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id D42DC20851; Tue, 4 Dec 2018 19:29:45 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1543951786; bh=Lv08ZrKz7g1AkPNI7rou+L8IpyiZP+dfjoilDHxS+rU=; h=Date:From:To:cc:Subject:In-Reply-To:References:From; b=lGXuJuWI3cdl88KjwyT1AvuJQuyrE+SaJKyQc/Pq5lzgwgvj0l92avrGQjW8xD5wz jzvNVxhIPNFsZqNEHDtPSVnW/IQyfh9NpzH1LOnLeFXZ8CbaqaL0GfjJ+VObrliVdB EP7m9BpxgTxbta+4gSAo8lSO5/IEvWJ9Ny6R0q2o= Date: Tue, 4 Dec 2018 11:29:45 -0800 (PST) From: Stefano Stabellini X-X-Sender: sstabellini@sstabellini-ThinkPad-X260 To: Wen Yang cc: boris.ostrovsky@oracle.com, jgross@suse.com, sstabellini@kernel.org, xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, zhong.weidong@zte.com.cn, wang.yi59@zte.com.cn, Julia Lawall Subject: Re: [PATCH v5] pvcalls-front: Avoid get_free_pages(GFP_KERNEL) under spinlock In-Reply-To: <1543907757-21647-1-git-send-email-wen.yang99@zte.com.cn> Message-ID: References: <1543907757-21647-1-git-send-email-wen.yang99@zte.com.cn> User-Agent: Alpine 2.10 (DEB 1266 2009-07-14) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, 4 Dec 2018, Wen Yang wrote: > The problem is that we call this with a spin lock held. > The call tree is: > pvcalls_front_accept() holds bedata->socket_lock. > -> create_active() > -> __get_free_pages() uses GFP_KERNEL > > The create_active() function is only called from pvcalls_front_accept() > with a spin_lock held, The allocation is not allowed to sleep and > GFP_KERNEL is not sufficient. > > This issue was detected by using the Coccinelle software. > > v2: Add a function doing the allocations which is called > outside the lock and passing the allocated data to > create_active(). > > v3: Use the matching deallocators i.e., free_page() > and free_pages(), respectively. > > v4: It would be better to pre-populate map (struct sock_mapping), > rather than introducing one more new struct. > > v5: Since allocating the data outside of this call it should also > be freed outside, when create_active() fails. > Move kzalloc(sizeof(*map2), GFP_ATOMIC) outside spinlock and > use GFP_KERNEL instead. > > Suggested-by: Juergen Gross > Suggested-by: Boris Ostrovsky > Suggested-by: Stefano Stabellini > Signed-off-by: Wen Yang > CC: Julia Lawall > CC: Boris Ostrovsky > CC: Juergen Gross > CC: Stefano Stabellini > CC: xen-devel@lists.xenproject.org > CC: linux-kernel@vger.kernel.org > --- > drivers/xen/pvcalls-front.c | 83 +++++++++++++++++++++++++++---------- > 1 file changed, 61 insertions(+), 22 deletions(-) > > diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c > index 77224d8f3e6f..5fd764a7b879 100644 > --- a/drivers/xen/pvcalls-front.c > +++ b/drivers/xen/pvcalls-front.c > @@ -335,6 +335,41 @@ int pvcalls_front_socket(struct socket *sock) > return ret; > } > > +static void free_active_ring(struct sock_mapping *map) > +{ > + free_pages((unsigned long)map->active.data.in, > + map->active.ring->ring_order); > + free_page((unsigned long)map->active.ring); > +} > + > +static int alloc_active_ring(struct sock_mapping *map) > +{ > + void *bytes; > + > + map->active.ring = NULL; This is superfluous Aside from this: Acked-by: Stefano Stabellini > + map->active.data.in = NULL; > + map->active.ring = (struct pvcalls_data_intf *) > + get_zeroed_page(GFP_KERNEL); > + if (!map->active.ring) > + goto out; > + > + map->active.ring->ring_order = PVCALLS_RING_ORDER; > + bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, > + PVCALLS_RING_ORDER); > + if (!bytes) > + goto out; > + > + map->active.data.in = bytes; > + map->active.data.out = bytes + > + XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); > + > + return 0; > + > +out: > + free_active_ring(map); > + return -ENOMEM; > +} > + > static int create_active(struct sock_mapping *map, int *evtchn) > { > void *bytes; > @@ -343,15 +378,7 @@ static int create_active(struct sock_mapping *map, int *evtchn) > *evtchn = -1; > init_waitqueue_head(&map->active.inflight_conn_req); > > - map->active.ring = (struct pvcalls_data_intf *) > - __get_free_page(GFP_KERNEL | __GFP_ZERO); > - if (map->active.ring == NULL) > - goto out_error; > - map->active.ring->ring_order = PVCALLS_RING_ORDER; > - bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, > - PVCALLS_RING_ORDER); > - if (bytes == NULL) > - goto out_error; > + bytes = map->active.data.in; > for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++) > map->active.ring->ref[i] = gnttab_grant_foreign_access( > pvcalls_front_dev->otherend_id, > @@ -361,10 +388,6 @@ static int create_active(struct sock_mapping *map, int *evtchn) > pvcalls_front_dev->otherend_id, > pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0); > > - map->active.data.in = bytes; > - map->active.data.out = bytes + > - XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER); > - > ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn); > if (ret) > goto out_error; > @@ -385,8 +408,6 @@ static int create_active(struct sock_mapping *map, int *evtchn) > out_error: > if (*evtchn >= 0) > xenbus_free_evtchn(pvcalls_front_dev, *evtchn); > - free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER); > - free_page((unsigned long)map->active.ring); > return ret; > } > > @@ -406,17 +427,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr, > return PTR_ERR(map); > > bedata = dev_get_drvdata(&pvcalls_front_dev->dev); > + ret = alloc_active_ring(map); > + if (ret < 0) { > + pvcalls_exit_sock(sock); > + return ret; > + } > > spin_lock(&bedata->socket_lock); > ret = get_request(bedata, &req_id); > if (ret < 0) { > spin_unlock(&bedata->socket_lock); > + free_active_ring(map); > pvcalls_exit_sock(sock); > return ret; > } > ret = create_active(map, &evtchn); > if (ret < 0) { > spin_unlock(&bedata->socket_lock); > + free_active_ring(map); > pvcalls_exit_sock(sock); > return ret; > } > @@ -780,25 +808,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags) > } > } > > - spin_lock(&bedata->socket_lock); > - ret = get_request(bedata, &req_id); > - if (ret < 0) { > + map2 = kzalloc(sizeof(*map2), GFP_KERNEL); > + if (map2 == NULL) { > clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, > (void *)&map->passive.flags); > - spin_unlock(&bedata->socket_lock); > + pvcalls_exit_sock(sock); > + return -ENOMEM; > + } > + ret = alloc_active_ring(map2); > + if (ret < 0) { > + clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, > + (void *)&map->passive.flags); > + kfree(map2); > pvcalls_exit_sock(sock); > return ret; > } > - map2 = kzalloc(sizeof(*map2), GFP_ATOMIC); > - if (map2 == NULL) { > + spin_lock(&bedata->socket_lock); > + ret = get_request(bedata, &req_id); > + if (ret < 0) { > clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, > (void *)&map->passive.flags); > spin_unlock(&bedata->socket_lock); > + free_active_ring(map2); > + kfree(map2); > pvcalls_exit_sock(sock); > - return -ENOMEM; > + return ret; > } > + > ret = create_active(map2, &evtchn); > if (ret < 0) { > + free_active_ring(map2); > kfree(map2); > clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT, > (void *)&map->passive.flags); > -- > 2.19.1 >