All of lore.kernel.org
 help / color / mirror / Atom feed
From: Konrad Rzeszutek Wilk <konrad@darnok.org>
To: Adin Scannell <adin@scannell.ca>
Cc: andres@gridcentric.ca, xen-devel@lists.xensource.com,
	olaf@aepfle.de, JBeulich@suse.com, adin@gridcentric.com
Subject: Re: [PATCH 2/3] Handle GNTST_eagain in kernel drivers
Date: Sat, 17 Dec 2011 09:30:16 -0500	[thread overview]
Message-ID: <20111217143015.GD14816@konrad-lan> (raw)
In-Reply-To: <1324092141-9730-3-git-send-email-adin@scannell.ca>

On Fri, Dec 16, 2011 at 10:22:20PM -0500, Adin Scannell wrote:
> Handle GNTST_eagain status from GNTTABOP_map_grant_ref and
> GNTTABOP_copy operations properly to allow usage of xenpaging without
> causing crashes or data corruption.
> 
> Replace all relevant HYPERVISOR_grant_table_op() calls with a retry
> loop. This loop is implemented as a macro to allow different
> GNTTABOP_* args. It will sleep up to 33 seconds and wait for the
> page to be paged in again.
> 
> All ->status checks were updated to use the GNTST_* namespace. All
> return values are converted from GNTST_* namespace to 0/-EINVAL, since
> all callers did not use the actual return value.
> 
> Signed-off-by: Olaf Hering <olaf@aepfle.de>
> Acked-by: Patrick Colp <pjcolp@cs.ubc.ca>
> 
> This is a port to the mainline Linux tree.  This required dropping many backend
> drivers which have not yet made it in.  Additionally, several of the referenced
> functions have moved and/or been refactored.  I attempted to minimize changes
> while keeping the same semantics.
> 
> Signed-off-by: Adin Scannell <adin@scannell.ca>
> 
> Index: linux/drivers/block/xen-blkback/blkback.c
> ===================================================================
> ---
>  drivers/block/xen-blkback/blkback.c |    4 ++-
>  drivers/xen/grant-table.c           |    7 ++++-
>  drivers/xen/xenbus/xenbus_client.c  |    4 +++
>  include/xen/grant_table.h           |   39 +++++++++++++++++++++++++++++++++++
>  include/xen/interface/grant_table.h |    6 ++++-

