Skip to content

Commit 4b22e20

Browse files
committed
Merge tag 'afs-fixes-20220802' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
Pull AFS fixes from David Howells: "Fix AFS refcount handling. The first patch converts afs to use refcount_t for its refcounts and the second patch fixes afs_put_call() and afs_put_server() to save the values they're going to log in the tracepoint before decrementing the refcount" * tag 'afs-fixes-20220802' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs: afs: Fix access after dec in put functions afs: Use refcount_t rather than atomic_t
2 parents 426b4ca + 2757a4d commit 4b22e20

File tree

9 files changed

+124
-116
lines changed

9 files changed

+124
-116
lines changed

fs/afs/cell.c

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ static struct afs_cell *afs_alloc_cell(struct afs_net *net,
158158
cell->name[i] = tolower(name[i]);
159159
cell->name[i] = 0;
160160

161-
atomic_set(&cell->ref, 1);
161+
refcount_set(&cell->ref, 1);
162162
atomic_set(&cell->active, 0);
163163
INIT_WORK(&cell->manager, afs_manage_cell_work);
164164
cell->volumes = RB_ROOT;
@@ -287,15 +287,15 @@ struct afs_cell *afs_lookup_cell(struct afs_net *net,
287287
cell = candidate;
288288
candidate = NULL;
289289
atomic_set(&cell->active, 2);
290-
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 2, afs_cell_trace_insert);
290+
trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 2, afs_cell_trace_insert);
291291
rb_link_node_rcu(&cell->net_node, parent, pp);
292292
rb_insert_color(&cell->net_node, &net->cells);
293293
up_write(&net->cells_lock);
294294

295295
afs_queue_cell(cell, afs_cell_trace_get_queue_new);
296296

297297
wait_for_cell:
298-
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), atomic_read(&cell->active),
298+
trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), atomic_read(&cell->active),
299299
afs_cell_trace_wait);
300300
_debug("wait_for_cell");
301301
wait_var_event(&cell->state,
@@ -490,13 +490,13 @@ static void afs_cell_destroy(struct rcu_head *rcu)
490490
{
491491
struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu);
492492
struct afs_net *net = cell->net;
493-
int u;
493+
int r;
494494

495495
_enter("%p{%s}", cell, cell->name);
496496

497-
u = atomic_read(&cell->ref);
498-
ASSERTCMP(u, ==, 0);
499-
trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), afs_cell_trace_free);
497+
r = refcount_read(&cell->ref);
498+
ASSERTCMP(r, ==, 0);
499+
trace_afs_cell(cell->debug_id, r, atomic_read(&cell->active), afs_cell_trace_free);
500500

501501
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
502502
afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias);
@@ -539,13 +539,10 @@ void afs_cells_timer(struct timer_list *timer)
539539
*/
540540
struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason)
541541
{
542-
int u;
542+
int r;
543543

544-
if (atomic_read(&cell->ref) <= 0)
545-
BUG();
546-
547-
u = atomic_inc_return(&cell->ref);
548-
trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), reason);
544+
__refcount_inc(&cell->ref, &r);
545+
trace_afs_cell(cell->debug_id, r + 1, atomic_read(&cell->active), reason);
549546
return cell;
550547
}
551548

