Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

test_kho: unpreserve memory in case of error

If there is an error half way through KHO memory preservation, we should
rollback and unpreserve everything that is partially preserved.

Link: https://lkml.kernel.org/r/20251101142325.1326536-6-pasha.tatashin@soleen.com
Co-developed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Cc: Alexander Graf <graf@amazon.com>
Cc: Changyuan Lyu <changyuanl@google.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Pratyush Yadav <pratyush@kernel.org>
Cc: Randy Dunlap <rdunlap@infradead.org>
Cc: Simon Horman <horms@kernel.org>
Cc: Tejun Heo <tj@kernel.org>
Cc: Zhu Yanjun <yanjun.zhu@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Pasha Tatashin and committed by
Andrew Morton
ce405ed5 f5bfd479

+73 -30
+73 -30
lib/test_kho.c
··· 33 33 unsigned int nr_folios; 34 34 struct folio **folios; 35 35 phys_addr_t *folios_info; 36 + struct kho_vmalloc folios_info_phys; 37 + int nr_folios_preserved; 36 38 struct folio *fdt; 37 39 __wsum csum; 38 40 }; 39 41 40 42 static struct kho_test_state kho_test_state; 41 43 42 - static int kho_test_save_data(struct kho_test_state *state, void *fdt) 44 + static void kho_test_unpreserve_data(struct kho_test_state *state) 43 45 { 44 - phys_addr_t *folios_info __free(kvfree) = NULL; 46 + for (int i = 0; i < state->nr_folios_preserved; i++) 47 + kho_unpreserve_folio(state->folios[i]); 48 + 49 + kho_unpreserve_vmalloc(&state->folios_info_phys); 50 + vfree(state->folios_info); 51 + } 52 + 53 + static int kho_test_preserve_data(struct kho_test_state *state) 54 + { 45 55 struct kho_vmalloc folios_info_phys; 46 - int err = 0; 56 + phys_addr_t *folios_info; 57 + int err; 47 58 48 59 folios_info = vmalloc_array(state->nr_folios, sizeof(*folios_info)); 49 60 if (!folios_info) ··· 62 51 63 52 err = kho_preserve_vmalloc(folios_info, &folios_info_phys); 64 53 if (err) 65 - return err; 54 + goto err_free_info; 55 + 56 + state->folios_info_phys = folios_info_phys; 57 + state->folios_info = folios_info; 66 58 67 59 for (int i = 0; i < state->nr_folios; i++) { 68 60 struct folio *folio = state->folios[i]; 69 61 unsigned int order = folio_order(folio); 70 62 71 63 folios_info[i] = virt_to_phys(folio_address(folio)) | order; 72 - 73 64 err = kho_preserve_folio(folio); 74 65 if (err) 75 - break; 66 + goto err_unpreserve; 67 + state->nr_folios_preserved++; 76 68 } 69 + 70 + return 0; 71 + 72 + err_unpreserve: 73 + /* 74 + * kho_test_unpreserve_data frees folio_info, bail out immediately to 75 + * avoid double free 76 + */ 77 + kho_test_unpreserve_data(state); 78 + return err; 79 + 80 + err_free_info: 81 + vfree(folios_info); 82 + return err; 83 + } 84 + 85 + static int kho_test_prepare_fdt(struct kho_test_state *state, ssize_t fdt_size) 86 + { 87 + const char compatible[] = KHO_TEST_COMPAT; 88 + unsigned int magic = KHO_TEST_MAGIC; 89 + void *fdt = folio_address(state->fdt); 90 + int err; 91 + 92 + err = fdt_create(fdt, fdt_size); 93 + err |= fdt_finish_reservemap(fdt); 94 + err |= fdt_begin_node(fdt, ""); 95 + err |= fdt_property(fdt, "compatible", compatible, sizeof(compatible)); 96 + err |= fdt_property(fdt, "magic", &magic, sizeof(magic)); 77 97 78 98 err |= fdt_begin_node(fdt, "data"); 79 99 err |= fdt_property(fdt, "nr_folios", &state->nr_folios, 80 100 sizeof(state->nr_folios)); 81 - err |= fdt_property(fdt, "folios_info", &folios_info_phys, 82 - sizeof(folios_info_phys)); 101 + err |= fdt_property(fdt, "folios_info", &state->folios_info_phys, 102 + sizeof(state->folios_info_phys)); 83 103 err |= fdt_property(fdt, "csum", &state->csum, sizeof(state->csum)); 84 104 err |= fdt_end_node(fdt); 85 105 86 - if (!err) 87 - state->folios_info = no_free_ptr(folios_info); 106 + err |= fdt_end_node(fdt); 107 + err |= fdt_finish(fdt); 88 108 89 109 return err; 90 110 } 91 111 92 - static int kho_test_prepare_fdt(struct kho_test_state *state) 112 + static int kho_test_preserve(struct kho_test_state *state) 93 113 { 94 - const char compatible[] = KHO_TEST_COMPAT; 95 - unsigned int magic = KHO_TEST_MAGIC; 96 114 ssize_t fdt_size; 97 - int err = 0; 98 - void *fdt; 115 + int err; 99 116 100 117 fdt_size = state->nr_folios * sizeof(phys_addr_t) + PAGE_SIZE; 101 118 state->fdt = folio_alloc(GFP_KERNEL, get_order(fdt_size)); 102 119 if (!state->fdt) 103 120 return -ENOMEM; 104 121 105 - fdt = folio_address(state->fdt); 122 + err = kho_preserve_folio(state->fdt); 123 + if (err) 124 + goto err_free_fdt; 106 125 107 - err |= kho_preserve_folio(state->fdt); 108 - err |= fdt_create(fdt, fdt_size); 109 - err |= fdt_finish_reservemap(fdt); 126 + err = kho_test_preserve_data(state); 127 + if (err) 128 + goto err_unpreserve_fdt; 110 129 111 - err |= fdt_begin_node(fdt, ""); 112 - err |= fdt_property(fdt, "compatible", compatible, sizeof(compatible)); 113 - err |= fdt_property(fdt, "magic", &magic, sizeof(magic)); 114 - err |= kho_test_save_data(state, fdt); 115 - err |= fdt_end_node(fdt); 116 - 117 - err |= fdt_finish(fdt); 130 + err = kho_test_prepare_fdt(state, fdt_size); 131 + if (err) 132 + goto err_unpreserve_data; 118 133 119 134 err = kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt)); 120 135 if (err) 121 - folio_put(state->fdt); 136 + goto err_unpreserve_data; 122 137 138 + return 0; 139 + 140 + err_unpreserve_data: 141 + kho_test_unpreserve_data(state); 142 + err_unpreserve_fdt: 143 + kho_unpreserve_folio(state->fdt); 144 + err_free_fdt: 145 + folio_put(state->fdt); 123 146 return err; 124 147 } 125 148 ··· 219 174 if (err) 220 175 goto err_free_folios; 221 176 222 - err = kho_test_prepare_fdt(state); 177 + err = kho_test_preserve(state); 223 178 if (err) 224 179 goto err_free_folios; 225 180 226 181 return 0; 227 182 228 - err_free_fdt: 229 - folio_put(state->fdt); 230 183 err_free_folios: 231 184 kvfree(folios); 232 185 return err;