block: Inactivate all children
Currently we only inactivate the top BDS. Actually bdrv_inactivate should be the opposite of bdrv_invalidate_cache. Recurse into the whole subtree instead. Because a node may have multiple parents, and because once BDRV_O_INACTIVE is set for a node, further writes are not allowed, we cannot interleave flag settings and .bdrv_inactivate calls (that may submit write to other nodes in a graph) within a single pass. Therefore two passes are used here. Signed-off-by: Fam Zheng <famz@redhat.com> Signed-off-by: Kevin Wolf <kwolf@redhat.com>
This commit is contained in:
		
							parent
							
								
									c9e9e9c66c
								
							
						
					
					
						commit
						aad0b7a0bf
					
				
							
								
								
									
										47
									
								
								block.c
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								block.c
									
									
									
									
									
								
							@ -3255,38 +3255,63 @@ void bdrv_invalidate_cache_all(Error **errp)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int bdrv_inactivate(BlockDriverState *bs)
 | 
					static int bdrv_inactivate_recurse(BlockDriverState *bs,
 | 
				
			||||||
 | 
					                                   bool setting_flag)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    BdrvChild *child;
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bs->drv->bdrv_inactivate) {
 | 
					    if (!setting_flag && bs->drv->bdrv_inactivate) {
 | 
				
			||||||
        ret = bs->drv->bdrv_inactivate(bs);
 | 
					        ret = bs->drv->bdrv_inactivate(bs);
 | 
				
			||||||
        if (ret < 0) {
 | 
					        if (ret < 0) {
 | 
				
			||||||
            return ret;
 | 
					            return ret;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bs->open_flags |= BDRV_O_INACTIVE;
 | 
					    QLIST_FOREACH(child, &bs->children, next) {
 | 
				
			||||||
 | 
					        ret = bdrv_inactivate_recurse(child->bs, setting_flag);
 | 
				
			||||||
 | 
					        if (ret < 0) {
 | 
				
			||||||
 | 
					            return ret;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (setting_flag) {
 | 
				
			||||||
 | 
					        bs->open_flags |= BDRV_O_INACTIVE;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int bdrv_inactivate_all(void)
 | 
					int bdrv_inactivate_all(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BlockDriverState *bs = NULL;
 | 
					    BlockDriverState *bs = NULL;
 | 
				
			||||||
    int ret;
 | 
					    int ret = 0;
 | 
				
			||||||
 | 
					    int pass;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while ((bs = bdrv_next(bs)) != NULL) {
 | 
					    while ((bs = bdrv_next(bs)) != NULL) {
 | 
				
			||||||
        AioContext *aio_context = bdrv_get_aio_context(bs);
 | 
					        aio_context_acquire(bdrv_get_aio_context(bs));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        aio_context_acquire(aio_context);
 | 
					    /* We do two passes of inactivation. The first pass calls to drivers'
 | 
				
			||||||
        ret = bdrv_inactivate(bs);
 | 
					     * .bdrv_inactivate callbacks recursively so all cache is flushed to disk;
 | 
				
			||||||
        aio_context_release(aio_context);
 | 
					     * the second pass sets the BDRV_O_INACTIVE flag so that no further write
 | 
				
			||||||
        if (ret < 0) {
 | 
					     * is allowed. */
 | 
				
			||||||
            return ret;
 | 
					    for (pass = 0; pass < 2; pass++) {
 | 
				
			||||||
 | 
					        bs = NULL;
 | 
				
			||||||
 | 
					        while ((bs = bdrv_next(bs)) != NULL) {
 | 
				
			||||||
 | 
					            ret = bdrv_inactivate_recurse(bs, pass);
 | 
				
			||||||
 | 
					            if (ret < 0) {
 | 
				
			||||||
 | 
					                goto out;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					out:
 | 
				
			||||||
 | 
					    bs = NULL;
 | 
				
			||||||
 | 
					    while ((bs = bdrv_next(bs)) != NULL) {
 | 
				
			||||||
 | 
					        aio_context_release(bdrv_get_aio_context(bs));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**************************************************************/
 | 
					/**************************************************************/
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user