@@ -556,12 +553,14 @@ void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason)
556553
{
557554
if (cell) {
558555
unsigned int debug_id = cell->debug_id;
559-
unsigned int u, a;
556+
unsigned int a;
557+
bool zero;
558+
int r;
560559

561560
a = atomic_read(&cell->active);
562-
u = atomic_dec_return(&cell->ref);
563-
trace_afs_cell(debug_id, u, a, reason);
564-
if (u == 0) {
561+
zero = __refcount_dec_and_test(&cell->ref, &r);
562+
trace_afs_cell(debug_id, r - 1, a, reason);
563+
if (zero) {
565564
a = atomic_read(&cell->active);
566565
WARN(a != 0, "Cell active count %u > 0\n", a);
567566
call_rcu(&cell->rcu, afs_cell_destroy);
@@ -574,14 +573,12 @@ void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason)
574573
*/
575574
struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason)
576575
{
577-
int u, a;
578-
579-
if (atomic_read(&cell->ref) <= 0)
580-
BUG();
576+
int r, a;
581577

582-
u = atomic_read(&cell->ref);
578+
r = refcount_read(&cell->ref);
579+
WARN_ON(r == 0);
583580
a = atomic_inc_return(&cell->active);
584-
trace_afs_cell(cell->debug_id, u, a, reason);
581+
trace_afs_cell(cell->debug_id, r, a, reason);
585582
return cell;
586583
}
587584

@@ -593,7 +590,7 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr
593590
{
594591
unsigned int debug_id;
595592
time64_t now, expire_delay;
596-
int u, a;
593+
int r, a;
597594

598595
if (!cell)
599596
return;
@@ -607,9 +604,9 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr
607604
expire_delay = afs_cell_gc_delay;
608605

609606
debug_id = cell->debug_id;
610-
u = atomic_read(&cell->ref);
607+
r = refcount_read(&cell->ref);
611608
a = atomic_dec_return(&cell->active);
612-
trace_afs_cell(debug_id, u, a, reason);
609+
trace_afs_cell(debug_id, r, a, reason);
613610
WARN_ON(a == 0);
614611
if (a == 1)
615612
/* 'cell' may now be garbage collected. */
@@ -621,11 +618,11 @@ void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_tr
621618
*/
622619
void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason)
623620
{
624-
int u, a;
621+
int r, a;
625622

626-
u = atomic_read(&cell->ref);
623+
r = refcount_read(&cell->ref);
627624
a = atomic_read(&cell->active);
628-
trace_afs_cell(cell->debug_id, u, a, reason);
625+
trace_afs_cell(cell->debug_id, r, a, reason);
629626
}
630627

631628
/*
@@ -739,7 +736,7 @@ static void afs_manage_cell(struct afs_cell *cell)
739736
active = 1;
740737
if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) {
741738
rb_erase(&cell->net_node, &net->cells);
742-
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 0,
739+
trace_afs_cell(cell->debug_id, refcount_read(&cell->ref), 0,
743740
afs_cell_trace_unuse_delete);
744741
smp_store_release(&cell->state, AFS_CELL_REMOVED);
745742
}
@@ -866,15 +863,15 @@ void afs_manage_cells(struct work_struct *work)
866863
bool sched_cell = false;
867864

868865
active = atomic_read(&cell->active);
869-
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
866+
trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
870867
active, afs_cell_trace_manage);
871868

872869
ASSERTCMP(active, >=, 1);
873870

874871
if (purging) {
875872
if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) {
876873
active = atomic_dec_return(&cell->active);
877-
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
874+
trace_afs_cell(cell->debug_id, refcount_read(&cell->ref),
878875
active, afs_cell_trace_unuse_pin);
879876
}
880877
}

fs/afs/cmservice.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,8 @@ static void SRXAFSCB_CallBack(struct work_struct *work)
212212
* to maintain cache coherency.
213213
*/
214214
if (call->server) {
215-
trace_afs_server(call->server,
216-
atomic_read(&call->server->ref),
215+
trace_afs_server(call->server->debug_id,
216+
refcount_read(&call->server->ref),
217217
atomic_read(&call->server->active),
218218
afs_server_trace_callback);
219219
afs_break_callbacks(call->server, call->count, call->request);

fs/afs/internal.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ struct afs_call {
122122
};
123123
struct afs_operation *op;
124124
unsigned int server_index;
125-
atomic_t usage;
125+
refcount_t ref;
126126
enum afs_call_state state;
127127
spinlock_t state_lock;
128128
int error; /* error code */
@@ -365,7 +365,7 @@ struct afs_cell {
365365
struct hlist_node proc_link; /* /proc cell list link */
366366
time64_t dns_expiry; /* Time AFSDB/SRV record expires */
367367
time64_t last_inactive; /* Time of last drop of usage count */
368-
atomic_t ref; /* Struct refcount */
368+
refcount_t ref; /* Struct refcount */
369369
atomic_t active; /* Active usage counter */
370370
unsigned long flags;
371371
#define AFS_CELL_FL_NO_GC 0 /* The cell was added manually, don't auto-gc */
@@ -410,7 +410,7 @@ struct afs_vlserver {
410410
#define AFS_VLSERVER_FL_IS_YFS 2 /* Server is YFS not AFS */
411411
#define AFS_VLSERVER_FL_RESPONDING 3 /* VL server is responding */
412412
rwlock_t lock; /* Lock on addresses */
413-
atomic_t usage;
413+
refcount_t ref;
414414
unsigned int rtt; /* Server's current RTT in uS */
415415

416416
/* Probe state */
@@ -446,7 +446,7 @@ struct afs_vlserver_entry {
446446

447447
struct afs_vlserver_list {
448448
struct rcu_head rcu;
449-
atomic_t usage;
449+
refcount_t ref;
450450
u8 nr_servers;
451451
u8 index; /* Server currently in use */
452452
u8 preferred; /* Preferred server */
@@ -517,7 +517,7 @@ struct afs_server {
517517
#define AFS_SERVER_FL_NO_IBULK 17 /* Fileserver doesn't support FS.InlineBulkStatus */
518518
#define AFS_SERVER_FL_NO_RM2 18 /* Fileserver doesn't support YFS.RemoveFile2 */
519519
#define AFS_SERVER_FL_HAS_FS64 19 /* Fileserver supports FS.{Fetch,Store}Data64 */
520-
atomic_t ref; /* Object refcount */
520+
refcount_t ref; /* Object refcount */
521521
atomic_t active; /* Active user count */
522522
u32 addr_version; /* Address list version */
523523
unsigned int rtt; /* Server's current RTT in uS */
@@ -571,7 +571,7 @@ struct afs_volume {
571571
struct rcu_head rcu;
572572
afs_volid_t vid; /* volume ID */
573573
};
574-
atomic_t usage;
574+
refcount_t ref;
575575
time64_t update_at; /* Time at which to next update */
576576
struct afs_cell *cell; /* Cell to which belongs (pins ref) */
577577
struct rb_node cell_node; /* Link in cell->volumes */
@@ -1493,14 +1493,14 @@ extern int afs_end_vlserver_operation(struct afs_vl_cursor *);
14931493
*/
14941494
static inline struct afs_vlserver *afs_get_vlserver(struct afs_vlserver *vlserver)
14951495
{
1496-
atomic_inc(&vlserver->usage);
1496+
refcount_inc(&vlserver->ref);
14971497
return vlserver;
14981498
}
14991499

15001500
static inline struct afs_vlserver_list *afs_get_vlserverlist(struct afs_vlserver_list *vllist)
15011501
{
15021502
if (vllist)
1503-
atomic_inc(&vllist->usage);
1503+
refcount_inc(&vllist->ref);
15041504
return vllist;
15051505
}
15061506

fs/afs/proc.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v)
4747

4848
/* display one cell per line on subsequent lines */
4949
seq_printf(m, "%3u %3u %6lld %2u %2u %s\n",
50-
atomic_read(&cell->ref),
50+
refcount_read(&cell->ref),
5151
atomic_read(&cell->active),
5252
cell->dns_expiry - ktime_get_real_seconds(),
5353
vllist ? vllist->nr_servers : 0,
@@ -217,7 +217,7 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
217217
}
218218

219219
seq_printf(m, "%3d %08llx %s %s\n",
220-
atomic_read(&vol->usage), vol->vid,
220+
refcount_read(&vol->ref), vol->vid,
221221
afs_vol_types[vol->type],
222222
vol->name);
223223

@@ -388,7 +388,7 @@ static int afs_proc_servers_show(struct seq_file *m, void *v)
388388
alist = rcu_dereference(server->addresses);
389389
seq_printf(m, "%pU %3d %3d\n",
390390
&server->uuid,
391-
atomic_read(&server->ref),
391+
refcount_read(&server->ref),
392392
atomic_read(&server->active));
393393
seq_printf(m, " - info: fl=%lx rtt=%u brk=%x\n",
394394
server->flags, server->rtt, server->cb_s_break);

fs/afs/rxrpc.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,14 @@ static struct afs_call *afs_alloc_call(struct afs_net *net,
145145
call->type = type;
146146
call->net = net;
147147
call->debug_id = atomic_inc_return(&rxrpc_debug_id);
148-
atomic_set(&call->usage, 1);
148+
refcount_set(&call->ref, 1);
149149
INIT_WORK(&call->async_work, afs_process_async_call);
150150
init_waitqueue_head(&call->waitq);
151151
spin_lock_init(&call->state_lock);
152152
call->iter = &call->def_iter;
153153

154154
o = atomic_inc_return(&net->nr_outstanding_calls);
155-
trace_afs_call(call, afs_call_trace_alloc, 1, o,
155+
trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o,
156156
__builtin_return_address(0));
157157
return call;
158158
}
@@ -163,14 +163,16 @@ static struct afs_call *afs_alloc_call(struct afs_net *net,
163163
void afs_put_call(struct afs_call *call)
164164
{
165165
struct afs_net *net = call->net;
166-
int n = atomic_dec_return(&call->usage);
167-
int o = atomic_read(&net->nr_outstanding_calls);
166+
unsigned int debug_id = call->debug_id;
167+
bool zero;
168+
int r, o;
168169

169-
trace_afs_call(call, afs_call_trace_put, n, o,
170+
zero = __refcount_dec_and_test(&call->ref, &r);
171+
o = atomic_read(&net->nr_outstanding_calls);
172+
trace_afs_call(debug_id, afs_call_trace_put, r - 1, o,
170173
__builtin_return_address(0));
171174

172-
ASSERTCMP(n, >=, 0);
173-
if (n == 0) {
175+
if (zero) {
174176
ASSERT(!work_pending(&call->async_work));
175177
ASSERT(call->type->name != NULL);
176178

@@ -185,7 +187,7 @@ void afs_put_call(struct afs_call *call)
185187
afs_put_addrlist(call->alist);
186188
kfree(call->request);
187189

188-
trace_afs_call(call, afs_call_trace_free, 0, o,
190+
trace_afs_call(call->debug_id, afs_call_trace_free, 0, o,
189191
__builtin_return_address(0));
190192
kfree(call);
191193

@@ -198,9 +200,11 @@ void afs_put_call(struct afs_call *call)
198200
static struct afs_call *afs_get_call(struct afs_call *call,
199201
enum afs_call_trace why)
200202
{
201-
int u = atomic_inc_return(&call->usage);
203+
int r;
202204

203-
trace_afs_call(call, why, u,
205+
__refcount_inc(&call->ref, &r);
206+
207+
trace_afs_call(call->debug_id, why, r + 1,
204208
atomic_read(&call->net->nr_outstanding_calls),
205209
__builtin_return_address(0));
206210
return call;
@@ -668,14 +672,13 @@ static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
668672
unsigned long call_user_ID)
669673
{
670674
struct afs_call *call = (struct afs_call *)call_user_ID;
671-
int u;
675+
int r;
672676

673677
trace_afs_notify_call(rxcall, call);
674678
call->need_attention = true;
675679

676-
u = atomic_fetch_add_unless(&call->usage, 1, 0);
677-
if (u != 0) {
678-
trace_afs_call(call, afs_call_trace_wake, u + 1,
680+
if (__refcount_inc_not_zero(&call->ref, &r)) {
681+
trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1,
679682
atomic_read(&call->net->nr_outstanding_calls),
680683
__builtin_return_address(0));
681684

0 commit comments

Comments
 (0)