From: Harry Butterworth <harry@hebutterworth.freeserve.co.uk>
To: Keir Fraser <Keir.Fraser@cl.cam.ac.uk>
Cc: xen-devel@lists.xensource.com
Subject: Re: Bug in use of grant tables in blkback.c error path?
Date: Sun, 06 Nov 2005 16:18:20 +0000 [thread overview]
Message-ID: <1131293900.18044.6.camel@localhost> (raw)
In-Reply-To: <38fd2de25d0e0dcf5b4103266e7ea4f1@cl.cam.ac.uk>
On Sun, 2005-11-06 at 15:32 +0000, Keir Fraser wrote:
> On 6 Nov 2005, at 12:24, Harry Butterworth wrote:
>
> > All in all, this looks like a bug to me where failure to map a grant
> > reference in the middle of a set would result in pages kept mapped in
> > the backend when fast_flush_area fails to clean them up.
> >
> > Am I right?
>
> Yes, it's a bug. We'll sort out a patch.
>
OK. I ended up doing the following in my code. I'm not particularly
confident about it but hopefully it's correct. As in blkback, the
phys_to_machine_mapping gets left lying around after unmap. I assume
this is not a problem.
typedef struct xenidc_grant_table_mapping_context_struct
xenidc_grant_table_mapping_context;
struct xenidc_grant_table_mapping_context_struct
{
xenidc_buffer_mappable_class * class;
xenidc_buffer_resource_provider * provider;
unsigned long page_count;
unsigned long mmap_vaddress;
int16_t handle
[ XENIDC_REMOTE_BUFFER_REFERENCE_GRANT_TABLE_REFERENCE_COUNT ];
};
static void xenidc_grant_table_unmap_rbr
( xenidc_buffer_mappable_class ** context_in );
static xenidc_buffer_mappable_class ** xenidc_grant_table_map_rbr
(
xenidc_buffer_mappable_class * class,
xenidc_remote_buffer_reference * rbr,
xenidc_address * address,
xenidc_buffer_resource_provider * provider,
void ** mapping
)
{
trace();
{
xenidc_grant_table_mapping_context * context =
xenidc_buffer_resource_provider_allocate_page( provider );
struct gnttab_map_grant_ref map
[ XENIDC_REMOTE_BUFFER_REFERENCE_GRANT_TABLE_REFERENCE_COUNT ];
unsigned long first_page = rbr->byte_offset / PAGE_SIZE;
unsigned long final_page =
( rbr->byte_offset + rbr->byte_count - 1 ) / PAGE_SIZE;
context->class = class;
context->provider = provider;
context->page_count = final_page - first_page + 1;
context->mmap_vaddress =
xenidc_buffer_resource_provider_allocate_empty_page_range
( provider, context->page_count );
{
int i;
for( i = 0; i < context->page_count; i++ )
{
map[ i ].host_addr =
context->mmap_vaddress + ( i * PAGE_SIZE );
map[ i ].dom =
xenidc_address_query_remote_domain_id( address );
map[ i ].ref =
rbr->base.grant_table.reference[ first_page + i ];
map[ i ].flags = GNTMAP_host_map;
}
}
{
int error = HYPERVISOR_grant_table_op
( GNTTABOP_map_grant_ref, map, context->page_count );
BUG_ON( error );
}
{
int error = 0;
{
int i;
for( i = 0; i < context->page_count; i++ )
{
context->handle[ i ] = map[ i ].handle;
if( unlikely( map[ i ].handle < 0 ) )
{
error = 1;
}
}
}
if( !error )
{
int i;
for( i = 0; i < context->page_count; i++ )
{
phys_to_machine_mapping
[
__pa( context->mmap_vaddress + ( i *
PAGE_SIZE ) )
>>
PAGE_SHIFT
]
=
FOREIGN_FRAME( map[ i ].dev_bus_addr >>
PAGE_SHIFT );
}
}
else
{
xenidc_grant_table_unmap_rbr( &context->class );
context = NULL;
}
}
if( context != NULL )
{
*mapping =
(void *)( context->mmap_vaddress + ( rbr->byte_offset %
PAGE_SIZE ) );
return &context->class;
}
else
{
return NULL;
}
}
}
static void xenidc_grant_table_unmap_rbr
( xenidc_buffer_mappable_class ** context_in )
{
trace();
{
xenidc_grant_table_mapping_context * context = container_of
( context_in, xenidc_grant_table_mapping_context, class );
{
struct gnttab_unmap_grant_ref unmap
[ XENIDC_REMOTE_BUFFER_REFERENCE_GRANT_TABLE_REFERENCE_COUNT ];
int i;
int j;
for( i = 0, j = 0; i < context->page_count; i++ )
{
if( context->handle[ i ] >= 0 )
{
unmap[ j ].host_addr =
context->mmap_vaddress + ( i * PAGE_SIZE );
unmap[ j ].dev_bus_addr = 0;
unmap[ j ].handle = context->handle[ i ];
j++;
}
}
if( j != 0 )
{
int error = HYPERVISOR_grant_table_op
( GNTTABOP_unmap_grant_ref, unmap, j );
BUG_ON( error );
}
}
xenidc_buffer_resource_provider_free_empty_page_range
( context->provider, context->mmap_vaddress );
xenidc_buffer_resource_provider_free_page
( context->provider, context );
}
}
> -- Keir
>
>
--
Harry Butterworth <harry@hebutterworth.freeserve.co.uk>
prev parent reply other threads:[~2005-11-06 16:18 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-11-06 12:24 Bug in use of grant tables in blkback.c error path? Harry Butterworth
2005-11-06 15:32 ` Keir Fraser
2005-11-06 16:18 ` Harry Butterworth [this message]
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=1131293900.18044.6.camel@localhost \
--to=harry@hebutterworth.freeserve.co.uk \
--cc=Keir.Fraser@cl.cam.ac.uk \
--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.