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

drivers: cacheinfo: use __free attribute instead of of_node_put()

Introduce the __free attribute for scope-based resource management.
Resources allocated with __free are automatically released at the end of
the scope. This enhancement aims to mitigate memory management issues
associated with forgetting to release resources by utilizing __free
instead of of_node_put().

To introduce this feature, some modifications to the code structure were
necessary. The original pattern:
```
prev = np;
while(...) {
[...]
np = of_find_next_cache_node(np);
of_node_put(prev);
prev = np;
[...]
}
```
has been updated to:
```
while(...) {
[...]
struct device_node __free(device_node) *prev = np;
np = of_find_next_cache_node(np)
[...]
}
```
With this change, the previous node is automatically cleaned up at the end
of each iteration, allowing the elimination of all of_node_put() calls and
some goto statements.

Suggested-by: Julia Lawall <julia.lawall@inria.fr>
Signed-off-by: Vincenzo Mezzela <vincenzo.mezzela@gmail.com>
Link: https://lore.kernel.org/r/20240719151335.869145-1-vincenzo.mezzela@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Vincenzo Mezzela and committed by
Greg Kroah-Hartman
1b48fbbc 30b968b0

+13 -28
+13 -28
drivers/base/cacheinfo.c
··· 202 202 203 203 static int cache_setup_of_node(unsigned int cpu) 204 204 { 205 - struct device_node *np, *prev; 206 205 struct cacheinfo *this_leaf; 207 206 unsigned int index = 0; 208 207 209 - np = of_cpu_device_node_get(cpu); 208 + struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu); 210 209 if (!np) { 211 210 pr_err("Failed to find cpu%d device node\n", cpu); 212 211 return -ENOENT; 213 212 } 214 213 215 214 if (!of_check_cache_nodes(np)) { 216 - of_node_put(np); 217 215 return -ENOENT; 218 216 } 219 - 220 - prev = np; 221 217 222 218 while (index < cache_leaves(cpu)) { 223 219 this_leaf = per_cpu_cacheinfo_idx(cpu, index); 224 220 if (this_leaf->level != 1) { 221 + struct device_node *prev __free(device_node) = np; 225 222 np = of_find_next_cache_node(np); 226 - of_node_put(prev); 227 - prev = np; 228 223 if (!np) 229 224 break; 230 225 } ··· 227 232 this_leaf->fw_token = np; 228 233 index++; 229 234 } 230 - 231 - of_node_put(np); 232 235 233 236 if (index != cache_leaves(cpu)) /* not all OF nodes populated */ 234 237 return -ENOENT; ··· 236 243 237 244 static bool of_check_cache_nodes(struct device_node *np) 238 245 { 239 - struct device_node *next; 240 - 241 246 if (of_property_present(np, "cache-size") || 242 247 of_property_present(np, "i-cache-size") || 243 248 of_property_present(np, "d-cache-size") || 244 249 of_property_present(np, "cache-unified")) 245 250 return true; 246 251 247 - next = of_find_next_cache_node(np); 252 + struct device_node *next __free(device_node) = of_find_next_cache_node(np); 248 253 if (next) { 249 - of_node_put(next); 250 254 return true; 251 255 } 252 256 ··· 277 287 int init_of_cache_level(unsigned int cpu) 278 288 { 279 289 struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); 280 - struct device_node *np = of_cpu_device_node_get(cpu); 281 - struct device_node *prev = NULL; 290 + struct device_node *np __free(device_node) = of_cpu_device_node_get(cpu); 282 291 unsigned int levels = 0, leaves, level; 283 292 284 293 if (!of_check_cache_nodes(np)) { 285 - of_node_put(np); 286 294 return -ENOENT; 287 295 } 288 296 ··· 288 300 if (leaves > 0) 289 301 levels = 1; 290 302 291 - prev = np; 292 - while ((np = of_find_next_cache_node(np))) { 293 - of_node_put(prev); 294 - prev = np; 303 + while (1) { 304 + struct device_node *prev __free(device_node) = np; 305 + np = of_find_next_cache_node(np); 306 + if (!np) 307 + break; 308 + 295 309 if (!of_device_is_compatible(np, "cache")) 296 - goto err_out; 310 + return -EINVAL; 297 311 if (of_property_read_u32(np, "cache-level", &level)) 298 - goto err_out; 312 + return -EINVAL; 299 313 if (level <= levels) 300 - goto err_out; 314 + return -EINVAL; 301 315 302 316 leaves += of_count_cache_leaves(np); 303 317 levels = level; 304 318 } 305 319 306 - of_node_put(np); 307 320 this_cpu_ci->num_levels = levels; 308 321 this_cpu_ci->num_leaves = leaves; 309 322 310 323 return 0; 311 - 312 - err_out: 313 - of_node_put(np); 314 - return -EINVAL; 315 324 } 316 325 317 326 #else