block.c (0978623e0f485266b015f533e76f2efab0769100) | block.c (3bb0e2980a96db6276e5032dcb2ccbf41f699b59) |
---|---|
1/* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights --- 2259 unchanged lines hidden (view full) --- 2268 .clean = g_free, 2269}; 2270 2271/* 2272 * bdrv_replace_child_safe 2273 * 2274 * Note: real unref of old_bs is done only on commit. 2275 */ | 1/* 2 * QEMU System Emulator block driver 3 * 4 * Copyright (c) 2003 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights --- 2259 unchanged lines hidden (view full) --- 2268 .clean = g_free, 2269}; 2270 2271/* 2272 * bdrv_replace_child_safe 2273 * 2274 * Note: real unref of old_bs is done only on commit. 2275 */ |
2276__attribute__((unused)) | |
2277static void bdrv_replace_child_safe(BdrvChild *child, BlockDriverState *new_bs, 2278 Transaction *tran) 2279{ 2280 BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1); 2281 *s = (BdrvReplaceChildState) { 2282 .child = child, 2283 .old_bs = child->bs, 2284 }; --- 2587 unchanged lines hidden (view full) --- 4872 * With auto_skip=false the error is returned if from has a parent which should 4873 * not be updated. 4874 */ 4875static int bdrv_replace_node_common(BlockDriverState *from, 4876 BlockDriverState *to, 4877 bool auto_skip, Error **errp) 4878{ 4879 BdrvChild *c, *next; | 2276static void bdrv_replace_child_safe(BdrvChild *child, BlockDriverState *new_bs, 2277 Transaction *tran) 2278{ 2279 BdrvReplaceChildState *s = g_new(BdrvReplaceChildState, 1); 2280 *s = (BdrvReplaceChildState) { 2281 .child = child, 2282 .old_bs = child->bs, 2283 }; --- 2587 unchanged lines hidden (view full) --- 4871 * With auto_skip=false the error is returned if from has a parent which should 4872 * not be updated. 4873 */ 4874static int bdrv_replace_node_common(BlockDriverState *from, 4875 BlockDriverState *to, 4876 bool auto_skip, Error **errp) 4877{ 4878 BdrvChild *c, *next; |
4880 GSList *list = NULL, *p; 4881 uint64_t perm = 0, shared = BLK_PERM_ALL; | 4879 Transaction *tran = tran_new(); 4880 g_autoptr(GHashTable) found = NULL; 4881 g_autoptr(GSList) refresh_list = NULL; |
4882 int ret; 4883 4884 /* Make sure that @from doesn't go away until we have successfully attached 4885 * all of its parents to @to. */ 4886 bdrv_ref(from); 4887 4888 assert(qemu_get_current_aio_context() == qemu_get_aio_context()); 4889 assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to)); 4890 bdrv_drained_begin(from); 4891 | 4882 int ret; 4883 4884 /* Make sure that @from doesn't go away until we have successfully attached 4885 * all of its parents to @to. */ 4886 bdrv_ref(from); 4887 4888 assert(qemu_get_current_aio_context() == qemu_get_aio_context()); 4889 assert(bdrv_get_aio_context(from) == bdrv_get_aio_context(to)); 4890 bdrv_drained_begin(from); 4891 |
4892 /* Put all parents into @list and calculate their cumulative permissions */ | 4892 /* 4893 * Do the replacement without permission update. 4894 * Replacement may influence the permissions, we should calculate new 4895 * permissions based on new graph. If we fail, we'll roll-back the 4896 * replacement. 4897 */ |
4893 QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) { 4894 assert(c->bs == from); 4895 if (!should_update_child(c, to)) { 4896 if (auto_skip) { 4897 continue; 4898 } 4899 ret = -EINVAL; 4900 error_setg(errp, "Should not change '%s' link to '%s'", 4901 c->name, from->node_name); 4902 goto out; 4903 } 4904 if (c->frozen) { 4905 ret = -EPERM; 4906 error_setg(errp, "Cannot change '%s' link to '%s'", 4907 c->name, from->node_name); 4908 goto out; 4909 } | 4898 QLIST_FOREACH_SAFE(c, &from->parents, next_parent, next) { 4899 assert(c->bs == from); 4900 if (!should_update_child(c, to)) { 4901 if (auto_skip) { 4902 continue; 4903 } 4904 ret = -EINVAL; 4905 error_setg(errp, "Should not change '%s' link to '%s'", 4906 c->name, from->node_name); 4907 goto out; 4908 } 4909 if (c->frozen) { 4910 ret = -EPERM; 4911 error_setg(errp, "Cannot change '%s' link to '%s'", 4912 c->name, from->node_name); 4913 goto out; 4914 } |
4910 list = g_slist_prepend(list, c); 4911 perm |= c->perm; 4912 shared &= c->shared_perm; | 4915 bdrv_replace_child_safe(c, to, tran); |
4913 } 4914 | 4916 } 4917 |
4915 /* Check whether the required permissions can be granted on @to, ignoring 4916 * all BdrvChild in @list so that they can't block themselves. */ 4917 ret = bdrv_check_update_perm(to, NULL, perm, shared, list, errp); | 4918 found = g_hash_table_new(NULL, NULL); 4919 4920 refresh_list = bdrv_topological_dfs(refresh_list, found, to); 4921 refresh_list = bdrv_topological_dfs(refresh_list, found, from); 4922 4923 ret = bdrv_list_refresh_perms(refresh_list, NULL, tran, errp); |
4918 if (ret < 0) { | 4924 if (ret < 0) { |
4919 bdrv_abort_perm_update(to); | |
4920 goto out; 4921 } 4922 | 4925 goto out; 4926 } 4927 |
4923 /* Now actually perform the change. We performed the permission check for 4924 * all elements of @list at once, so set the permissions all at once at the 4925 * very end. */ 4926 for (p = list; p != NULL; p = p->next) { 4927 c = p->data; 4928 4929 bdrv_ref(to); 4930 bdrv_replace_child_noperm(c, to); 4931 bdrv_unref(from); 4932 } 4933 4934 bdrv_set_perm(to); 4935 | |
4936 ret = 0; 4937 4938out: | 4928 ret = 0; 4929 4930out: |
4939 g_slist_free(list); | 4931 tran_finalize(tran, ret); 4932 |
4940 bdrv_drained_end(from); 4941 bdrv_unref(from); 4942 4943 return ret; 4944} 4945 4946int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, 4947 Error **errp) --- 2635 unchanged lines hidden --- | 4933 bdrv_drained_end(from); 4934 bdrv_unref(from); 4935 4936 return ret; 4937} 4938 4939int bdrv_replace_node(BlockDriverState *from, BlockDriverState *to, 4940 Error **errp) --- 2635 unchanged lines hidden --- |