Blame view
fs/afs/cell.c
23.7 KB
2874c5fd2 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
ec26815ad [AFS]: Clean up t... |
2 |
/* AFS cell and server record management |
1da177e4c Linux-2.6.12-rc2 |
3 |
* |
989782dcd afs: Overhaul cel... |
4 |
* Copyright (C) 2002, 2017 Red Hat, Inc. All Rights Reserved. |
1da177e4c Linux-2.6.12-rc2 |
5 |
* Written by David Howells (dhowells@redhat.com) |
1da177e4c Linux-2.6.12-rc2 |
6 |
*/ |
1da177e4c Linux-2.6.12-rc2 |
7 |
#include <linux/slab.h> |
00d3b7a45 [AFS]: Add securi... |
8 9 |
#include <linux/key.h> #include <linux/ctype.h> |
07567a550 DNS: Make AFS go ... |
10 |
#include <linux/dns_resolver.h> |
e8edc6e03 Detach sched.h fr... |
11 |
#include <linux/sched.h> |
3838d3ecd afs: Allow IPv6 a... |
12 |
#include <linux/inet.h> |
0da0b7fd7 afs: Display manu... |
13 |
#include <linux/namei.h> |
00d3b7a45 [AFS]: Add securi... |
14 |
#include <keys/rxrpc-type.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include "internal.h" |
fe342cf77 afs: Fix checker ... |
16 |
static unsigned __read_mostly afs_cell_gc_delay = 10; |
ded2f4c58 afs: Fix TTL on V... |
17 18 |
static unsigned __read_mostly afs_cell_min_ttl = 10 * 60; static unsigned __read_mostly afs_cell_max_ttl = 24 * 60 * 60; |
dca54a7bb afs: Add tracing ... |
19 |
static atomic_t cell_debug_id; |
989782dcd afs: Overhaul cel... |
20 |
|
286377f6b afs: Fix cell pur... |
21 |
static void afs_queue_cell_manager(struct afs_net *); |
88c853c3f afs: Fix cell ref... |
22 |
static void afs_manage_cell_work(struct work_struct *); |
989782dcd afs: Overhaul cel... |
23 24 25 26 |
static void afs_dec_cells_outstanding(struct afs_net *net) { if (atomic_dec_and_test(&net->cells_outstanding)) |
ab1fbe324 sched/wait, fs/af... |
27 |
wake_up_var(&net->cells_outstanding); |
989782dcd afs: Overhaul cel... |
28 |
} |
1da177e4c Linux-2.6.12-rc2 |
29 |
/* |
989782dcd afs: Overhaul cel... |
30 31 |
* Set the cell timer to fire after a given delay, assuming it's not already * set for an earlier time. |
1da177e4c Linux-2.6.12-rc2 |
32 |
*/ |
989782dcd afs: Overhaul cel... |
33 |
static void afs_set_cell_timer(struct afs_net *net, time64_t delay) |
1da177e4c Linux-2.6.12-rc2 |
34 |
{ |
989782dcd afs: Overhaul cel... |
35 36 37 38 |
if (net->live) { atomic_inc(&net->cells_outstanding); if (timer_reduce(&net->cells_timer, jiffies + delay * HZ)) afs_dec_cells_outstanding(net); |
286377f6b afs: Fix cell pur... |
39 40 |
} else { afs_queue_cell_manager(net); |
989782dcd afs: Overhaul cel... |
41 42 43 44 |
} } /* |
92e3cc91d afs: Fix rapid ce... |
45 46 |
* Look up and get an activation reference on a cell record. The caller must * hold net->cells_lock at least read-locked. |
989782dcd afs: Overhaul cel... |
47 |
*/ |
92e3cc91d afs: Fix rapid ce... |
48 |
static struct afs_cell *afs_find_cell_locked(struct afs_net *net, |
dca54a7bb afs: Add tracing ... |
49 50 |
const char *name, unsigned int namesz, enum afs_cell_trace reason) |
989782dcd afs: Overhaul cel... |
51 52 53 |
{ struct afs_cell *cell = NULL; struct rb_node *p; |
92e3cc91d afs: Fix rapid ce... |
54 |
int n; |
989782dcd afs: Overhaul cel... |
55 56 57 58 59 60 61 |
_enter("%*.*s", namesz, namesz, name); if (name && namesz == 0) return ERR_PTR(-EINVAL); if (namesz > AFS_MAXCELLNAME) return ERR_PTR(-ENAMETOOLONG); |
92e3cc91d afs: Fix rapid ce... |
62 63 64 65 |
if (!name) { cell = net->ws_cell; if (!cell) return ERR_PTR(-EDESTADDRREQ); |
88c853c3f afs: Fix cell ref... |
66 |
goto found; |
92e3cc91d afs: Fix rapid ce... |
67 |
} |
989782dcd afs: Overhaul cel... |
68 |
|
92e3cc91d afs: Fix rapid ce... |
69 70 71 |
p = net->cells.rb_node; while (p) { cell = rb_entry(p, struct afs_cell, net_node); |
1da177e4c Linux-2.6.12-rc2 |
72 |
|
92e3cc91d afs: Fix rapid ce... |
73 74 75 76 77 78 79 80 81 82 83 84 85 |
n = strncasecmp(cell->name, name, min_t(size_t, cell->name_len, namesz)); if (n == 0) n = cell->name_len - namesz; if (n < 0) p = p->rb_left; else if (n > 0) p = p->rb_right; else goto found; } return ERR_PTR(-ENOENT); |
1da177e4c Linux-2.6.12-rc2 |
86 |
|
92e3cc91d afs: Fix rapid ce... |
87 |
found: |
dca54a7bb afs: Add tracing ... |
88 |
return afs_use_cell(cell, reason); |
92e3cc91d afs: Fix rapid ce... |
89 |
} |
a5fb8e6c0 afs: Fix leak in ... |
90 |
|
88c853c3f afs: Fix cell ref... |
91 92 93 |
/* * Look up and get an activation reference on a cell record. */ |
92e3cc91d afs: Fix rapid ce... |
94 |
struct afs_cell *afs_find_cell(struct afs_net *net, |
dca54a7bb afs: Add tracing ... |
95 96 |
const char *name, unsigned int namesz, enum afs_cell_trace reason) |
92e3cc91d afs: Fix rapid ce... |
97 98 99 100 |
{ struct afs_cell *cell; down_read(&net->cells_lock); |
dca54a7bb afs: Add tracing ... |
101 |
cell = afs_find_cell_locked(net, name, namesz, reason); |
92e3cc91d afs: Fix rapid ce... |
102 103 |
up_read(&net->cells_lock); return cell; |
989782dcd afs: Overhaul cel... |
104 105 106 107 108 109 110 111 |
} /* * Set up a cell record and fill in its name, VL server address list and * allocate an anonymous key */ static struct afs_cell *afs_alloc_cell(struct afs_net *net, const char *name, unsigned int namelen, |
0a5143f2f afs: Implement VL... |
112 |
const char *addresses) |
989782dcd afs: Overhaul cel... |
113 |
{ |
ca1cbbdce afs: Fix afs_cell... |
114 |
struct afs_vlserver_list *vllist; |
989782dcd afs: Overhaul cel... |
115 116 117 118 119 120 |
struct afs_cell *cell; int i, ret; ASSERT(name); if (namelen == 0) return ERR_PTR(-EINVAL); |
07567a550 DNS: Make AFS go ... |
121 122 |
if (namelen > AFS_MAXCELLNAME) { _leave(" = -ENAMETOOLONG"); |
00d3b7a45 [AFS]: Add securi... |
123 |
return ERR_PTR(-ENAMETOOLONG); |
07567a550 DNS: Make AFS go ... |
124 |
} |
a45ea48e2 afs: Fix characte... |
125 126 127 128 129 |
/* Prohibit cell names that contain unprintable chars, '/' and '@' or * that begin with a dot. This also precludes "@cell". */ if (name[0] == '.') |
37ab63688 afs: Implement @c... |
130 |
return ERR_PTR(-EINVAL); |
a45ea48e2 afs: Fix characte... |
131 132 133 134 135 |
for (i = 0; i < namelen; i++) { char ch = name[i]; if (!isprint(ch) || ch == '/' || ch == '@') return ERR_PTR(-EINVAL); } |
00d3b7a45 [AFS]: Add securi... |
136 |
|
0a5143f2f afs: Implement VL... |
137 |
_enter("%*.*s,%s", namelen, namelen, name, addresses); |
989782dcd afs: Overhaul cel... |
138 139 |
cell = kzalloc(sizeof(struct afs_cell), GFP_KERNEL); |
1da177e4c Linux-2.6.12-rc2 |
140 141 |
if (!cell) { _leave(" = -ENOMEM"); |
08e0e7c82 [AF_RXRPC]: Make ... |
142 |
return ERR_PTR(-ENOMEM); |
1da177e4c Linux-2.6.12-rc2 |
143 |
} |
719fdd329 afs: Fix storage ... |
144 145 146 147 148 |
cell->name = kmalloc(namelen + 1, GFP_KERNEL); if (!cell->name) { kfree(cell); return ERR_PTR(-ENOMEM); } |
f044c8847 afs: Lay the grou... |
149 |
cell->net = net; |
989782dcd afs: Overhaul cel... |
150 151 152 |
cell->name_len = namelen; for (i = 0; i < namelen; i++) cell->name[i] = tolower(name[i]); |
719fdd329 afs: Fix storage ... |
153 |
cell->name[i] = 0; |
989782dcd afs: Overhaul cel... |
154 |
|
88c853c3f afs: Fix cell ref... |
155 156 157 |
atomic_set(&cell->ref, 1); atomic_set(&cell->active, 0); INIT_WORK(&cell->manager, afs_manage_cell_work); |
20325960f afs: Reorganise v... |
158 159 160 161 162 |
cell->volumes = RB_ROOT; INIT_HLIST_HEAD(&cell->proc_volumes); seqlock_init(&cell->volume_lock); cell->fs_servers = RB_ROOT; seqlock_init(&cell->fs_lock); |
0a5143f2f afs: Implement VL... |
163 |
rwlock_init(&cell->vl_servers_lock); |
8a070a964 afs: Detect cell ... |
164 |
cell->flags = (1 << AFS_CELL_FL_CHECK_ALIAS); |
4d9df9868 afs: Keep and pas... |
165 |
|
ca1cbbdce afs: Fix afs_cell... |
166 167 |
/* Provide a VL server list, filling it in if we were given a list of * addresses to use. |
989782dcd afs: Overhaul cel... |
168 |
*/ |
0a5143f2f afs: Implement VL... |
169 |
if (addresses) { |
0a5143f2f afs: Implement VL... |
170 171 172 173 174 |
vllist = afs_parse_text_addrs(net, addresses, strlen(addresses), ':', VL_SERVICE, AFS_VL_PORT); if (IS_ERR(vllist)) { ret = PTR_ERR(vllist); |
8b2a464ce afs: Add an addre... |
175 176 |
goto parse_failed; } |
00d3b7a45 [AFS]: Add securi... |
177 |
|
d5c32c89b afs: Fix cell DNS... |
178 179 |
vllist->source = DNS_RECORD_FROM_CONFIG; vllist->status = DNS_LOOKUP_NOT_DONE; |
989782dcd afs: Overhaul cel... |
180 |
cell->dns_expiry = TIME64_MAX; |
ded2f4c58 afs: Fix TTL on V... |
181 |
} else { |
ca1cbbdce afs: Fix afs_cell... |
182 183 184 185 |
ret = -ENOMEM; vllist = afs_alloc_vlserver_list(0); if (!vllist) goto error; |
d5c32c89b afs: Fix cell DNS... |
186 187 |
vllist->source = DNS_RECORD_UNAVAILABLE; vllist->status = DNS_LOOKUP_NOT_DONE; |
ded2f4c58 afs: Fix TTL on V... |
188 |
cell->dns_expiry = ktime_get_real_seconds(); |
00d3b7a45 [AFS]: Add securi... |
189 |
} |
00d3b7a45 [AFS]: Add securi... |
190 |
|
ca1cbbdce afs: Fix afs_cell... |
191 |
rcu_assign_pointer(cell->vl_servers, vllist); |
d5c32c89b afs: Fix cell DNS... |
192 193 194 |
cell->dns_source = vllist->source; cell->dns_status = vllist->status; smp_store_release(&cell->dns_lookup_count, 1); /* vs source/status */ |
88c853c3f afs: Fix cell ref... |
195 |
atomic_inc(&net->cells_outstanding); |
dca54a7bb afs: Add tracing ... |
196 197 |
cell->debug_id = atomic_inc_return(&cell_debug_id); trace_afs_cell(cell->debug_id, 1, 0, afs_cell_trace_alloc); |
d5c32c89b afs: Fix cell DNS... |
198 |
|
00d3b7a45 [AFS]: Add securi... |
199 200 |
_leave(" = %p", cell); return cell; |
8b2a464ce afs: Add an addre... |
201 202 203 204 |
parse_failed: if (ret == -EINVAL) printk(KERN_ERR "kAFS: bad VL server IP address "); |
ca1cbbdce afs: Fix afs_cell... |
205 |
error: |
719fdd329 afs: Fix storage ... |
206 |
kfree(cell->name); |
00d3b7a45 [AFS]: Add securi... |
207 208 209 210 |
kfree(cell); _leave(" = %d", ret); return ERR_PTR(ret); } |
1da177e4c Linux-2.6.12-rc2 |
211 |
|
00d3b7a45 [AFS]: Add securi... |
212 |
/* |
989782dcd afs: Overhaul cel... |
213 |
* afs_lookup_cell - Look up or create a cell record. |
f044c8847 afs: Lay the grou... |
214 |
* @net: The network namespace |
989782dcd afs: Overhaul cel... |
215 216 217 218 219 220 221 222 223 |
* @name: The name of the cell. * @namesz: The strlen of the cell name. * @vllist: A colon/comma separated list of numeric IP addresses or NULL. * @excl: T if an error should be given if the cell name already exists. * * Look up a cell record by name and query the DNS for VL server addresses if * needed. Note that that actual DNS query is punted off to the manager thread * so that this function can return immediately if interrupted whilst allowing * cell records to be shared even if not yet fully constructed. |
00d3b7a45 [AFS]: Add securi... |
224 |
*/ |
989782dcd afs: Overhaul cel... |
225 226 227 |
struct afs_cell *afs_lookup_cell(struct afs_net *net, const char *name, unsigned int namesz, const char *vllist, bool excl) |
00d3b7a45 [AFS]: Add securi... |
228 |
{ |
989782dcd afs: Overhaul cel... |
229 230 |
struct afs_cell *cell, *candidate, *cursor; struct rb_node *parent, **pp; |
d5c32c89b afs: Fix cell DNS... |
231 |
enum afs_cell_state state; |
989782dcd afs: Overhaul cel... |
232 233 234 235 236 |
int ret, n; _enter("%s,%s", name, vllist); if (!excl) { |
dca54a7bb afs: Add tracing ... |
237 |
cell = afs_find_cell(net, name, namesz, afs_cell_trace_use_lookup); |
683279516 afs: cell: Remove... |
238 |
if (!IS_ERR(cell)) |
989782dcd afs: Overhaul cel... |
239 |
goto wait_for_cell; |
989782dcd afs: Overhaul cel... |
240 |
} |
00d3b7a45 [AFS]: Add securi... |
241 |
|
989782dcd afs: Overhaul cel... |
242 243 244 245 246 247 248 249 250 251 252 |
/* Assume we're probably going to create a cell and preallocate and * mostly set up a candidate record. We can then use this to stash the * name, the net namespace and VL server addresses. * * We also want to do this before we hold any locks as it may involve * upcalling to userspace to make DNS queries. */ candidate = afs_alloc_cell(net, name, namesz, vllist); if (IS_ERR(candidate)) { _leave(" = %ld", PTR_ERR(candidate)); return candidate; |
5214b729e afs: prevent doub... |
253 |
} |
5214b729e afs: prevent doub... |
254 |
|
989782dcd afs: Overhaul cel... |
255 256 257 |
/* Find the insertion point and check to see if someone else added a * cell whilst we were allocating. */ |
92e3cc91d afs: Fix rapid ce... |
258 |
down_write(&net->cells_lock); |
989782dcd afs: Overhaul cel... |
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
pp = &net->cells.rb_node; parent = NULL; while (*pp) { parent = *pp; cursor = rb_entry(parent, struct afs_cell, net_node); n = strncasecmp(cursor->name, name, min_t(size_t, cursor->name_len, namesz)); if (n == 0) n = cursor->name_len - namesz; if (n < 0) pp = &(*pp)->rb_left; else if (n > 0) pp = &(*pp)->rb_right; else goto cell_already_exists; |
00d3b7a45 [AFS]: Add securi... |
276 |
} |
989782dcd afs: Overhaul cel... |
277 278 |
cell = candidate; candidate = NULL; |
88c853c3f afs: Fix cell ref... |
279 |
atomic_set(&cell->active, 2); |
dca54a7bb afs: Add tracing ... |
280 |
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 2, afs_cell_trace_insert); |
989782dcd afs: Overhaul cel... |
281 282 |
rb_link_node_rcu(&cell->net_node, parent, pp); rb_insert_color(&cell->net_node, &net->cells); |
92e3cc91d afs: Fix rapid ce... |
283 |
up_write(&net->cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
284 |
|
dca54a7bb afs: Add tracing ... |
285 |
afs_queue_cell(cell, afs_cell_trace_get_queue_new); |
1da177e4c Linux-2.6.12-rc2 |
286 |
|
989782dcd afs: Overhaul cel... |
287 |
wait_for_cell: |
dca54a7bb afs: Add tracing ... |
288 289 |
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), atomic_read(&cell->active), afs_cell_trace_wait); |
989782dcd afs: Overhaul cel... |
290 |
_debug("wait_for_cell"); |
d5c32c89b afs: Fix cell DNS... |
291 292 293 |
wait_var_event(&cell->state, ({ state = smp_load_acquire(&cell->state); /* vs error */ |
1d0e850a4 afs: Fix cell rem... |
294 |
state == AFS_CELL_ACTIVE || state == AFS_CELL_REMOVED; |
d5c32c89b afs: Fix cell DNS... |
295 296 297 |
})); /* Check the state obtained from the wait check. */ |
1d0e850a4 afs: Fix cell rem... |
298 |
if (state == AFS_CELL_REMOVED) { |
989782dcd afs: Overhaul cel... |
299 300 |
ret = cell->error; goto error; |
989782dcd afs: Overhaul cel... |
301 |
} |
1da177e4c Linux-2.6.12-rc2 |
302 |
|
989782dcd afs: Overhaul cel... |
303 |
_leave(" = %p [cell]", cell); |
08e0e7c82 [AF_RXRPC]: Make ... |
304 |
return cell; |
1da177e4c Linux-2.6.12-rc2 |
305 |
|
989782dcd afs: Overhaul cel... |
306 307 308 309 310 311 |
cell_already_exists: _debug("cell exists"); cell = cursor; if (excl) { ret = -EEXIST; } else { |
dca54a7bb afs: Add tracing ... |
312 |
afs_use_cell(cursor, afs_cell_trace_use_lookup); |
989782dcd afs: Overhaul cel... |
313 314 |
ret = 0; } |
92e3cc91d afs: Fix rapid ce... |
315 |
up_write(&net->cells_lock); |
88c853c3f afs: Fix cell ref... |
316 |
if (candidate) |
dca54a7bb afs: Add tracing ... |
317 |
afs_put_cell(candidate, afs_cell_trace_put_candidate); |
989782dcd afs: Overhaul cel... |
318 319 |
if (ret == 0) goto wait_for_cell; |
8b2a464ce afs: Add an addre... |
320 |
goto error_noput; |
ec26815ad [AFS]: Clean up t... |
321 |
error: |
dca54a7bb afs: Add tracing ... |
322 |
afs_unuse_cell(net, cell, afs_cell_trace_unuse_lookup); |
8b2a464ce afs: Add an addre... |
323 |
error_noput: |
989782dcd afs: Overhaul cel... |
324 |
_leave(" = %d [error]", ret); |
08e0e7c82 [AF_RXRPC]: Make ... |
325 |
return ERR_PTR(ret); |
ec26815ad [AFS]: Clean up t... |
326 |
} |
1da177e4c Linux-2.6.12-rc2 |
327 |
|
1da177e4c Linux-2.6.12-rc2 |
328 |
/* |
08e0e7c82 [AF_RXRPC]: Make ... |
329 330 331 |
* set the root cell information * - can be called with a module parameter string * - can be called from a write to /proc/fs/afs/rootcell |
1da177e4c Linux-2.6.12-rc2 |
332 |
*/ |
989782dcd afs: Overhaul cel... |
333 |
int afs_cell_init(struct afs_net *net, const char *rootcell) |
1da177e4c Linux-2.6.12-rc2 |
334 335 |
{ struct afs_cell *old_root, *new_root; |
989782dcd afs: Overhaul cel... |
336 337 |
const char *cp, *vllist; size_t len; |
1da177e4c Linux-2.6.12-rc2 |
338 339 340 341 342 343 344 |
_enter(""); if (!rootcell) { /* module is loaded with no parameters, or built statically. * - in the future we might initialize cell DB here. */ |
08e0e7c82 [AF_RXRPC]: Make ... |
345 |
_leave(" = 0 [no root]"); |
1da177e4c Linux-2.6.12-rc2 |
346 347 348 349 |
return 0; } cp = strchr(rootcell, ':'); |
989782dcd afs: Overhaul cel... |
350 |
if (!cp) { |
07567a550 DNS: Make AFS go ... |
351 |
_debug("kAFS: no VL server IP addresses specified"); |
989782dcd afs: Overhaul cel... |
352 353 354 355 356 357 |
vllist = NULL; len = strlen(rootcell); } else { vllist = cp + 1; len = cp - rootcell; } |
1da177e4c Linux-2.6.12-rc2 |
358 359 |
/* allocate a cell record for the root cell */ |
989782dcd afs: Overhaul cel... |
360 |
new_root = afs_lookup_cell(net, rootcell, len, vllist, false); |
08e0e7c82 [AF_RXRPC]: Make ... |
361 362 363 |
if (IS_ERR(new_root)) { _leave(" = %ld", PTR_ERR(new_root)); return PTR_ERR(new_root); |
1da177e4c Linux-2.6.12-rc2 |
364 |
} |
17814aef5 afs: Don't over-i... |
365 |
if (!test_and_set_bit(AFS_CELL_FL_NO_GC, &new_root->flags)) |
dca54a7bb afs: Add tracing ... |
366 |
afs_use_cell(new_root, afs_cell_trace_use_pin); |
989782dcd afs: Overhaul cel... |
367 |
|
08e0e7c82 [AF_RXRPC]: Make ... |
368 |
/* install the new cell */ |
92e3cc91d afs: Fix rapid ce... |
369 |
down_write(&net->cells_lock); |
dca54a7bb afs: Add tracing ... |
370 |
afs_see_cell(new_root, afs_cell_trace_see_ws); |
92e3cc91d afs: Fix rapid ce... |
371 372 373 |
old_root = net->ws_cell; net->ws_cell = new_root; up_write(&net->cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
374 |
|
dca54a7bb afs: Add tracing ... |
375 |
afs_unuse_cell(net, old_root, afs_cell_trace_unuse_ws); |
08e0e7c82 [AF_RXRPC]: Make ... |
376 377 |
_leave(" = 0"); return 0; |
ec26815ad [AFS]: Clean up t... |
378 |
} |
1da177e4c Linux-2.6.12-rc2 |
379 |
|
1da177e4c Linux-2.6.12-rc2 |
380 |
/* |
989782dcd afs: Overhaul cel... |
381 |
* Update a cell's VL server address list from the DNS. |
1da177e4c Linux-2.6.12-rc2 |
382 |
*/ |
d5c32c89b afs: Fix cell DNS... |
383 |
static int afs_update_cell(struct afs_cell *cell) |
1da177e4c Linux-2.6.12-rc2 |
384 |
{ |
d5c32c89b afs: Fix cell DNS... |
385 |
struct afs_vlserver_list *vllist, *old = NULL, *p; |
ded2f4c58 afs: Fix TTL on V... |
386 387 388 |
unsigned int min_ttl = READ_ONCE(afs_cell_min_ttl); unsigned int max_ttl = READ_ONCE(afs_cell_max_ttl); time64_t now, expiry = 0; |
d5c32c89b afs: Fix cell DNS... |
389 |
int ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
390 |
|
989782dcd afs: Overhaul cel... |
391 |
_enter("%s", cell->name); |
0a5143f2f afs: Implement VL... |
392 |
vllist = afs_dns_query(cell, &expiry); |
d5c32c89b afs: Fix cell DNS... |
393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 |
if (IS_ERR(vllist)) { ret = PTR_ERR(vllist); _debug("%s: fail %d", cell->name, ret); if (ret == -ENOMEM) goto out_wake; ret = -ENOMEM; vllist = afs_alloc_vlserver_list(0); if (!vllist) goto out_wake; switch (ret) { case -ENODATA: case -EDESTADDRREQ: vllist->status = DNS_LOOKUP_GOT_NOT_FOUND; break; case -EAGAIN: case -ECONNREFUSED: vllist->status = DNS_LOOKUP_GOT_TEMP_FAILURE; break; default: vllist->status = DNS_LOOKUP_GOT_LOCAL_FAILURE; break; } } _debug("%s: got list %d %d", cell->name, vllist->source, vllist->status); cell->dns_status = vllist->status; |
ded2f4c58 afs: Fix TTL on V... |
422 423 424 425 426 427 428 429 |
now = ktime_get_real_seconds(); if (min_ttl > max_ttl) max_ttl = min_ttl; if (expiry < now + min_ttl) expiry = now + min_ttl; else if (expiry > now + max_ttl) expiry = now + max_ttl; |
d5c32c89b afs: Fix cell DNS... |
430 431 432 433 |
_debug("%s: status %d", cell->name, vllist->status); if (vllist->source == DNS_RECORD_UNAVAILABLE) { switch (vllist->status) { case DNS_LOOKUP_GOT_NOT_FOUND: |
ded2f4c58 afs: Fix TTL on V... |
434 435 436 |
/* The DNS said that the cell does not exist or there * weren't any addresses to be had. */ |
ded2f4c58 afs: Fix TTL on V... |
437 |
cell->dns_expiry = expiry; |
8b2a464ce afs: Add an addre... |
438 |
break; |
989782dcd afs: Overhaul cel... |
439 |
|
d5c32c89b afs: Fix cell DNS... |
440 441 442 443 |
case DNS_LOOKUP_BAD: case DNS_LOOKUP_GOT_LOCAL_FAILURE: case DNS_LOOKUP_GOT_TEMP_FAILURE: case DNS_LOOKUP_GOT_NS_FAILURE: |
8b2a464ce afs: Add an addre... |
444 |
default: |
ded2f4c58 afs: Fix TTL on V... |
445 |
cell->dns_expiry = now + 10; |
8b2a464ce afs: Add an addre... |
446 447 |
break; } |
8b2a464ce afs: Add an addre... |
448 |
} else { |
8b2a464ce afs: Add an addre... |
449 |
cell->dns_expiry = expiry; |
8b2a464ce afs: Add an addre... |
450 |
} |
bec5eb614 AFS: Implement an... |
451 |
|
d5c32c89b afs: Fix cell DNS... |
452 453 454 455 456 457 458 459 460 461 462 463 |
/* Replace the VL server list if the new record has servers or the old * record doesn't. */ write_lock(&cell->vl_servers_lock); p = rcu_dereference_protected(cell->vl_servers, true); if (vllist->nr_servers > 0 || p->nr_servers == 0) { rcu_assign_pointer(cell->vl_servers, vllist); cell->dns_source = vllist->source; old = p; } write_unlock(&cell->vl_servers_lock); afs_put_vlserverlist(cell->net, old); |
bec5eb614 AFS: Implement an... |
464 |
|
d5c32c89b afs: Fix cell DNS... |
465 466 467 468 469 470 |
out_wake: smp_store_release(&cell->dns_lookup_count, cell->dns_lookup_count + 1); /* vs source/status */ wake_up_var(&cell->dns_lookup_count); _leave(" = %d", ret); return ret; |
ec26815ad [AFS]: Clean up t... |
471 |
} |
1da177e4c Linux-2.6.12-rc2 |
472 |
|
1da177e4c Linux-2.6.12-rc2 |
473 |
/* |
989782dcd afs: Overhaul cel... |
474 |
* Destroy a cell record |
1da177e4c Linux-2.6.12-rc2 |
475 |
*/ |
989782dcd afs: Overhaul cel... |
476 |
static void afs_cell_destroy(struct rcu_head *rcu) |
1da177e4c Linux-2.6.12-rc2 |
477 |
{ |
989782dcd afs: Overhaul cel... |
478 |
struct afs_cell *cell = container_of(rcu, struct afs_cell, rcu); |
88c853c3f afs: Fix cell ref... |
479 480 |
struct afs_net *net = cell->net; int u; |
1da177e4c Linux-2.6.12-rc2 |
481 |
|
989782dcd afs: Overhaul cel... |
482 |
_enter("%p{%s}", cell, cell->name); |
1da177e4c Linux-2.6.12-rc2 |
483 |
|
88c853c3f afs: Fix cell ref... |
484 485 |
u = atomic_read(&cell->ref); ASSERTCMP(u, ==, 0); |
dca54a7bb afs: Add tracing ... |
486 |
trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), afs_cell_trace_free); |
989782dcd afs: Overhaul cel... |
487 |
|
88c853c3f afs: Fix cell ref... |
488 |
afs_put_vlserverlist(net, rcu_access_pointer(cell->vl_servers)); |
dca54a7bb afs: Add tracing ... |
489 |
afs_unuse_cell(net, cell->alias_of, afs_cell_trace_unuse_alias); |
989782dcd afs: Overhaul cel... |
490 |
key_put(cell->anonymous_key); |
719fdd329 afs: Fix storage ... |
491 |
kfree(cell->name); |
989782dcd afs: Overhaul cel... |
492 |
kfree(cell); |
88c853c3f afs: Fix cell ref... |
493 |
afs_dec_cells_outstanding(net); |
989782dcd afs: Overhaul cel... |
494 |
_leave(" [destroyed]"); |
ec26815ad [AFS]: Clean up t... |
495 |
} |
1da177e4c Linux-2.6.12-rc2 |
496 |
|
1da177e4c Linux-2.6.12-rc2 |
497 |
/* |
989782dcd afs: Overhaul cel... |
498 |
* Queue the cell manager. |
1da177e4c Linux-2.6.12-rc2 |
499 |
*/ |
989782dcd afs: Overhaul cel... |
500 |
static void afs_queue_cell_manager(struct afs_net *net) |
1da177e4c Linux-2.6.12-rc2 |
501 |
{ |
989782dcd afs: Overhaul cel... |
502 |
int outstanding = atomic_inc_return(&net->cells_outstanding); |
1da177e4c Linux-2.6.12-rc2 |
503 |
|
989782dcd afs: Overhaul cel... |
504 |
_enter("%d", outstanding); |
1da177e4c Linux-2.6.12-rc2 |
505 |
|
989782dcd afs: Overhaul cel... |
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 |
if (!queue_work(afs_wq, &net->cells_manager)) afs_dec_cells_outstanding(net); } /* * Cell management timer. We have an increment on cells_outstanding that we * need to pass along to the work item. */ void afs_cells_timer(struct timer_list *timer) { struct afs_net *net = container_of(timer, struct afs_net, cells_timer); _enter(""); if (!queue_work(afs_wq, &net->cells_manager)) afs_dec_cells_outstanding(net); } |
1da177e4c Linux-2.6.12-rc2 |
522 |
|
989782dcd afs: Overhaul cel... |
523 |
/* |
8b2a464ce afs: Add an addre... |
524 525 |
* Get a reference on a cell record. */ |
dca54a7bb afs: Add tracing ... |
526 |
struct afs_cell *afs_get_cell(struct afs_cell *cell, enum afs_cell_trace reason) |
8b2a464ce afs: Add an addre... |
527 |
{ |
dca54a7bb afs: Add tracing ... |
528 |
int u; |
88c853c3f afs: Fix cell ref... |
529 530 |
if (atomic_read(&cell->ref) <= 0) BUG(); |
dca54a7bb afs: Add tracing ... |
531 532 |
u = atomic_inc_return(&cell->ref); trace_afs_cell(cell->debug_id, u, atomic_read(&cell->active), reason); |
8b2a464ce afs: Add an addre... |
533 534 535 536 |
return cell; } /* |
989782dcd afs: Overhaul cel... |
537 538 |
* Drop a reference on a cell record. */ |
dca54a7bb afs: Add tracing ... |
539 |
void afs_put_cell(struct afs_cell *cell, enum afs_cell_trace reason) |
88c853c3f afs: Fix cell ref... |
540 541 |
{ if (cell) { |
dca54a7bb afs: Add tracing ... |
542 |
unsigned int debug_id = cell->debug_id; |
88c853c3f afs: Fix cell ref... |
543 |
unsigned int u, a; |
dca54a7bb afs: Add tracing ... |
544 |
a = atomic_read(&cell->active); |
88c853c3f afs: Fix cell ref... |
545 |
u = atomic_dec_return(&cell->ref); |
dca54a7bb afs: Add tracing ... |
546 |
trace_afs_cell(debug_id, u, a, reason); |
88c853c3f afs: Fix cell ref... |
547 548 549 550 551 552 553 554 555 556 557 558 |
if (u == 0) { a = atomic_read(&cell->active); WARN(a != 0, "Cell active count %u > 0 ", a); call_rcu(&cell->rcu, afs_cell_destroy); } } } /* * Note a cell becoming more active. */ |
dca54a7bb afs: Add tracing ... |
559 |
struct afs_cell *afs_use_cell(struct afs_cell *cell, enum afs_cell_trace reason) |
88c853c3f afs: Fix cell ref... |
560 |
{ |
dca54a7bb afs: Add tracing ... |
561 |
int u, a; |
88c853c3f afs: Fix cell ref... |
562 563 |
if (atomic_read(&cell->ref) <= 0) BUG(); |
dca54a7bb afs: Add tracing ... |
564 565 566 |
u = atomic_read(&cell->ref); a = atomic_inc_return(&cell->active); trace_afs_cell(cell->debug_id, u, a, reason); |
88c853c3f afs: Fix cell ref... |
567 568 569 570 571 572 573 |
return cell; } /* * Record a cell becoming less active. When the active counter reaches 1, it * is scheduled for destruction, but may get reactivated. */ |
dca54a7bb afs: Add tracing ... |
574 |
void afs_unuse_cell(struct afs_net *net, struct afs_cell *cell, enum afs_cell_trace reason) |
989782dcd afs: Overhaul cel... |
575 |
{ |
acc080d15 afs: Fix tracing ... |
576 |
unsigned int debug_id; |
989782dcd afs: Overhaul cel... |
577 |
time64_t now, expire_delay; |
dca54a7bb afs: Add tracing ... |
578 |
int u, a; |
1da177e4c Linux-2.6.12-rc2 |
579 |
|
989782dcd afs: Overhaul cel... |
580 |
if (!cell) |
1da177e4c Linux-2.6.12-rc2 |
581 |
return; |
1da177e4c Linux-2.6.12-rc2 |
582 |
|
989782dcd afs: Overhaul cel... |
583 |
_enter("%s", cell->name); |
08e0e7c82 [AF_RXRPC]: Make ... |
584 |
|
989782dcd afs: Overhaul cel... |
585 586 587 |
now = ktime_get_real_seconds(); cell->last_inactive = now; expire_delay = 0; |
d5c32c89b afs: Fix cell DNS... |
588 |
if (cell->vl_servers->nr_servers) |
989782dcd afs: Overhaul cel... |
589 |
expire_delay = afs_cell_gc_delay; |
1da177e4c Linux-2.6.12-rc2 |
590 |
|
acc080d15 afs: Fix tracing ... |
591 |
debug_id = cell->debug_id; |
dca54a7bb afs: Add tracing ... |
592 |
u = atomic_read(&cell->ref); |
88c853c3f afs: Fix cell ref... |
593 |
a = atomic_dec_return(&cell->active); |
dca54a7bb afs: Add tracing ... |
594 |
trace_afs_cell(debug_id, u, a, reason); |
88c853c3f afs: Fix cell ref... |
595 596 597 598 599 |
WARN_ON(a == 0); if (a == 1) /* 'cell' may now be garbage collected. */ afs_set_cell_timer(net, expire_delay); } |
1da177e4c Linux-2.6.12-rc2 |
600 |
|
88c853c3f afs: Fix cell ref... |
601 |
/* |
dca54a7bb afs: Add tracing ... |
602 603 604 605 606 607 608 609 610 611 612 613 |
* Note that a cell has been seen. */ void afs_see_cell(struct afs_cell *cell, enum afs_cell_trace reason) { int u, a; u = atomic_read(&cell->ref); a = atomic_read(&cell->active); trace_afs_cell(cell->debug_id, u, a, reason); } /* |
88c853c3f afs: Fix cell ref... |
614 615 |
* Queue a cell for management, giving the workqueue a ref to hold. */ |
dca54a7bb afs: Add tracing ... |
616 |
void afs_queue_cell(struct afs_cell *cell, enum afs_cell_trace reason) |
88c853c3f afs: Fix cell ref... |
617 |
{ |
dca54a7bb afs: Add tracing ... |
618 |
afs_get_cell(cell, reason); |
88c853c3f afs: Fix cell ref... |
619 |
if (!queue_work(afs_wq, &cell->manager)) |
dca54a7bb afs: Add tracing ... |
620 |
afs_put_cell(cell, afs_cell_trace_put_queue_fail); |
ec26815ad [AFS]: Clean up t... |
621 |
} |
1da177e4c Linux-2.6.12-rc2 |
622 |
|
1da177e4c Linux-2.6.12-rc2 |
623 |
/* |
989782dcd afs: Overhaul cel... |
624 |
* Allocate a key to use as a placeholder for anonymous user security. |
1da177e4c Linux-2.6.12-rc2 |
625 |
*/ |
989782dcd afs: Overhaul cel... |
626 |
static int afs_alloc_anon_key(struct afs_cell *cell) |
1da177e4c Linux-2.6.12-rc2 |
627 |
{ |
989782dcd afs: Overhaul cel... |
628 629 |
struct key *key; char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp; |
1da177e4c Linux-2.6.12-rc2 |
630 |
|
989782dcd afs: Overhaul cel... |
631 632 633 634 635 636 637 |
/* Create a key to represent an anonymous user. */ memcpy(keyname, "afs@", 4); dp = keyname + 4; cp = cell->name; do { *dp++ = tolower(*cp); } while (*cp++); |
1da177e4c Linux-2.6.12-rc2 |
638 |
|
989782dcd afs: Overhaul cel... |
639 640 641 |
key = rxrpc_get_null_key(keyname); if (IS_ERR(key)) return PTR_ERR(key); |
1da177e4c Linux-2.6.12-rc2 |
642 |
|
989782dcd afs: Overhaul cel... |
643 |
cell->anonymous_key = key; |
1da177e4c Linux-2.6.12-rc2 |
644 |
|
989782dcd afs: Overhaul cel... |
645 646 647 648 |
_debug("anon key %p{%x}", cell->anonymous_key, key_serial(cell->anonymous_key)); return 0; } |
1da177e4c Linux-2.6.12-rc2 |
649 |
|
989782dcd afs: Overhaul cel... |
650 651 652 653 654 |
/* * Activate a cell. */ static int afs_activate_cell(struct afs_net *net, struct afs_cell *cell) { |
6b3944e42 afs: Fix cell pro... |
655 656 |
struct hlist_node **p; struct afs_cell *pcell; |
989782dcd afs: Overhaul cel... |
657 658 659 660 661 662 |
int ret; if (!cell->anonymous_key) { ret = afs_alloc_anon_key(cell); if (ret < 0) return ret; |
08e0e7c82 [AF_RXRPC]: Make ... |
663 |
} |
989782dcd afs: Overhaul cel... |
664 665 666 |
#ifdef CONFIG_AFS_FSCACHE cell->cache = fscache_acquire_cookie(afs_cache_netfs.primary_index, &afs_cell_cache_index_def, |
402cb8dda fscache: Attach t... |
667 668 |
cell->name, strlen(cell->name), NULL, 0, |
ee1235a9a fscache: Pass obj... |
669 |
cell, 0, true); |
989782dcd afs: Overhaul cel... |
670 |
#endif |
5b86d4ff5 afs: Implement ne... |
671 |
ret = afs_proc_cell_setup(cell); |
989782dcd afs: Overhaul cel... |
672 673 |
if (ret < 0) return ret; |
0da0b7fd7 afs: Display manu... |
674 675 |
mutex_lock(&net->proc_cells_lock); |
6b3944e42 afs: Fix cell pro... |
676 677 678 679 680 681 682 683 684 685 686 |
for (p = &net->proc_cells.first; *p; p = &(*p)->next) { pcell = hlist_entry(*p, struct afs_cell, proc_link); if (strcmp(cell->name, pcell->name) < 0) break; } cell->proc_link.pprev = p; cell->proc_link.next = *p; rcu_assign_pointer(*p, &cell->proc_link.next); if (cell->proc_link.next) cell->proc_link.next->pprev = &cell->proc_link.next; |
0da0b7fd7 afs: Display manu... |
687 688 |
afs_dynroot_mkdir(net, cell); mutex_unlock(&net->proc_cells_lock); |
989782dcd afs: Overhaul cel... |
689 690 691 692 693 694 695 696 697 |
return 0; } /* * Deactivate a cell. */ static void afs_deactivate_cell(struct afs_net *net, struct afs_cell *cell) { _enter("%s", cell->name); |
1da177e4c Linux-2.6.12-rc2 |
698 |
|
5b86d4ff5 afs: Implement ne... |
699 |
afs_proc_cell_remove(cell); |
1da177e4c Linux-2.6.12-rc2 |
700 |
|
0da0b7fd7 afs: Display manu... |
701 |
mutex_lock(&net->proc_cells_lock); |
6b3944e42 afs: Fix cell pro... |
702 |
hlist_del_rcu(&cell->proc_link); |
0da0b7fd7 afs: Display manu... |
703 704 |
afs_dynroot_rmdir(net, cell); mutex_unlock(&net->proc_cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
705 |
|
9b3f26c91 FS-Cache: Make kA... |
706 |
#ifdef CONFIG_AFS_FSCACHE |
402cb8dda fscache: Attach t... |
707 |
fscache_relinquish_cookie(cell->cache, NULL, false); |
989782dcd afs: Overhaul cel... |
708 |
cell->cache = NULL; |
1da177e4c Linux-2.6.12-rc2 |
709 |
#endif |
1da177e4c Linux-2.6.12-rc2 |
710 |
|
989782dcd afs: Overhaul cel... |
711 |
_leave(""); |
ec26815ad [AFS]: Clean up t... |
712 |
} |
1da177e4c Linux-2.6.12-rc2 |
713 |
|
1da177e4c Linux-2.6.12-rc2 |
714 |
/* |
989782dcd afs: Overhaul cel... |
715 716 |
* Manage a cell record, initialising and destroying it, maintaining its DNS * records. |
1da177e4c Linux-2.6.12-rc2 |
717 |
*/ |
88c853c3f afs: Fix cell ref... |
718 |
static void afs_manage_cell(struct afs_cell *cell) |
1da177e4c Linux-2.6.12-rc2 |
719 |
{ |
989782dcd afs: Overhaul cel... |
720 |
struct afs_net *net = cell->net; |
88c853c3f afs: Fix cell ref... |
721 |
int ret, active; |
989782dcd afs: Overhaul cel... |
722 723 724 725 726 727 728 729 |
_enter("%s", cell->name); again: _debug("state %u", cell->state); switch (cell->state) { case AFS_CELL_INACTIVE: case AFS_CELL_FAILED: |
92e3cc91d afs: Fix rapid ce... |
730 |
down_write(&net->cells_lock); |
88c853c3f afs: Fix cell ref... |
731 |
active = 1; |
1d0e850a4 afs: Fix cell rem... |
732 |
if (atomic_try_cmpxchg_relaxed(&cell->active, &active, 0)) { |
989782dcd afs: Overhaul cel... |
733 |
rb_erase(&cell->net_node, &net->cells); |
dca54a7bb afs: Add tracing ... |
734 735 |
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), 0, afs_cell_trace_unuse_delete); |
1d0e850a4 afs: Fix cell rem... |
736 |
smp_store_release(&cell->state, AFS_CELL_REMOVED); |
88c853c3f afs: Fix cell ref... |
737 |
} |
92e3cc91d afs: Fix rapid ce... |
738 |
up_write(&net->cells_lock); |
1d0e850a4 afs: Fix cell rem... |
739 740 |
if (cell->state == AFS_CELL_REMOVED) { wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
741 |
goto final_destruction; |
1d0e850a4 afs: Fix cell rem... |
742 |
} |
989782dcd afs: Overhaul cel... |
743 744 |
if (cell->state == AFS_CELL_FAILED) goto done; |
d5c32c89b afs: Fix cell DNS... |
745 746 |
smp_store_release(&cell->state, AFS_CELL_UNSET); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
747 748 749 |
goto again; case AFS_CELL_UNSET: |
d5c32c89b afs: Fix cell DNS... |
750 751 |
smp_store_release(&cell->state, AFS_CELL_ACTIVATING); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
752 753 754 755 756 757 |
goto again; case AFS_CELL_ACTIVATING: ret = afs_activate_cell(net, cell); if (ret < 0) goto activation_failed; |
d5c32c89b afs: Fix cell DNS... |
758 759 |
smp_store_release(&cell->state, AFS_CELL_ACTIVE); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
760 761 762 |
goto again; case AFS_CELL_ACTIVE: |
88c853c3f afs: Fix cell ref... |
763 |
if (atomic_read(&cell->active) > 1) { |
d5c32c89b afs: Fix cell DNS... |
764 765 766 767 768 |
if (test_and_clear_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) { ret = afs_update_cell(cell); if (ret < 0) cell->error = ret; } |
989782dcd afs: Overhaul cel... |
769 770 |
goto done; } |
d5c32c89b afs: Fix cell DNS... |
771 772 |
smp_store_release(&cell->state, AFS_CELL_DEACTIVATING); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
773 774 775 |
goto again; case AFS_CELL_DEACTIVATING: |
88c853c3f afs: Fix cell ref... |
776 |
if (atomic_read(&cell->active) > 1) |
989782dcd afs: Overhaul cel... |
777 778 |
goto reverse_deactivation; afs_deactivate_cell(net, cell); |
d5c32c89b afs: Fix cell DNS... |
779 780 |
smp_store_release(&cell->state, AFS_CELL_INACTIVE); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
781 |
goto again; |
1d0e850a4 afs: Fix cell rem... |
782 783 |
case AFS_CELL_REMOVED: goto done; |
989782dcd afs: Overhaul cel... |
784 785 786 787 788 789 790 791 792 |
default: break; } _debug("bad state %u", cell->state); BUG(); /* Unhandled state */ activation_failed: cell->error = ret; afs_deactivate_cell(net, cell); |
d5c32c89b afs: Fix cell DNS... |
793 794 |
smp_store_release(&cell->state, AFS_CELL_FAILED); /* vs error */ wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
795 796 797 |
goto again; reverse_deactivation: |
d5c32c89b afs: Fix cell DNS... |
798 799 |
smp_store_release(&cell->state, AFS_CELL_ACTIVE); wake_up_var(&cell->state); |
989782dcd afs: Overhaul cel... |
800 801 802 803 804 805 806 807 |
_leave(" [deact->act]"); return; done: _leave(" [done %u]", cell->state); return; final_destruction: |
88c853c3f afs: Fix cell ref... |
808 809 810 |
/* The root volume is pinning the cell */ afs_put_volume(cell->net, cell->root_volume, afs_volume_trace_put_cell_root); cell->root_volume = NULL; |
dca54a7bb afs: Add tracing ... |
811 |
afs_put_cell(cell, afs_cell_trace_put_destroy); |
88c853c3f afs: Fix cell ref... |
812 813 814 815 816 817 818 |
} static void afs_manage_cell_work(struct work_struct *work) { struct afs_cell *cell = container_of(work, struct afs_cell, manager); afs_manage_cell(cell); |
dca54a7bb afs: Add tracing ... |
819 |
afs_put_cell(cell, afs_cell_trace_put_queue_work); |
989782dcd afs: Overhaul cel... |
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 |
} /* * Manage the records of cells known to a network namespace. This includes * updating the DNS records and garbage collecting unused cells that were * automatically added. * * Note that constructed cell records may only be removed from net->cells by * this work item, so it is safe for this work item to stash a cursor pointing * into the tree and then return to caller (provided it skips cells that are * still under construction). * * Note also that we were given an increment on net->cells_outstanding by * whoever queued us that we need to deal with before returning. */ void afs_manage_cells(struct work_struct *work) { struct afs_net *net = container_of(work, struct afs_net, cells_manager); struct rb_node *cursor; time64_t now = ktime_get_real_seconds(), next_manage = TIME64_MAX; bool purging = !net->live; |
1da177e4c Linux-2.6.12-rc2 |
841 842 |
_enter(""); |
989782dcd afs: Overhaul cel... |
843 844 845 846 |
/* Trawl the cell database looking for cells that have expired from * lack of use and cells whose DNS results have expired and dispatch * their managers. */ |
92e3cc91d afs: Fix rapid ce... |
847 |
down_read(&net->cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
848 |
|
989782dcd afs: Overhaul cel... |
849 850 851 |
for (cursor = rb_first(&net->cells); cursor; cursor = rb_next(cursor)) { struct afs_cell *cell = rb_entry(cursor, struct afs_cell, net_node); |
88c853c3f afs: Fix cell ref... |
852 |
unsigned active; |
989782dcd afs: Overhaul cel... |
853 |
bool sched_cell = false; |
08e0e7c82 [AF_RXRPC]: Make ... |
854 |
|
88c853c3f afs: Fix cell ref... |
855 |
active = atomic_read(&cell->active); |
dca54a7bb afs: Add tracing ... |
856 857 |
trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), active, afs_cell_trace_manage); |
989782dcd afs: Overhaul cel... |
858 |
|
88c853c3f afs: Fix cell ref... |
859 |
ASSERTCMP(active, >=, 1); |
989782dcd afs: Overhaul cel... |
860 861 |
if (purging) { |
dca54a7bb afs: Add tracing ... |
862 863 864 865 866 |
if (test_and_clear_bit(AFS_CELL_FL_NO_GC, &cell->flags)) { active = atomic_dec_return(&cell->active); trace_afs_cell(cell->debug_id, atomic_read(&cell->ref), active, afs_cell_trace_unuse_pin); } |
989782dcd afs: Overhaul cel... |
867 |
} |
1da177e4c Linux-2.6.12-rc2 |
868 |
|
88c853c3f afs: Fix cell ref... |
869 |
if (active == 1) { |
d5c32c89b afs: Fix cell DNS... |
870 |
struct afs_vlserver_list *vllist; |
989782dcd afs: Overhaul cel... |
871 |
time64_t expire_at = cell->last_inactive; |
1da177e4c Linux-2.6.12-rc2 |
872 |
|
d5c32c89b afs: Fix cell DNS... |
873 874 875 876 877 |
read_lock(&cell->vl_servers_lock); vllist = rcu_dereference_protected( cell->vl_servers, lockdep_is_held(&cell->vl_servers_lock)); if (vllist->nr_servers > 0) |
989782dcd afs: Overhaul cel... |
878 |
expire_at += afs_cell_gc_delay; |
d5c32c89b afs: Fix cell DNS... |
879 |
read_unlock(&cell->vl_servers_lock); |
989782dcd afs: Overhaul cel... |
880 881 882 883 |
if (purging || expire_at <= now) sched_cell = true; else if (expire_at < next_manage) next_manage = expire_at; |
1da177e4c Linux-2.6.12-rc2 |
884 |
} |
989782dcd afs: Overhaul cel... |
885 |
if (!purging) { |
d5c32c89b afs: Fix cell DNS... |
886 |
if (test_bit(AFS_CELL_FL_DO_LOOKUP, &cell->flags)) |
989782dcd afs: Overhaul cel... |
887 |
sched_cell = true; |
989782dcd afs: Overhaul cel... |
888 889 890 |
} if (sched_cell) |
dca54a7bb afs: Add tracing ... |
891 |
afs_queue_cell(cell, afs_cell_trace_get_queue_manage); |
989782dcd afs: Overhaul cel... |
892 |
} |
92e3cc91d afs: Fix rapid ce... |
893 |
up_read(&net->cells_lock); |
1da177e4c Linux-2.6.12-rc2 |
894 |
|
989782dcd afs: Overhaul cel... |
895 896 897 898 899 900 |
/* Update the timer on the way out. We have to pass an increment on * cells_outstanding in the namespace that we are in to the timer or * the work scheduler. */ if (!purging && next_manage < TIME64_MAX) { now = ktime_get_real_seconds(); |
1da177e4c Linux-2.6.12-rc2 |
901 |
|
989782dcd afs: Overhaul cel... |
902 903 904 905 906 |
if (next_manage - now <= 0) { if (queue_work(afs_wq, &net->cells_manager)) atomic_inc(&net->cells_outstanding); } else { afs_set_cell_timer(net, next_manage - now); |
1da177e4c Linux-2.6.12-rc2 |
907 908 |
} } |
989782dcd afs: Overhaul cel... |
909 910 911 912 913 914 915 916 917 918 919 920 |
afs_dec_cells_outstanding(net); _leave(" [%d]", atomic_read(&net->cells_outstanding)); } /* * Purge in-memory cell database. */ void afs_cell_purge(struct afs_net *net) { struct afs_cell *ws; _enter(""); |
92e3cc91d afs: Fix rapid ce... |
921 922 923 924 |
down_write(&net->cells_lock); ws = net->ws_cell; net->ws_cell = NULL; up_write(&net->cells_lock); |
dca54a7bb afs: Add tracing ... |
925 |
afs_unuse_cell(net, ws, afs_cell_trace_unuse_ws); |
989782dcd afs: Overhaul cel... |
926 927 928 929 930 931 932 933 934 |
_debug("del timer"); if (del_timer_sync(&net->cells_timer)) atomic_dec(&net->cells_outstanding); _debug("kick mgr"); afs_queue_cell_manager(net); _debug("wait"); |
ab1fbe324 sched/wait, fs/af... |
935 936 |
wait_var_event(&net->cells_outstanding, !atomic_read(&net->cells_outstanding)); |
1da177e4c Linux-2.6.12-rc2 |
937 |
_leave(""); |
ec26815ad [AFS]: Clean up t... |
938 |
} |