diff options
| author | Matthew Wilcox <willy@infradead.org> | 2019-01-02 13:57:03 -0500 |
|---|---|---|
| committer | Matthew Wilcox <willy@infradead.org> | 2019-01-06 22:12:58 -0500 |
| commit | b0606fed6eece16a421034eca0bbea9a08b90e91 (patch) | |
| tree | f705b58760a60fce2d6f03a934a5038154505c1b /include/linux/xarray.h | |
| parent | 76b4e52995654af260f14558e0e07b5b039ae202 (diff) | |
XArray: Honour reserved entries in xa_insert
xa_insert() should treat reserved entries as occupied, not as available.
Also, it should treat requests to insert a NULL pointer as a request
to reserve the slot. Add xa_insert_bh() and xa_insert_irq() for
completeness.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Diffstat (limited to 'include/linux/xarray.h')
| -rw-r--r-- | include/linux/xarray.h | 110 |
1 files changed, 71 insertions, 39 deletions
diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 435c25b29079..12244aa98a69 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h | |||
| @@ -463,40 +463,13 @@ void *__xa_erase(struct xarray *, unsigned long index); | |||
| 463 | void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); | 463 | void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t); |
| 464 | void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old, | 464 | void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old, |
| 465 | void *entry, gfp_t); | 465 | void *entry, gfp_t); |
| 466 | int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t); | ||
| 466 | int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t); | 467 | int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t); |
| 467 | int __xa_reserve(struct xarray *, unsigned long index, gfp_t); | 468 | int __xa_reserve(struct xarray *, unsigned long index, gfp_t); |
| 468 | void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); | 469 | void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t); |
| 469 | void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); | 470 | void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t); |
| 470 | 471 | ||
| 471 | /** | 472 | /** |
| 472 | * __xa_insert() - Store this entry in the XArray unless another entry is | ||
| 473 | * already present. | ||
| 474 | * @xa: XArray. | ||
| 475 | * @index: Index into array. | ||
| 476 | * @entry: New entry. | ||
| 477 | * @gfp: Memory allocation flags. | ||
| 478 | * | ||
| 479 | * If you would rather see the existing entry in the array, use __xa_cmpxchg(). | ||
| 480 | * This function is for users who don't care what the entry is, only that | ||
| 481 | * one is present. | ||
| 482 | * | ||
| 483 | * Context: Any context. Expects xa_lock to be held on entry. May | ||
| 484 | * release and reacquire xa_lock if the @gfp flags permit. | ||
| 485 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. | ||
| 486 | * -ENOMEM if memory could not be allocated. | ||
| 487 | */ | ||
| 488 | static inline int __xa_insert(struct xarray *xa, unsigned long index, | ||
| 489 | void *entry, gfp_t gfp) | ||
| 490 | { | ||
| 491 | void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp); | ||
| 492 | if (!curr) | ||
| 493 | return 0; | ||
| 494 | if (xa_is_err(curr)) | ||
| 495 | return xa_err(curr); | ||
| 496 | return -EEXIST; | ||
| 497 | } | ||
| 498 | |||
| 499 | /** | ||
| 500 | * xa_store_bh() - Store this entry in the XArray. | 473 | * xa_store_bh() - Store this entry in the XArray. |
| 501 | * @xa: XArray. | 474 | * @xa: XArray. |
| 502 | * @index: Index into array. | 475 | * @index: Index into array. |
| @@ -685,24 +658,83 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index, | |||
| 685 | * @entry: New entry. | 658 | * @entry: New entry. |
| 686 | * @gfp: Memory allocation flags. | 659 | * @gfp: Memory allocation flags. |
| 687 | * | 660 | * |
| 688 | * If you would rather see the existing entry in the array, use xa_cmpxchg(). | 661 | * Inserting a NULL entry will store a reserved entry (like xa_reserve()) |
| 689 | * This function is for users who don't care what the entry is, only that | 662 | * if no entry is present. Inserting will fail if a reserved entry is |
| 690 | * one is present. | 663 | * present, even though loading from this index will return NULL. |
| 691 | * | 664 | * |
| 692 | * Context: Process context. Takes and releases the xa_lock. | 665 | * Context: Any context. Takes and releases the xa_lock. May sleep if |
| 693 | * May sleep if the @gfp flags permit. | 666 | * the @gfp flags permit. |
| 694 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. | 667 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. |
| 695 | * -ENOMEM if memory could not be allocated. | 668 | * -ENOMEM if memory could not be allocated. |
| 696 | */ | 669 | */ |
| 697 | static inline int xa_insert(struct xarray *xa, unsigned long index, | 670 | static inline int xa_insert(struct xarray *xa, unsigned long index, |
| 698 | void *entry, gfp_t gfp) | 671 | void *entry, gfp_t gfp) |
| 699 | { | 672 | { |
| 700 | void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp); | 673 | int err; |
| 701 | if (!curr) | 674 | |
| 702 | return 0; | 675 | xa_lock(xa); |
| 703 | if (xa_is_err(curr)) | 676 | err = __xa_insert(xa, index, entry, gfp); |
| 704 | return xa_err(curr); | 677 | xa_unlock(xa); |
| 705 | return -EEXIST; | 678 | |
| 679 | return err; | ||
| 680 | } | ||
| 681 | |||
| 682 | /** | ||
| 683 | * xa_insert_bh() - Store this entry in the XArray unless another entry is | ||
| 684 | * already present. | ||
| 685 | * @xa: XArray. | ||
| 686 | * @index: Index into array. | ||
| 687 | * @entry: New entry. | ||
| 688 | * @gfp: Memory allocation flags. | ||
| 689 | * | ||
| 690 | * Inserting a NULL entry will store a reserved entry (like xa_reserve()) | ||
| 691 | * if no entry is present. Inserting will fail if a reserved entry is | ||
| 692 | * present, even though loading from this index will return NULL. | ||
| 693 | * | ||
| 694 | * Context: Any context. Takes and releases the xa_lock while | ||
| 695 | * disabling softirqs. May sleep if the @gfp flags permit. | ||
| 696 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. | ||
| 697 | * -ENOMEM if memory could not be allocated. | ||
| 698 | */ | ||
| 699 | static inline int xa_insert_bh(struct xarray *xa, unsigned long index, | ||
| 700 | void *entry, gfp_t gfp) | ||
| 701 | { | ||
| 702 | int err; | ||
| 703 | |||
| 704 | xa_lock_bh(xa); | ||
| 705 | err = __xa_insert(xa, index, entry, gfp); | ||
| 706 | xa_unlock_bh(xa); | ||
| 707 | |||
| 708 | return err; | ||
| 709 | } | ||
| 710 | |||
| 711 | /** | ||
| 712 | * xa_insert_irq() - Store this entry in the XArray unless another entry is | ||
| 713 | * already present. | ||
| 714 | * @xa: XArray. | ||
| 715 | * @index: Index into array. | ||
| 716 | * @entry: New entry. | ||
| 717 | * @gfp: Memory allocation flags. | ||
| 718 | * | ||
| 719 | * Inserting a NULL entry will store a reserved entry (like xa_reserve()) | ||
| 720 | * if no entry is present. Inserting will fail if a reserved entry is | ||
| 721 | * present, even though loading from this index will return NULL. | ||
| 722 | * | ||
| 723 | * Context: Process context. Takes and releases the xa_lock while | ||
| 724 | * disabling interrupts. May sleep if the @gfp flags permit. | ||
| 725 | * Return: 0 if the store succeeded. -EEXIST if another entry was present. | ||
| 726 | * -ENOMEM if memory could not be allocated. | ||
| 727 | */ | ||
| 728 | static inline int xa_insert_irq(struct xarray *xa, unsigned long index, | ||
| 729 | void *entry, gfp_t gfp) | ||
| 730 | { | ||
| 731 | int err; | ||
| 732 | |||
| 733 | xa_lock_irq(xa); | ||
| 734 | err = __xa_insert(xa, index, entry, gfp); | ||
| 735 | xa_unlock_irq(xa); | ||
| 736 | |||
| 737 | return err; | ||
| 706 | } | 738 | } |
| 707 | 739 | ||
| 708 | /** | 740 | /** |
