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: protect FLB lists with luo_register_rwlock

Because liveupdate FLB objects will soon drop their persistent module
references when registered, list traversals must be protected against
concurrent module unloading.

To provide this protection, utilize the global luo_register_rwlock. It
protects the global registry of FLBs and the handler's specific list of
FLB dependencies.

Read locks are used during concurrent list traversals (e.g., during
preservation and serialization). Write locks are taken during
registration and unregistration.

Link: https://lore.kernel.org/20260327033335.696621-5-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
6b2b22f7 9e1e1858

+15
+1
include/linux/liveupdate.h
··· 12 12 #include <linux/kho/abi/luo.h> 13 13 #include <linux/list.h> 14 14 #include <linux/mutex.h> 15 + #include <linux/rwsem.h> 15 16 #include <linux/types.h> 16 17 #include <uapi/linux/liveupdate.h> 17 18
+14
kernel/liveupdate/luo_flb.c
··· 245 245 struct luo_flb_link *iter; 246 246 int err = 0; 247 247 248 + down_read(&luo_register_rwlock); 248 249 list_for_each_entry(iter, flb_list, list) { 249 250 err = luo_flb_file_preserve_one(iter->flb); 250 251 if (err) 251 252 goto exit_err; 252 253 } 254 + up_read(&luo_register_rwlock); 253 255 254 256 return 0; 255 257 256 258 exit_err: 257 259 list_for_each_entry_continue_reverse(iter, flb_list, list) 258 260 luo_flb_file_unpreserve_one(iter->flb); 261 + up_read(&luo_register_rwlock); 259 262 260 263 return err; 261 264 } ··· 280 277 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 281 278 struct luo_flb_link *iter; 282 279 280 + guard(rwsem_read)(&luo_register_rwlock); 283 281 list_for_each_entry_reverse(iter, flb_list, list) 284 282 luo_flb_file_unpreserve_one(iter->flb); 285 283 } ··· 301 297 struct list_head *flb_list = &ACCESS_PRIVATE(fh, flb_list); 302 298 struct luo_flb_link *iter; 303 299 300 + guard(rwsem_read)(&luo_register_rwlock); 304 301 list_for_each_entry_reverse(iter, flb_list, list) 305 302 luo_flb_file_finish_one(iter->flb); 306 303 } ··· 365 360 if (!luo_session_quiesce()) 366 361 return -EBUSY; 367 362 363 + down_write(&luo_register_rwlock); 364 + 368 365 /* Check that this FLB is not already linked to this file handler */ 369 366 err = -EEXIST; 370 367 list_for_each_entry(iter, flb_list, list) { ··· 408 401 private->users++; 409 402 link->flb = flb; 410 403 list_add_tail(&no_free_ptr(link)->list, flb_list); 404 + up_write(&luo_register_rwlock); 411 405 luo_session_resume(); 412 406 413 407 return 0; 414 408 415 409 err_resume: 410 + up_write(&luo_register_rwlock); 416 411 luo_session_resume(); 417 412 return err; 418 413 } ··· 458 449 if (!luo_session_quiesce()) 459 450 return -EBUSY; 460 451 452 + down_write(&luo_register_rwlock); 453 + 461 454 /* Find and remove the link from the file handler's list */ 462 455 list_for_each_entry(iter, flb_list, list) { 463 456 if (iter->flb == flb) { ··· 484 473 module_put(flb->ops->owner); 485 474 } 486 475 476 + up_write(&luo_register_rwlock); 487 477 luo_session_resume(); 488 478 489 479 return 0; 490 480 491 481 err_resume: 482 + up_write(&luo_register_rwlock); 492 483 luo_session_resume(); 493 484 return err; 494 485 } ··· 656 643 struct liveupdate_flb *gflb; 657 644 int i = 0; 658 645 646 + guard(rwsem_read)(&luo_register_rwlock); 659 647 list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) { 660 648 struct luo_flb_private *private = luo_flb_get_private(gflb); 661 649