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.

liveupdate: auto unregister FLBs on file handler unregistration

To ensure that unregistration is always successful and doesn't leave
dangling resources, introduce auto-unregistration of FLBs: when a file
handler is unregistered, all FLBs associated with it are automatically
unregistered.

Introduce a new helper luo_flb_unregister_all() which unregisters all FLBs
linked to the given file handler.

Link: https://lore.kernel.org/20260327033335.696621-8-pasha.tatashin@soleen.com
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org>
Cc: David Matlack <dmatlack@google.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Samiullah Khawaja <skhawaja@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Pasha Tatashin and committed by
Andrew Morton
5ee1c7d6 118c3908

+60 -39
+2 -12
kernel/liveupdate/luo_file.c
··· 923 923 */ 924 924 int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh) 925 925 { 926 - int err = -EBUSY; 927 - 928 926 if (!liveupdate_enabled()) 929 927 return -EOPNOTSUPP; 930 928 931 929 liveupdate_test_unregister(fh); 932 930 933 - down_write(&luo_register_rwlock); 934 - if (!list_empty(&ACCESS_PRIVATE(fh, flb_list))) 935 - goto err_unlock; 936 - 931 + guard(rwsem_write)(&luo_register_rwlock); 932 + luo_flb_unregister_all(fh); 937 933 list_del(&ACCESS_PRIVATE(fh, list)); 938 - up_write(&luo_register_rwlock); 939 934 940 935 module_put(fh->ops->owner); 941 936 942 937 return 0; 943 - 944 - err_unlock: 945 - up_write(&luo_register_rwlock); 946 - liveupdate_test_register(fh); 947 - return err; 948 938 }
+57 -27
kernel/liveupdate/luo_flb.c
··· 318 318 luo_flb_file_finish_one(iter->flb); 319 319 } 320 320 321 + static void luo_flb_unregister_one(struct liveupdate_file_handler *fh, 322 + struct liveupdate_flb *flb) 323 + { 324 + struct luo_flb_private *private = luo_flb_get_private(flb); 325 + struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 326 + struct luo_flb_link *iter; 327 + bool found = false; 328 + 329 + /* Find and remove the link from the file handler's list */ 330 + list_for_each_entry(iter, flb_list, list) { 331 + if (iter->flb == flb) { 332 + list_del(&iter->list); 333 + kfree(iter); 334 + found = true; 335 + break; 336 + } 337 + } 338 + 339 + if (!found) { 340 + pr_warn("Failed to unregister FLB '%s': not found in file handler '%s'\n", 341 + flb->compatible, fh->compatible); 342 + return; 343 + } 344 + 345 + private->users--; 346 + 347 + /* 348 + * If this is the last file-handler with which we are registred, remove 349 + * from the global list. 350 + */ 351 + if (!private->users) { 352 + list_del_init(&private->list); 353 + luo_flb_global.count--; 354 + } 355 + } 356 + 357 + /** 358 + * luo_flb_unregister_all - Unregister all FLBs associated with a file handler. 359 + * @fh: The file handler whose FLBs should be unregistered. 360 + * 361 + * This function iterates through the list of FLBs associated with the given 362 + * file handler and unregisters them all one by one. 363 + */ 364 + void luo_flb_unregister_all(struct liveupdate_file_handler *fh) 365 + { 366 + struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 367 + struct luo_flb_link *iter, *tmp; 368 + 369 + if (!liveupdate_enabled()) 370 + return; 371 + 372 + lockdep_assert_held_write(&luo_register_rwlock); 373 + list_for_each_entry_safe(iter, tmp, flb_list, list) 374 + luo_flb_unregister_one(fh, iter->flb); 375 + } 376 + 321 377 /** 322 378 * liveupdate_register_flb - Associate an FLB with a file handler and register it globally. 323 379 * @fh: The file handler that will now depend on the FLB. ··· 482 426 int liveupdate_unregister_flb(struct liveupdate_file_handler *fh, 483 427 struct liveupdate_flb *flb) 484 428 { 485 - struct luo_flb_private *private = luo_flb_get_private(flb); 486 - struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 487 - struct luo_flb_link *iter; 488 - int err = -ENOENT; 489 - 490 429 if (!liveupdate_enabled()) 491 430 return -EOPNOTSUPP; 492 431 493 432 guard(rwsem_write)(&luo_register_rwlock); 494 433 495 - /* Find and remove the link from the file handler's list */ 496 - list_for_each_entry(iter, flb_list, list) { 497 - if (iter->flb == flb) { 498 - list_del(&iter->list); 499 - kfree(iter); 500 - err = 0; 501 - break; 502 - } 503 - } 504 - 505 - if (err) 506 - return err; 507 - 508 - private->users--; 509 - /* 510 - * If this is the last file-handler with which we are registred, remove 511 - * from the global list. 512 - */ 513 - if (!private->users) { 514 - list_del_init(&private->list); 515 - luo_flb_global.count--; 516 - } 434 + luo_flb_unregister_one(fh, flb); 517 435 518 436 return 0; 519 437 }
+1
kernel/liveupdate/luo_internal.h
··· 103 103 int luo_flb_file_preserve(struct liveupdate_file_handler *fh); 104 104 void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh); 105 105 void luo_flb_file_finish(struct liveupdate_file_handler *fh); 106 + void luo_flb_unregister_all(struct liveupdate_file_handler *fh); 106 107 int __init luo_flb_setup_outgoing(void *fdt); 107 108 int __init luo_flb_setup_incoming(void *fdt); 108 109 void luo_flb_serialize(void);