Skip to content

Commit d2850ff

Browse files
dmatlackrppt
authored andcommitted
liveupdate: Use refcount_t for FLB reference counts
Use refcount_t instead of a raw integer to keep track of references on incoming and outgoing FLBs. Using refcount_t provides protection from overflow, underflow, and other issues. Fixes: cab056f ("liveupdate: luo_flb: introduce File-Lifecycle-Bound global state") Signed-off-by: David Matlack <dmatlack@google.com> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Link: https://lore.kernel.org/r/20260423174032.3140399-2-dmatlack@google.com Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com> Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
1 parent a1f8ed3 commit d2850ff

2 files changed

Lines changed: 12 additions & 13 deletions

File tree

include/linux/liveupdate.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <linux/kho/abi/luo.h>
1313
#include <linux/list.h>
1414
#include <linux/mutex.h>
15+
#include <linux/refcount.h>
1516
#include <linux/rwsem.h>
1617
#include <linux/types.h>
1718
#include <uapi/linux/liveupdate.h>
@@ -175,7 +176,7 @@ struct liveupdate_flb_ops {
175176
* @retrieved: True once the FLB's retrieve() callback has run.
176177
*/
177178
struct luo_flb_private_state {
178-
long count;
179+
refcount_t count;
179180
u64 data;
180181
void *obj;
181182
struct mutex lock;

kernel/liveupdate/luo_flb.c

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
111111
struct luo_flb_private *private = luo_flb_get_private(flb);
112112

113113
scoped_guard(mutex, &private->outgoing.lock) {
114-
if (!private->outgoing.count) {
114+
if (!refcount_read(&private->outgoing.count)) {
115115
struct liveupdate_flb_op_args args = {0};
116116
int err;
117117

@@ -126,8 +126,10 @@ static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
126126
}
127127
private->outgoing.data = args.data;
128128
private->outgoing.obj = args.obj;
129+
refcount_set(&private->outgoing.count, 1);
130+
} else {
131+
refcount_inc(&private->outgoing.count);
129132
}
130-
private->outgoing.count++;
131133
}
132134

133135
return 0;
@@ -138,8 +140,7 @@ static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
138140
struct luo_flb_private *private = luo_flb_get_private(flb);
139141

140142
scoped_guard(mutex, &private->outgoing.lock) {
141-
private->outgoing.count--;
142-
if (!private->outgoing.count) {
143+
if (refcount_dec_and_test(&private->outgoing.count)) {
143144
struct liveupdate_flb_op_args args = {0};
144145

145146
args.flb = flb;
@@ -178,7 +179,7 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
178179
for (int i = 0; i < fh->header_ser->count; i++) {
179180
if (!strcmp(fh->ser[i].name, flb->compatible)) {
180181
private->incoming.data = fh->ser[i].data;
181-
private->incoming.count = fh->ser[i].count;
182+
refcount_set(&private->incoming.count, fh->ser[i].count);
182183
found = true;
183184
break;
184185
}
@@ -208,12 +209,8 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
208209
static void luo_flb_file_finish_one(struct liveupdate_flb *flb)
209210
{
210211
struct luo_flb_private *private = luo_flb_get_private(flb);
211-
u64 count;
212212

213-
scoped_guard(mutex, &private->incoming.lock)
214-
count = --private->incoming.count;
215-
216-
if (!count) {
213+
if (refcount_dec_and_test(&private->incoming.count)) {
217214
struct liveupdate_flb_op_args args = {0};
218215

219216
if (!private->incoming.retrieved) {
@@ -652,12 +649,13 @@ void luo_flb_serialize(void)
652649
guard(rwsem_read)(&luo_register_rwlock);
653650
list_private_for_each_entry(gflb, &luo_flb_global.list, private.list) {
654651
struct luo_flb_private *private = luo_flb_get_private(gflb);
652+
long count = refcount_read(&private->outgoing.count);
655653

656-
if (private->outgoing.count > 0) {
654+
if (count > 0) {
657655
strscpy(fh->ser[i].name, gflb->compatible,
658656
sizeof(fh->ser[i].name));
659657
fh->ser[i].data = private->outgoing.data;
660-
fh->ser[i].count = private->outgoing.count;
658+
fh->ser[i].count = count;
661659
i++;
662660
}
663661
}

0 commit comments

Comments
 (0)