hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/afs/cell.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* AFS cell and server record management
23 *
34 * Copyright (C) 2002, 2017 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/slab.h>
....@@ -20,8 +16,12 @@
2016 #include "internal.h"
2117
2218 static unsigned __read_mostly afs_cell_gc_delay = 10;
19
+static unsigned __read_mostly afs_cell_min_ttl = 10 * 60;
20
+static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60;
21
+static atomic_t cell_debug_id;
2322
24
-static void afs_manage_cell(struct work_struct *);
23
+static void afs_queue_cell_manager(struct afs_net *);
24
+static void afs_manage_cell_work(struct work_struct *);
2525
2626 static void afs_dec_cells_outstanding(struct afs_net *net)
2727 {
....@@ -39,19 +39,22 @@
3939 atomic_inc(&net->cells_outstanding);
4040 if (timer_reduce(&net->cells_timer, jiffies + delay * HZ))
4141 afs_dec_cells_outstanding(net);
42
+ } else {
43
+ afs_queue_cell_manager(net);
4244 }
4345 }
4446
4547 /*
46
- * Look up and get an activation reference on a cell record under RCU
47
- * conditions. The caller must hold the RCU read lock.
48
+ * Look up and get an activation reference on a cell record. The caller must
49
+ * hold net->cells_lock at least read-locked.
4850 */
49
-struct afs_cell *afs_lookup_cell_rcu(struct afs_net *net,
50
- const char *name, unsigned int namesz)
51
+static struct afs_cell *afs_find_cell_locked(struct afs_net *net,
52
+ const char *name, unsigned int namesz,
53
+ enum afs_cell_trace reason)
5154 {
5255 struct afs_cell *cell = NULL;
5356 struct rb_node *p;
54
- int n, seq = 0, ret = 0;
57
+ int n;
5558
5659 _enter("%*.*s", namesz, namesz, name);
5760
....@@ -60,61 +63,48 @@
6063 if (namesz > AFS_MAXCELLNAME)
6164 return ERR_PTR(-ENAMETOOLONG);
6265
63
- do {
64
- /* Unfortunately, rbtree walking doesn't give reliable results
65
- * under just the RCU read lock, so we have to check for
66
- * changes.
67
- */
68
- if (cell)
69
- afs_put_cell(net, cell);
70
- cell = NULL;
71
- ret = -ENOENT;
66
+ if (!name) {
67
+ cell = net->ws_cell;
68
+ if (!cell)
69
+ return ERR_PTR(-EDESTADDRREQ);
70
+ goto found;
71
+ }
7272
73
- read_seqbegin_or_lock(&net->cells_lock, &seq);
73
+ p = net->cells.rb_node;
74
+ while (p) {
75
+ cell = rb_entry(p, struct afs_cell, net_node);
7476
75
- if (!name) {
76
- cell = rcu_dereference_raw(net->ws_cell);
77
- if (cell) {
78
- afs_get_cell(cell);
79
- ret = 0;
80
- break;
81
- }
82
- ret = -EDESTADDRREQ;
83
- continue;
84
- }
77
+ n = strncasecmp(cell->name, name,
78
+ min_t(size_t, cell->name_len, namesz));
79
+ if (n == 0)
80
+ n = cell->name_len - namesz;
81
+ if (n < 0)
82
+ p = p->rb_left;
83
+ else if (n > 0)
84
+ p = p->rb_right;
85
+ else
86
+ goto found;
87
+ }
8588
86
- p = rcu_dereference_raw(net->cells.rb_node);
87
- while (p) {
88
- cell = rb_entry(p, struct afs_cell, net_node);
89
+ return ERR_PTR(-ENOENT);
8990
90
- n = strncasecmp(cell->name, name,
91
- min_t(size_t, cell->name_len, namesz));
92
- if (n == 0)
93
- n = cell->name_len - namesz;
94
- if (n < 0) {
95
- p = rcu_dereference_raw(p->rb_left);
96
- } else if (n > 0) {
97
- p = rcu_dereference_raw(p->rb_right);
98
- } else {
99
- if (atomic_inc_not_zero(&cell->usage)) {
100
- ret = 0;
101
- break;
102
- }
103
- /* We want to repeat the search, this time with
104
- * the lock properly locked.
105
- */
106
- }
107
- cell = NULL;
108
- }
91
+found:
92
+ return afs_use_cell(cell, reason);
93
+}
10994
110
- } while (need_seqretry(&net->cells_lock, seq));
95
+/*
96
+ * Look up and get an activation reference on a cell record.
97
+ */
98
+struct afs_cell *afs_find_cell(struct afs_net *net,
99
+ const char *name, unsigned int namesz,
100
+ enum afs_cell_trace reason)
101
+{
102
+ struct afs_cell *cell;
111103
112
- done_seqretry(&net->cells_lock, seq);
113
-
114
- if (ret != 0 && cell)
115
- afs_put_cell(net, cell);
116
-
117
- return ret == 0 ? cell : ERR_PTR(ret);
104
+ down_read(&net->cells_lock);
105
+ cell = afs_find_cell_locked(net, name, namesz, reason);
106
+ up_read(&net->cells_lock);
107
+ return cell;
118108 }
119109
120110 /*
....@@ -123,8 +113,9 @@
123113 */
124114 static struct afs_cell *afs_alloc_cell(struct afs_net *net,
125115 const char *name, unsigned int namelen,
126
- const char *vllist)
116
+ const char *addresses)
127117 {
118
+ struct afs_vlserver_list *vllist;
128119 struct afs_cell *cell;
129120 int i, ret;
130121
....@@ -147,7 +138,7 @@
147138 return ERR_PTR(-EINVAL);
148139 }
149140
150
- _enter("%*.*s,%s", namelen, namelen, name, vllist);
141
+ _enter("%*.*s,%s", namelen, namelen, name, addresses);
151142
152143 cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL);
153144 if (!cell) {
....@@ -155,35 +146,62 @@
155146 return ERR_PTR(-ENOMEM);
156147 }
157148
149
+ cell->name = kmalloc(namelen + 1, GFP_KERNEL);
150
+ if (!cell->name) {
151
+ kfree(cell);
152
+ return ERR_PTR(-ENOMEM);
153
+ }
154
+
158155 cell->net = net;
159156 cell->name_len = namelen;
160157 for (i = 0; i < namelen; i++)
161158 cell->name[i] = tolower(name[i]);
159
+ cell->name[i] = 0;
162160
163
- atomic_set(&cell->usage, 2);
164
- INIT_WORK(&cell->manager, afs_manage_cell);
165
- cell->flags = ((1 << AFS_CELL_FL_NOT_READY) |
166
- (1 << AFS_CELL_FL_NO_LOOKUP_YET));
167
- INIT_LIST_HEAD(&cell->proc_volumes);
168
- rwlock_init(&cell->proc_lock);
169
- rwlock_init(&cell->vl_addrs_lock);
161
+ atomic_set(&cell->ref, 1);
162
+ atomic_set(&cell->active, 0);
163
+ INIT_WORK(&cell->manager, afs_manage_cell_work);
164
+ cell->volumes = RB_ROOT;
165
+ INIT_HLIST_HEAD(&cell->proc_volumes);
166
+ seqlock_init(&cell->volume_lock);
167
+ cell->fs_servers = RB_ROOT;
168
+ seqlock_init(&cell->fs_lock);
169
+ rwlock_init(&cell->vl_servers_lock);
170
+ cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS);
170171
171
- /* Fill in the VL server list if we were given a list of addresses to
172
- * use.
172
+ /* Provide a VL server list, filling it in if we were given a list of
173
+ * addresses to use.
173174 */
174
- if (vllist) {
175
- struct afs_addr_list *alist;
176
-
177
- alist = afs_parse_text_addrs(vllist, strlen(vllist), ':',
178
- VL_SERVICE, AFS_VL_PORT);
179
- if (IS_ERR(alist)) {
180
- ret = PTR_ERR(alist);
175
+ if (addresses) {
176
+ vllist = afs_parse_text_addrs(net,
177
+ addresses, strlen(addresses), ':',
178
+ VL_SERVICE, AFS_VL_PORT);
179
+ if (IS_ERR(vllist)) {
180
+ ret = PTR_ERR(vllist);
181181 goto parse_failed;
182182 }
183183
184
- rcu_assign_pointer(cell->vl_addrs, alist);
184
+ vllist->source = DNS_RECORD_FROM_CONFIG;
185
+ vllist->status = DNS_LOOKUP_NOT_DONE;
185186 cell->dns_expiry = TIME64_MAX;
187
+ } else {
188
+ ret = -ENOMEM;
189
+ vllist = afs_alloc_vlserver_list(0);
190
+ if (!vllist)
191
+ goto error;
192
+ vllist->source = DNS_RECORD_UNAVAILABLE;
193
+ vllist->status = DNS_LOOKUP_NOT_DONE;
194
+ cell->dns_expiry = ktime_get_real_seconds();
186195 }
196
+
197
+ rcu_assign_pointer(cell->vl_servers, vllist);
198
+
199
+ cell->dns_source = vllist->source;
200
+ cell->dns_status = vllist->status;
201
+ smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */
202
+ atomic_inc(&net->cells_outstanding);
203
+ cell->debug_id = atomic_inc_return(&cell_debug_id);
204
+ trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc);
187205
188206 _leave(" = %p", cell);
189207 return cell;
....@@ -191,6 +209,8 @@
191209 parse_failed:
192210 if (ret == -EINVAL)
193211 printk(KERN_ERR "kAFS: bad VL server IP address\n");
212
+error:
213
+ kfree(cell->name);
194214 kfree(cell);
195215 _leave(" = %d", ret);
196216 return ERR_PTR(ret);
....@@ -215,14 +235,13 @@
215235 {
216236 struct afs_cell *cell, *candidate, *cursor;
217237 struct rb_node *parent, **pp;
238
+ enum afs_cell_state state;
218239 int ret, n;
219240
220241 _enter("%s,%s", name, vllist);
221242
222243 if (!excl) {
223
- rcu_read_lock();
224
- cell = afs_lookup_cell_rcu(net, name, namesz);
225
- rcu_read_unlock();
244
+ cell = afs_find_cell(net, name, namesz, afs_cell_trace_use_lookup);
226245 if (!IS_ERR(cell))
227246 goto wait_for_cell;
228247 }
....@@ -243,7 +262,7 @@
243262 /* Find the insertion point and check to see if someone else added a
244263 * cell whilst we were allocating.
245264 */
246
- write_seqlock(&net->cells_lock);
265
+ down_write(&net->cells_lock);
247266
248267 pp = &net->cells.rb_node;
249268 parent = NULL;
....@@ -265,27 +284,28 @@
265284
266285 cell = candidate;
267286 candidate = NULL;
287
+ atomic_set(&cell->active, 2);
288
+ trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 2, afs_cell_trace_insert);
268289 rb_link_node_rcu(&cell->net_node, parent, pp);
269290 rb_insert_color(&cell->net_node, &net->cells);
270
- atomic_inc(&net->cells_outstanding);
271
- write_sequnlock(&net->cells_lock);
291
+ up_write(&net->cells_lock);
272292
273
- queue_work(afs_wq, &cell->manager);
293
+ afs_queue_cell(cell, afs_cell_trace_get_queue_new);
274294
275295 wait_for_cell:
296
+ trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), atomic_read(&cell->active),
297
+ afs_cell_trace_wait);
276298 _debug("wait_for_cell");
277
- ret = wait_on_bit(&cell->flags, AFS_CELL_FL_NOT_READY, TASK_INTERRUPTIBLE);
278
- smp_rmb();
299
+ wait_var_event(&cell->state,
300
+ ({
301
+ state = smp_load_acquire(&cell->state); /* vs error */
302
+ state == AFS_CELL_ACTIVE || state == AFS_CELL_REMOVED;
303
+ }));
279304
280
- switch (READ_ONCE(cell->state)) {
281
- case AFS_CELL_FAILED:
305
+ /* Check the state obtained from the wait check. */
306
+ if (state == AFS_CELL_REMOVED) {
282307 ret = cell->error;
283308 goto error;
284
- default:
285
- _debug("weird %u %d", cell->state, cell->error);
286
- goto error;
287
- case AFS_CELL_ACTIVE:
288
- break;
289309 }
290310
291311 _leave(" = %p [cell]", cell);
....@@ -297,16 +317,17 @@
297317 if (excl) {
298318 ret = -EEXIST;
299319 } else {
300
- afs_get_cell(cursor);
320
+ afs_use_cell(cursor, afs_cell_trace_use_lookup);
301321 ret = 0;
302322 }
303
- write_sequnlock(&net->cells_lock);
304
- kfree(candidate);
323
+ up_write(&net->cells_lock);
324
+ if (candidate)
325
+ afs_put_cell(candidate, afs_cell_trace_put_candidate);
305326 if (ret == 0)
306327 goto wait_for_cell;
307328 goto error_noput;
308329 error:
309
- afs_put_cell(net, cell);
330
+ afs_unuse_cell(net, cell, afs_cell_trace_unuse_lookup);
310331 error_noput:
311332 _leave(" = %d [error]", ret);
312333 return ERR_PTR(ret);
....@@ -351,15 +372,16 @@
351372 }
352373
353374 if (!test_and_set_bit(AFS_CELL_FL_NO_GC, &new_root->flags))
354
- afs_get_cell(new_root);
375
+ afs_use_cell(new_root, afs_cell_trace_use_pin);
355376
356377 /* install the new cell */
357
- write_seqlock(&net->cells_lock);
358
- old_root = rcu_access_pointer(net->ws_cell);
359
- rcu_assign_pointer(net->ws_cell, new_root);
360
- write_sequnlock(&net->cells_lock);
378
+ down_write(&net->cells_lock);
379
+ afs_see_cell(new_root, afs_cell_trace_see_ws);
380
+ old_root = net->ws_cell;
381
+ net->ws_cell = new_root;
382
+ up_write(&net->cells_lock);
361383
362
- afs_put_cell(net, old_root);
384
+ afs_unuse_cell(net, old_root, afs_cell_trace_unuse_ws);
363385 _leave(" = 0");
364386 return 0;
365387 }
....@@ -367,53 +389,96 @@
367389 /*
368390 * Update a cell's VL server address list from the DNS.
369391 */
370
-static void afs_update_cell(struct afs_cell *cell)
392
+static int afs_update_cell(struct afs_cell *cell)
371393 {
372
- struct afs_addr_list *alist, *old;
373
- time64_t now, expiry;
394
+ struct afs_vlserver_list *vllist, *old = NULL, *p;
395
+ unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl);
396
+ unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl);
397
+ time64_t now, expiry = 0;
398
+ int ret = 0;
374399
375400 _enter("%s", cell->name);
376401
377
- alist = afs_dns_query(cell, &expiry);
378
- if (IS_ERR(alist)) {
379
- switch (PTR_ERR(alist)) {
380
- case -ENODATA:
381
- /* The DNS said that the cell does not exist */
382
- set_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
383
- clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
384
- cell->dns_expiry = ktime_get_real_seconds() + 61;
385
- break;
402
+ vllist = afs_dns_query(cell, &expiry);
403
+ if (IS_ERR(vllist)) {
404
+ ret = PTR_ERR(vllist);
386405
406
+ _debug("%s: fail %d", cell->name, ret);
407
+ if (ret == -ENOMEM)
408
+ goto out_wake;
409
+
410
+ ret = -ENOMEM;
411
+ vllist = afs_alloc_vlserver_list(0);
412
+ if (!vllist)
413
+ goto out_wake;
414
+
415
+ switch (ret) {
416
+ case -ENODATA:
417
+ case -EDESTADDRREQ:
418
+ vllist->status = DNS_LOOKUP_GOT_NOT_FOUND;
419
+ break;
387420 case -EAGAIN:
388421 case -ECONNREFUSED:
422
+ vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE;
423
+ break;
389424 default:
390
- set_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
391
- cell->dns_expiry = ktime_get_real_seconds() + 10;
425
+ vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE;
392426 break;
393427 }
394
-
395
- cell->error = -EDESTADDRREQ;
396
- } else {
397
- clear_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags);
398
- clear_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags);
399
-
400
- /* Exclusion on changing vl_addrs is achieved by a
401
- * non-reentrant work item.
402
- */
403
- old = rcu_dereference_protected(cell->vl_addrs, true);
404
- rcu_assign_pointer(cell->vl_addrs, alist);
405
- cell->dns_expiry = expiry;
406
-
407
- if (old)
408
- afs_put_addrlist(old);
409428 }
410429
411
- if (test_and_clear_bit(AFS_CELL_FL_NO_LOOKUP_YET, &cell->flags))
412
- wake_up_bit(&cell->flags, AFS_CELL_FL_NO_LOOKUP_YET);
430
+ _debug("%s: got list %d %d", cell->name, vllist->source, vllist->status);
431
+ cell->dns_status = vllist->status;
413432
414433 now = ktime_get_real_seconds();
415
- afs_set_cell_timer(cell->net, cell->dns_expiry - now);
416
- _leave("");
434
+ if (min_ttl > max_ttl)
435
+ max_ttl = min_ttl;
436
+ if (expiry < now + min_ttl)
437
+ expiry = now + min_ttl;
438
+ else if (expiry > now + max_ttl)
439
+ expiry = now + max_ttl;
440
+
441
+ _debug("%s: status %d", cell->name, vllist->status);
442
+ if (vllist->source == DNS_RECORD_UNAVAILABLE) {
443
+ switch (vllist->status) {
444
+ case DNS_LOOKUP_GOT_NOT_FOUND:
445
+ /* The DNS said that the cell does not exist or there
446
+ * weren't any addresses to be had.
447
+ */
448
+ cell->dns_expiry = expiry;
449
+ break;
450
+
451
+ case DNS_LOOKUP_BAD:
452
+ case DNS_LOOKUP_GOT_LOCAL_FAILURE:
453
+ case DNS_LOOKUP_GOT_TEMP_FAILURE:
454
+ case DNS_LOOKUP_GOT_NS_FAILURE:
455
+ default:
456
+ cell->dns_expiry = now + 10;
457
+ break;
458
+ }
459
+ } else {
460
+ cell->dns_expiry = expiry;
461
+ }
462
+
463
+ /* Replace the VL server list if the new record has servers or the old
464
+ * record doesn't.
465
+ */
466
+ write_lock(&cell->vl_servers_lock);
467
+ p = rcu_dereference_protected(cell->vl_servers, true);
468
+ if (vllist->nr_servers > 0 || p->nr_servers == 0) {
469
+ rcu_assign_pointer(cell->vl_servers, vllist);
470
+ cell->dns_source = vllist->source;
471
+ old = p;
472
+ }
473
+ write_unlock(&cell->vl_servers_lock);
474
+ afs_put_vlserverlist(cell->net, old);
475
+
476
+out_wake:
477
+ smp_store_release(&cell->dns_lookup_count,
478
+ cell->dns_lookup_count + 1); /* vs source/status */
479
+ wake_up_var(&cell->dns_lookup_count);
480
+ _leave(" = %d", ret);
481
+ return ret;
417482 }
418483
419484 /*
....@@ -422,15 +487,22 @@
422487 static void afs_cell_destroy(struct rcu_head *rcu)
423488 {
424489 struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu);
490
+ struct afs_net *net = cell->net;
491
+ int u;
425492
426493 _enter("%p{%s}", cell, cell->name);
427494
428
- ASSERTCMP(atomic_read(&cell->usage), ==, 0);
495
+ u = atomic_read(&cell->ref);
496
+ ASSERTCMP(u, ==, 0);
497
+ trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), afs_cell_trace_free);
429498
430
- afs_put_addrlist(rcu_access_pointer(cell->vl_addrs));
499
+ afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers));
500
+ afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias);
431501 key_put(cell->anonymous_key);
502
+ kfree(cell->name);
432503 kfree(cell);
433504
505
+ afs_dec_cells_outstanding(net);
434506 _leave(" [destroyed]");
435507 }
436508
....@@ -463,18 +535,63 @@
463535 /*
464536 * Get a reference on a cell record.
465537 */
466
-struct afs_cell *afs_get_cell(struct afs_cell *cell)
538
+struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason)
467539 {
468
- atomic_inc(&cell->usage);
540
+ int u;
541
+
542
+ if (atomic_read(&cell->ref) <= 0)
543
+ BUG();
544
+
545
+ u = atomic_inc_return(&cell->ref);
546
+ trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), reason);
469547 return cell;
470548 }
471549
472550 /*
473551 * Drop a reference on a cell record.
474552 */
475
-void afs_put_cell(struct afs_net *net, struct afs_cell *cell)
553
+void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason)
476554 {
555
+ if (cell) {
556
+ unsigned int debug_id = cell->debug_id;
557
+ unsigned int u, a;
558
+
559
+ a = atomic_read(&cell->active);
560
+ u = atomic_dec_return(&cell->ref);
561
+ trace_afs_cell(debug_id, u, a, reason);
562
+ if (u == 0) {
563
+ a = atomic_read(&cell->active);
564
+ WARN(a != 0, "Cell active count %u > 0\n", a);
565
+ call_rcu(&cell->rcu, afs_cell_destroy);
566
+ }
567
+ }
568
+}
569
+
570
+/*
571
+ * Note a cell becoming more active.
572
+ */
573
+struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason)
574
+{
575
+ int u, a;
576
+
577
+ if (atomic_read(&cell->ref) <= 0)
578
+ BUG();
579
+
580
+ u = atomic_read(&cell->ref);
581
+ a = atomic_inc_return(&cell->active);
582
+ trace_afs_cell(cell->debug_id, u, a, reason);
583
+ return cell;
584
+}
585
+
586
+/*
587
+ * Record a cell becoming less active. When the active counter reaches 1, it
588
+ * is scheduled for destruction, but may get reactivated.
589
+ */
590
+void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason)
591
+{
592
+ unsigned int debug_id;
477593 time64_t now, expire_delay;
594
+ int u, a;
478595
479596 if (!cell)
480597 return;
....@@ -484,15 +601,39 @@
484601 now = ktime_get_real_seconds();
485602 cell->last_inactive = now;
486603 expire_delay = 0;
487
- if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
488
- !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
604
+ if (cell->vl_servers->nr_servers)
489605 expire_delay = afs_cell_gc_delay;
490606
491
- if (atomic_dec_return(&cell->usage) > 1)
492
- return;
607
+ debug_id = cell->debug_id;
608
+ u = atomic_read(&cell->ref);
609
+ a = atomic_dec_return(&cell->active);
610
+ trace_afs_cell(debug_id, u, a, reason);
611
+ WARN_ON(a == 0);
612
+ if (a == 1)
613
+ /* 'cell' may now be garbage collected. */
614
+ afs_set_cell_timer(net, expire_delay);
615
+}
493616
494
- /* 'cell' may now be garbage collected. */
495
- afs_set_cell_timer(net, expire_delay);
617
+/*
618
+ * Note that a cell has been seen.
619
+ */
620
+void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason)
621
+{
622
+ int u, a;
623
+
624
+ u = atomic_read(&cell->ref);
625
+ a = atomic_read(&cell->active);
626
+ trace_afs_cell(cell->debug_id, u, a, reason);
627
+}
628
+
629
+/*
630
+ * Queue a cell for management, giving the workqueue a ref to hold.
631
+ */
632
+void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason)
633
+{
634
+ afs_get_cell(cell, reason);
635
+ if (!queue_work(afs_wq, &cell->manager))
636
+ afs_put_cell(cell, afs_cell_trace_put_queue_fail);
496637 }
497638
498639 /*
....@@ -592,12 +733,10 @@
592733 * Manage a cell record, initialising and destroying it, maintaining its DNS
593734 * records.
594735 */
595
-static void afs_manage_cell(struct work_struct *work)
736
+static void afs_manage_cell(struct afs_cell *cell)
596737 {
597
- struct afs_cell *cell = container_of(work, struct afs_cell, manager);
598738 struct afs_net *net = cell->net;
599
- bool deleted;
600
- int ret, usage;
739
+ int ret, active;
601740
602741 _enter("%s", cell->name);
603742
....@@ -606,21 +745,28 @@
606745 switch (cell->state) {
607746 case AFS_CELL_INACTIVE:
608747 case AFS_CELL_FAILED:
609
- write_seqlock(&net->cells_lock);
610
- usage = 1;
611
- deleted = atomic_try_cmpxchg_relaxed(&cell->usage, &usage, 0);
612
- if (deleted)
748
+ down_write(&net->cells_lock);
749
+ active = 1;
750
+ if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) {
613751 rb_erase(&cell->net_node, &net->cells);
614
- write_sequnlock(&net->cells_lock);
615
- if (deleted)
752
+ trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 0,
753
+ afs_cell_trace_unuse_delete);
754
+ smp_store_release(&cell->state, AFS_CELL_REMOVED);
755
+ }
756
+ up_write(&net->cells_lock);
757
+ if (cell->state == AFS_CELL_REMOVED) {
758
+ wake_up_var(&cell->state);
616759 goto final_destruction;
760
+ }
617761 if (cell->state == AFS_CELL_FAILED)
618762 goto done;
619
- cell->state = AFS_CELL_UNSET;
763
+ smp_store_release(&cell->state, AFS_CELL_UNSET);
764
+ wake_up_var(&cell->state);
620765 goto again;
621766
622767 case AFS_CELL_UNSET:
623
- cell->state = AFS_CELL_ACTIVATING;
768
+ smp_store_release(&cell->state, AFS_CELL_ACTIVATING);
769
+ wake_up_var(&cell->state);
624770 goto again;
625771
626772 case AFS_CELL_ACTIVATING:
....@@ -628,29 +774,33 @@
628774 if (ret < 0)
629775 goto activation_failed;
630776
631
- cell->state = AFS_CELL_ACTIVE;
632
- smp_wmb();
633
- clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
634
- wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
777
+ smp_store_release(&cell->state, AFS_CELL_ACTIVE);
778
+ wake_up_var(&cell->state);
635779 goto again;
636780
637781 case AFS_CELL_ACTIVE:
638
- if (atomic_read(&cell->usage) > 1) {
639
- time64_t now = ktime_get_real_seconds();
640
- if (cell->dns_expiry <= now && net->live)
641
- afs_update_cell(cell);
782
+ if (atomic_read(&cell->active) > 1) {
783
+ if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) {
784
+ ret = afs_update_cell(cell);
785
+ if (ret < 0)
786
+ cell->error = ret;
787
+ }
642788 goto done;
643789 }
644
- cell->state = AFS_CELL_DEACTIVATING;
790
+ smp_store_release(&cell->state, AFS_CELL_DEACTIVATING);
791
+ wake_up_var(&cell->state);
645792 goto again;
646793
647794 case AFS_CELL_DEACTIVATING:
648
- set_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
649
- if (atomic_read(&cell->usage) > 1)
795
+ if (atomic_read(&cell->active) > 1)
650796 goto reverse_deactivation;
651797 afs_deactivate_cell(net, cell);
652
- cell->state = AFS_CELL_INACTIVE;
798
+ smp_store_release(&cell->state, AFS_CELL_INACTIVE);
799
+ wake_up_var(&cell->state);
653800 goto again;
801
+
802
+ case AFS_CELL_REMOVED:
803
+ goto done;
654804
655805 default:
656806 break;
....@@ -662,17 +812,13 @@
662812 cell->error = ret;
663813 afs_deactivate_cell(net, cell);
664814
665
- cell->state = AFS_CELL_FAILED;
666
- smp_wmb();
667
- if (test_and_clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags))
668
- wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
815
+ smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */
816
+ wake_up_var(&cell->state);
669817 goto again;
670818
671819 reverse_deactivation:
672
- cell->state = AFS_CELL_ACTIVE;
673
- smp_wmb();
674
- clear_bit(AFS_CELL_FL_NOT_READY, &cell->flags);
675
- wake_up_bit(&cell->flags, AFS_CELL_FL_NOT_READY);
820
+ smp_store_release(&cell->state, AFS_CELL_ACTIVE);
821
+ wake_up_var(&cell->state);
676822 _leave(" [deact->act]");
677823 return;
678824
....@@ -681,9 +827,18 @@
681827 return;
682828
683829 final_destruction:
684
- call_rcu(&cell->rcu, afs_cell_destroy);
685
- afs_dec_cells_outstanding(net);
686
- _leave(" [destruct %d]", atomic_read(&net->cells_outstanding));
830
+ /* The root volume is pinning the cell */
831
+ afs_put_volume(cell->net, cell->root_volume, afs_volume_trace_put_cell_root);
832
+ cell->root_volume = NULL;
833
+ afs_put_cell(cell, afs_cell_trace_put_destroy);
834
+}
835
+
836
+static void afs_manage_cell_work(struct work_struct *work)
837
+{
838
+ struct afs_cell *cell = container_of(work, struct afs_cell, manager);
839
+
840
+ afs_manage_cell(cell);
841
+ afs_put_cell(cell, afs_cell_trace_put_queue_work);
687842 }
688843
689844 /*
....@@ -712,31 +867,39 @@
712867 * lack of use and cells whose DNS results have expired and dispatch
713868 * their managers.
714869 */
715
- read_seqlock_excl(&net->cells_lock);
870
+ down_read(&net->cells_lock);
716871
717872 for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) {
718873 struct afs_cell *cell =
719874 rb_entry(cursor, struct afs_cell, net_node);
720
- unsigned usage;
875
+ unsigned active;
721876 bool sched_cell = false;
722877
723
- usage = atomic_read(&cell->usage);
724
- _debug("manage %s %u", cell->name, usage);
878
+ active = atomic_read(&cell->active);
879
+ trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
880
+ active, afs_cell_trace_manage);
725881
726
- ASSERTCMP(usage, >=, 1);
882
+ ASSERTCMP(active, >=, 1);
727883
728884 if (purging) {
729
- if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags))
730
- usage = atomic_dec_return(&cell->usage);
731
- ASSERTCMP(usage, ==, 1);
885
+ if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) {
886
+ active = atomic_dec_return(&cell->active);
887
+ trace_afs_cell(cell->debug_id, atomic_read(&cell->ref),
888
+ active, afs_cell_trace_unuse_pin);
889
+ }
732890 }
733891
734
- if (usage == 1) {
892
+ if (active == 1) {
893
+ struct afs_vlserver_list *vllist;
735894 time64_t expire_at = cell->last_inactive;
736895
737
- if (!test_bit(AFS_CELL_FL_DNS_FAIL, &cell->flags) &&
738
- !test_bit(AFS_CELL_FL_NOT_FOUND, &cell->flags))
896
+ read_lock(&cell->vl_servers_lock);
897
+ vllist = rcu_dereference_protected(
898
+ cell->vl_servers,
899
+ lockdep_is_held(&cell->vl_servers_lock));
900
+ if (vllist->nr_servers > 0)
739901 expire_at += afs_cell_gc_delay;
902
+ read_unlock(&cell->vl_servers_lock);
740903 if (purging || expire_at <= now)
741904 sched_cell = true;
742905 else if (expire_at < next_manage)
....@@ -744,17 +907,15 @@
744907 }
745908
746909 if (!purging) {
747
- if (cell->dns_expiry <= now)
910
+ if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags))
748911 sched_cell = true;
749
- else if (cell->dns_expiry <= next_manage)
750
- next_manage = cell->dns_expiry;
751912 }
752913
753914 if (sched_cell)
754
- queue_work(afs_wq, &cell->manager);
915
+ afs_queue_cell(cell, afs_cell_trace_get_queue_manage);
755916 }
756917
757
- read_sequnlock_excl(&net->cells_lock);
918
+ up_read(&net->cells_lock);
758919
759920 /* Update the timer on the way out. We have to pass an increment on
760921 * cells_outstanding in the namespace that we are in to the timer or
....@@ -784,11 +945,11 @@
784945
785946 _enter("");
786947
787
- write_seqlock(&net->cells_lock);
788
- ws = rcu_access_pointer(net->ws_cell);
789
- RCU_INIT_POINTER(net->ws_cell, NULL);
790
- write_sequnlock(&net->cells_lock);
791
- afs_put_cell(net, ws);
948
+ down_write(&net->cells_lock);
949
+ ws = net->ws_cell;
950
+ net->ws_cell = NULL;
951
+ up_write(&net->cells_lock);
952
+ afs_unuse_cell(net, ws, afs_cell_trace_unuse_ws);
792953
793954 _debug("del timer");
794955 if (del_timer_sync(&net->cells_timer))