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

xarray: make xa_alloc_cyclic() return 0 on all success cases

Change xa_alloc_cyclic() to return 0 even on wrap-around. Do the same for
xa_alloc_cyclic_irq() and xa_alloc_cyclic_bh().

This will prevent any future bug of treating return of 1 as an error:
int ret = xa_alloc_cyclic(...)
if (ret) // currently mishandles ret==1
goto failure;

If there will be someone interested in when wrap-around occurs, there is
still __xa_alloc_cyclic() that behaves as before. For now there is no
such user.

Link: https://lkml.kernel.org/r/20250320102219.8101-1-przemyslaw.kitszel@intel.com
Signed-off-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Suggested-by: Matthew Wilcox <willy@infradead.org>
Link: https://lore.kernel.org/netdev/Z9gUd-5t8b5NX2wE@casper.infradead.org
Cc: Andriy Shevchenko <andriy.shevchenko@intel.com>
Cc: Dave Hansen <dave.hansen@intel.com>
Cc: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
Cc: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Przemek Kitszel and committed by
Andrew Morton
4c97a17a dbb9c166

+30 -11
+15 -9
include/linux/xarray.h
··· 965 965 * Must only be operated on an xarray initialized with flag XA_FLAGS_ALLOC set 966 966 * in xa_init_flags(). 967 967 * 968 + * Note that callers interested in whether wrapping has occurred should 969 + * use __xa_alloc_cyclic() instead. 970 + * 968 971 * Context: Any context. Takes and releases the xa_lock. May sleep if 969 972 * the @gfp flags permit. 970 - * Return: 0 if the allocation succeeded without wrapping. 1 if the 971 - * allocation succeeded after wrapping, -ENOMEM if memory could not be 973 + * Return: 0 if the allocation succeeded, -ENOMEM if memory could not be 972 974 * allocated or -EBUSY if there are no free entries in @limit. 973 975 */ 974 976 static inline int xa_alloc_cyclic(struct xarray *xa, u32 *id, void *entry, ··· 983 981 err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); 984 982 xa_unlock(xa); 985 983 986 - return err; 984 + return err < 0 ? err : 0; 987 985 } 988 986 989 987 /** ··· 1004 1002 * Must only be operated on an xarray initialized with flag XA_FLAGS_ALLOC set 1005 1003 * in xa_init_flags(). 1006 1004 * 1005 + * Note that callers interested in whether wrapping has occurred should 1006 + * use __xa_alloc_cyclic() instead. 1007 + * 1007 1008 * Context: Any context. Takes and releases the xa_lock while 1008 1009 * disabling softirqs. May sleep if the @gfp flags permit. 1009 - * Return: 0 if the allocation succeeded without wrapping. 1 if the 1010 - * allocation succeeded after wrapping, -ENOMEM if memory could not be 1010 + * Return: 0 if the allocation succeeded, -ENOMEM if memory could not be 1011 1011 * allocated or -EBUSY if there are no free entries in @limit. 1012 1012 */ 1013 1013 static inline int xa_alloc_cyclic_bh(struct xarray *xa, u32 *id, void *entry, ··· 1022 1018 err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); 1023 1019 xa_unlock_bh(xa); 1024 1020 1025 - return err; 1021 + return err < 0 ? err : 0; 1026 1022 } 1027 1023 1028 1024 /** ··· 1043 1039 * Must only be operated on an xarray initialized with flag XA_FLAGS_ALLOC set 1044 1040 * in xa_init_flags(). 1045 1041 * 1042 + * Note that callers interested in whether wrapping has occurred should 1043 + * use __xa_alloc_cyclic() instead. 1044 + * 1046 1045 * Context: Process context. Takes and releases the xa_lock while 1047 1046 * disabling interrupts. May sleep if the @gfp flags permit. 1048 - * Return: 0 if the allocation succeeded without wrapping. 1 if the 1049 - * allocation succeeded after wrapping, -ENOMEM if memory could not be 1047 + * Return: 0 if the allocation succeeded, -ENOMEM if memory could not be 1050 1048 * allocated or -EBUSY if there are no free entries in @limit. 1051 1049 */ 1052 1050 static inline int xa_alloc_cyclic_irq(struct xarray *xa, u32 *id, void *entry, ··· 1061 1055 err = __xa_alloc_cyclic(xa, id, entry, limit, next, gfp); 1062 1056 xa_unlock_irq(xa); 1063 1057 1064 - return err; 1058 + return err < 0 ? err : 0; 1065 1059 } 1066 1060 1067 1061 /**
+15 -2
lib/test_xarray.c
··· 1040 1040 unsigned int i, id; 1041 1041 unsigned long index; 1042 1042 void *entry; 1043 + int ret; 1043 1044 1044 1045 XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(1), limit, 1045 1046 &next, GFP_KERNEL) != 0); ··· 1060 1059 else 1061 1060 entry = xa_mk_index(i - 0x3fff); 1062 1061 XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, entry, limit, 1063 - &next, GFP_KERNEL) != (id == 1)); 1062 + &next, GFP_KERNEL) != 0); 1064 1063 XA_BUG_ON(xa, xa_mk_index(id) != entry); 1065 1064 } 1066 1065 ··· 1073 1072 xa_limit_32b, &next, GFP_KERNEL) != 0); 1074 1073 XA_BUG_ON(xa, id != UINT_MAX); 1075 1074 XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base), 1076 - xa_limit_32b, &next, GFP_KERNEL) != 1); 1075 + xa_limit_32b, &next, GFP_KERNEL) != 0); 1077 1076 XA_BUG_ON(xa, id != base); 1078 1077 XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(base + 1), 1079 1078 xa_limit_32b, &next, GFP_KERNEL) != 0); ··· 1081 1080 1082 1081 xa_for_each(xa, index, entry) 1083 1082 xa_erase_index(xa, index); 1083 + XA_BUG_ON(xa, !xa_empty(xa)); 1084 1084 1085 + /* check wrap-around return of __xa_alloc_cyclic() */ 1086 + next = UINT_MAX; 1087 + XA_BUG_ON(xa, xa_alloc_cyclic(xa, &id, xa_mk_index(UINT_MAX), 1088 + xa_limit_32b, &next, GFP_KERNEL) != 0); 1089 + xa_lock(xa); 1090 + ret = __xa_alloc_cyclic(xa, &id, xa_mk_index(base), xa_limit_32b, 1091 + &next, GFP_KERNEL); 1092 + xa_unlock(xa); 1093 + XA_BUG_ON(xa, ret != 1); 1094 + xa_for_each(xa, index, entry) 1095 + xa_erase_index(xa, index); 1085 1096 XA_BUG_ON(xa, !xa_empty(xa)); 1086 1097 } 1087 1098