>  5 files changed, 56 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
> index 15ec4db..d3fb290 100644
> --- a/drivers/block/xen-blkback/blkback.c
> +++ b/drivers/block/xen-blkback/blkback.c
> @@ -390,7 +390,9 @@ static int xen_blkbk_map(struct blkif_request *req,
>  	 * the page from the other domain.
>  	 */
>  	for (i = 0; i < nseg; i++) {
> -		if (unlikely(map[i].status != 0)) {
> +		if (unlikely(map[i].status == GNTST_eagain))
> +			gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, &map[i]);
> +		if (unlikely(map[i].status != GNTST_okay)) {
>  			pr_debug(DRV_PFX "invalid buffer -- could not remap it\n");
>  			map[i].handle = BLKBACK_INVALID_HANDLE;
>  			ret |= 1;

> diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
> index bf1c094..48826c3 100644
> --- a/drivers/xen/grant-table.c
> +++ b/drivers/xen/grant-table.c
> @@ -464,9 +464,12 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
>  
>  	for (i = 0; i < count; i++) {
>  		/* Do not add to override if the map failed. */
> -		if (map_ops[i].status)
> +		if (map_ops[i].status != GNTST_okay && map_ops[i].status != GNTST_eagain)
>  			continue;
>  
> +		if (map_ops[i].status == GNTST_eagain)
> +			return -EAGAIN;
> +
>  		if (map_ops[i].flags & GNTMAP_contains_pte) {
>  			pte = (pte_t *) (mfn_to_virt(PFN_DOWN(map_ops[i].host_addr)) +
>  				(map_ops[i].host_addr & ~PAGE_MASK));
> @@ -565,7 +568,7 @@ static int gnttab_map(unsigned int start_idx, unsigned int end_idx)
>  		return -ENOSYS;
>  	}
>  
> -	BUG_ON(rc || setup.status);
> +	BUG_ON(rc || (setup.status != GNTST_okay));
>  
>  	rc = arch_gnttab_map_shared(frames, nr_gframes, gnttab_max_grant_frames(),
>  				    &shared);
> diff --git a/drivers/xen/xenbus/xenbus_client.c b/drivers/xen/xenbus/xenbus_client.c
> index 1906125..d123c78 100644
> --- a/drivers/xen/xenbus/xenbus_client.c
> +++ b/drivers/xen/xenbus/xenbus_client.c
> @@ -455,6 +455,8 @@ int xenbus_map_ring_valloc(struct xenbus_device *dev, int gnt_ref, void **vaddr)
>  	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>  		BUG();
>  
> +	if (op.status == GNTST_eagain)
> +		gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, (&op));
>  	if (op.status != GNTST_okay) {
>  		free_vm_area(area);
>  		xenbus_dev_fatal(dev, op.status,
> @@ -499,6 +501,8 @@ int xenbus_map_ring(struct xenbus_device *dev, int gnt_ref,
>  	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
>  		BUG();
>  
> +	if (op.status == GNTST_eagain)
> +		gnttab_check_GNTST_eagain_do_while(GNTTABOP_map_grant_ref, (&op));
>  	if (op.status != GNTST_okay) {
>  		xenbus_dev_fatal(dev, op.status,
>  				 "mapping in shared page %d from domain %d",
> diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
> index 11e2dfc..46fac85 100644
> --- a/include/xen/grant_table.h
> +++ b/include/xen/grant_table.h
> @@ -37,6 +37,8 @@
>  #ifndef __ASM_GNTTAB_H__
>  #define __ASM_GNTTAB_H__
>  
> +#include <linux/delay.h>
> +
>  #include <asm/page.h>
>  
>  #include <xen/interface/xen.h>
> @@ -160,4 +162,41 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
>  int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
>  		      struct page **pages, unsigned int count);
>  
> +#define gnttab_check_GNTST_eagain_while(__HCop, __HCarg_p)					\

So why does this have to be a macro? What is the advantage of that
versus making this a function?

> +do {																		\
> +	u8 __hc_delay = 1;														\
> +	int __ret;																\
> +	while (unlikely((__HCarg_p)->status == GNTST_eagain && __hc_delay)) {	\
> +		msleep(__hc_delay++);												\

Ugh. Not sure what happend to this, but there are tons of '\' at the
end.

So why msleep? Why not go for a proper yield? Call the safe_halt()
function?

> +		__ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);			\
> +		BUG_ON(__ret);														\
> +	}																		\
> +	if (__hc_delay == 0) {													\

So this would happen if we rolled over __hc_delay, so did this more than
255 times? Presumarily this can happen if the swapper in dom0 crashes..

I would recommend you use 'WARN' here and include tons of details.
This is a pretty serious issues, is it not?

> +		printk(KERN_ERR "%s: gnt busy\n", __func__,);						\
> +		(__HCarg_p)->status = GNTST_bad_page;								\
> +	}																		\
> +	if ((__HCarg_p)->status != GNTST_okay)									\
> +		printk(KERN_ERR "%s: gnt status %x\n", 								\
> +			__func__, (__HCarg_p)->status);									\

Use GNTTABOP_error_msgs. Also should we continue? What is the
impact if we do continue? The times this is hit is if the status
is not GNTS_okay and if it is not GNTS_eagain - so what are the
situations in which this happens and what can the domain do
to recover? Should there be some helpfull message instead of
just "gnt status: X" ?

> +} while(0)
> +
> +#define gnttab_check_GNTST_eagain_do_while(__HCop, __HCarg_p)			\
> +do {																	\
> +	u8 __hc_delay = 1;													\
> +	int __ret;															\
> +	do {																\
> +		__ret = HYPERVISOR_grant_table_op(__HCop, (__HCarg_p), 1);		\
> +		BUG_ON(__ret);													\
> +		if ((__HCarg_p)->status == GNTST_eagain)						\
> +			msleep(__hc_delay++);										\
> +	} while ((__HCarg_p)->status == GNTST_eagain && __hc_delay);		\
> +	if (__hc_delay == 0) {												\
> +		printk(KERN_ERR "%s: gnt busy\n", __func__);					\
> +		(__HCarg_p)->status = GNTST_bad_page;							\
> +	}																	\
> +	if ((__HCarg_p)->status != GNTST_okay)								\
> +		printk(KERN_ERR "%s: gnt status %x\n", 							\
> +			__func__, (__HCarg_p)->status);								\
> +} while(0)
> +
>  #endif /* __ASM_GNTTAB_H__ */
> diff --git a/include/xen/interface/grant_table.h b/include/xen/interface/grant_table.h
> index 39e5717..ba04080 100644
> --- a/include/xen/interface/grant_table.h
> +++ b/include/xen/interface/grant_table.h
> @@ -363,6 +363,8 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
>  #define GNTST_permission_denied (-8) /* Not enough privilege for operation.  */
>  #define GNTST_bad_page         (-9) /* Specified page was invalid for op.    */
>  #define GNTST_bad_copy_arg    (-10) /* copy arguments cross page boundary */
> +#define GNTST_address_too_big (-11) /* transfer page address too large.      */
> +#define GNTST_eagain          (-12) /* Could not map at the moment. Retry.   */
>  
>  #define GNTTABOP_error_msgs {                   \
>      "okay",                                     \
> @@ -375,7 +377,9 @@ DEFINE_GUEST_HANDLE_STRUCT(gnttab_query_size);
>      "no spare translation slot in the I/O MMU", \
>      "permission denied",                        \
>      "bad page",                                 \
> -    "copy arguments cross page boundary"        \
> +    "copy arguments cross page boundary",       \
> +    "page address size too large",              \
> +    "could not map at the moment, retry"        \
>  }
>  
>  #endif /* __XEN_PUBLIC_GRANT_TABLE_H__ */
> -- 
> 1.6.2.5
> 

  reply	other threads:[~2011-12-17 14:30 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-12-17  3:22 [PATCH] Add necessary bits to pvops Linux for mapping paged-out pages Adin Scannell
2011-12-17  3:22 ` [PATCH 1/3] Make xen_remap_domain_mfn_range return value meaningful in case of error Adin Scannell
2011-12-17  3:22 ` [PATCH 2/3] Handle GNTST_eagain in kernel drivers Adin Scannell
2011-12-17 14:30   ` Konrad Rzeszutek Wilk [this message]
2011-12-17 16:53     ` Adin Scannell
2011-12-17 21:31       ` Konrad Rzeszutek Wilk
2012-01-02 16:06     ` Olaf Hering
2012-01-03 18:19       ` Konrad Rzeszutek Wilk
2012-01-03 18:40         ` Olaf Hering
2012-01-03 18:48           ` Konrad Rzeszutek Wilk
2011-12-17  3:22 ` [PATCH 3/3] Port of mmap_batch_v2 to support paging in Xen Adin Scannell
2011-12-17 14:40   ` Konrad Rzeszutek Wilk
2011-12-17 16:51     ` Adin Scannell
2011-12-17 21:29       ` Konrad Rzeszutek Wilk
2011-12-17  3:49 ` [PATCH] Add necessary bits to pvops Linux for mapping paged-out pages Adin Scannell
2011-12-17 14:16 ` Konrad Rzeszutek Wilk
2011-12-17 14:16 ` Konrad Rzeszutek Wilk
2012-01-02 16:06 ` Olaf Hering

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=20111217143015.GD14816@konrad-lan \
    --to=konrad@darnok.org \
    --cc=JBeulich@suse.com \
    --cc=adin@gridcentric.com \
    --cc=adin@scannell.ca \
    --cc=andres@gridcentric.ca \
    --cc=olaf@aepfle.de \
    --cc=xen-devel@lists.xensource.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.