aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/vlocation.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-04-26 18:55:03 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-26 18:55:03 -0400
commit08e0e7c82eeadec6f4871a386b86bf0f0fbcb4eb (patch)
tree1c4f7e91e20e56ff2ec755e988a6ee828b1a21c0 /fs/afs/vlocation.c
parent651350d10f93bed7003c9a66e24cf25e0f8eed3d (diff)
[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
Make the in-kernel AFS filesystem use AF_RXRPC instead of the old RxRPC code. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/vlocation.c')
-rw-r--r--fs/afs/vlocation.c1153
1 files changed, 469 insertions, 684 deletions
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c
index e48728c92175..60cb2f408c75 100644
--- a/fs/afs/vlocation.c
+++ b/fs/afs/vlocation.c
@@ -1,6 +1,6 @@
1/* volume location management 1/* AFS volume location management
2 * 2 *
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -12,130 +12,60 @@
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/module.h> 13#include <linux/module.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/slab.h>
16#include <linux/fs.h>
17#include <linux/pagemap.h>
18#include "volume.h"
19#include "cell.h"
20#include "cmservice.h"
21#include "fsclient.h"
22#include "vlclient.h"
23#include "kafstimod.h"
24#include <rxrpc/connection.h>
25#include "internal.h" 15#include "internal.h"
26 16
27#define AFS_VLDB_TIMEOUT HZ*1000 17unsigned afs_vlocation_timeout = 10; /* volume location timeout in seconds */
18unsigned afs_vlocation_update_timeout = 10 * 60;
28 19
29static void afs_vlocation_update_timer(struct afs_timer *timer); 20static void afs_vlocation_reaper(struct work_struct *);
30static void afs_vlocation_update_attend(struct afs_async_op *op); 21static void afs_vlocation_updater(struct work_struct *);
31static void afs_vlocation_update_discard(struct afs_async_op *op);
32static void __afs_put_vlocation(struct afs_vlocation *vlocation);
33 22
34static void __afs_vlocation_timeout(struct afs_timer *timer) 23static LIST_HEAD(afs_vlocation_updates);
35{ 24static LIST_HEAD(afs_vlocation_graveyard);
36 struct afs_vlocation *vlocation = 25static DEFINE_SPINLOCK(afs_vlocation_updates_lock);
37 list_entry(timer, struct afs_vlocation, timeout); 26static DEFINE_SPINLOCK(afs_vlocation_graveyard_lock);
38 27static DECLARE_DELAYED_WORK(afs_vlocation_reap, afs_vlocation_reaper);
39 _debug("VL TIMEOUT [%s{u=%d}]", 28static DECLARE_DELAYED_WORK(afs_vlocation_update, afs_vlocation_updater);
40 vlocation->vldb.name, atomic_read(&vlocation->usage)); 29static struct workqueue_struct *afs_vlocation_update_worker;
41
42 afs_vlocation_do_timeout(vlocation);
43}
44
45static const struct afs_timer_ops afs_vlocation_timer_ops = {
46 .timed_out = __afs_vlocation_timeout,
47};
48
49static const struct afs_timer_ops afs_vlocation_update_timer_ops = {
50 .timed_out = afs_vlocation_update_timer,
51};
52
53static const struct afs_async_op_ops afs_vlocation_update_op_ops = {
54 .attend = afs_vlocation_update_attend,
55 .discard = afs_vlocation_update_discard,
56};
57
58static LIST_HEAD(afs_vlocation_update_pendq); /* queue of VLs awaiting update */
59static struct afs_vlocation *afs_vlocation_update; /* VL currently being updated */
60static DEFINE_SPINLOCK(afs_vlocation_update_lock); /* lock guarding update queue */
61
62#ifdef AFS_CACHING_SUPPORT
63static cachefs_match_val_t afs_vlocation_cache_match(void *target,
64 const void *entry);
65static void afs_vlocation_cache_update(void *source, void *entry);
66
67struct cachefs_index_def afs_vlocation_cache_index_def = {
68 .name = "vldb",
69 .data_size = sizeof(struct afs_cache_vlocation),
70 .keys[0] = { CACHEFS_INDEX_KEYS_ASCIIZ, 64 },
71 .match = afs_vlocation_cache_match,
72 .update = afs_vlocation_cache_update,
73};
74#endif
75 30
76/* 31/*
77 * iterate through the VL servers in a cell until one of them admits knowing 32 * iterate through the VL servers in a cell until one of them admits knowing
78 * about the volume in question 33 * about the volume in question
79 * - caller must have cell->vl_sem write-locked
80 */ 34 */
81static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vlocation, 35static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
82 const char *name,
83 unsigned namesz,
84 struct afs_cache_vlocation *vldb) 36 struct afs_cache_vlocation *vldb)
85{ 37{
86 struct afs_server *server = NULL; 38 struct afs_cell *cell = vl->cell;
87 struct afs_cell *cell = vlocation->cell; 39 struct in_addr addr;
88 int count, ret; 40 int count, ret;
89 41
90 _enter("%s,%*.*s,%u", cell->name, namesz, namesz, name, namesz); 42 _enter("%s,%s", cell->name, vl->vldb.name);
91 43
44 down_write(&vl->cell->vl_sem);
92 ret = -ENOMEDIUM; 45 ret = -ENOMEDIUM;
93 for (count = cell->vl_naddrs; count > 0; count--) { 46 for (count = cell->vl_naddrs; count > 0; count--) {
94 _debug("CellServ[%hu]: %08x", 47 addr = cell->vl_addrs[cell->vl_curr_svix];
95 cell->vl_curr_svix, 48
96 cell->vl_addrs[cell->vl_curr_svix].s_addr); 49 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
97
98 /* try and create a server */
99 ret = afs_server_lookup(cell,
100 &cell->vl_addrs[cell->vl_curr_svix],
101 &server);
102 switch (ret) {
103 case 0:
104 break;
105 case -ENOMEM:
106 case -ENONET:
107 goto out;
108 default:
109 goto rotate;
110 }
111 50
112 /* attempt to access the VL server */ 51 /* attempt to access the VL server */
113 ret = afs_rxvl_get_entry_by_name(server, name, namesz, vldb); 52 ret = afs_vl_get_entry_by_name(&addr, vl->vldb.name, vldb,
53 &afs_sync_call);
114 switch (ret) { 54 switch (ret) {
115 case 0: 55 case 0:
116 afs_put_server(server);
117 goto out; 56 goto out;
118 case -ENOMEM: 57 case -ENOMEM:
119 case -ENONET: 58 case -ENONET:
120 case -ENETUNREACH: 59 case -ENETUNREACH:
121 case -EHOSTUNREACH: 60 case -EHOSTUNREACH:
122 case -ECONNREFUSED: 61 case -ECONNREFUSED:
123 down_write(&server->sem);
124 if (server->vlserver) {
125 rxrpc_put_connection(server->vlserver);
126 server->vlserver = NULL;
127 }
128 up_write(&server->sem);
129 afs_put_server(server);
130 if (ret == -ENOMEM || ret == -ENONET) 62 if (ret == -ENOMEM || ret == -ENONET)
131 goto out; 63 goto out;
132 goto rotate; 64 goto rotate;
133 case -ENOMEDIUM: 65 case -ENOMEDIUM:
134 afs_put_server(server);
135 goto out; 66 goto out;
136 default: 67 default:
137 afs_put_server(server); 68 ret = -EIO;
138 ret = -ENOMEDIUM;
139 goto rotate; 69 goto rotate;
140 } 70 }
141 71
@@ -146,6 +76,7 @@ static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vlocation,
146 } 76 }
147 77
148out: 78out:
79 up_write(&vl->cell->vl_sem);
149 _leave(" = %d", ret); 80 _leave(" = %d", ret);
150 return ret; 81 return ret;
151} 82}
@@ -153,66 +84,56 @@ out:
153/* 84/*
154 * iterate through the VL servers in a cell until one of them admits knowing 85 * iterate through the VL servers in a cell until one of them admits knowing
155 * about the volume in question 86 * about the volume in question
156 * - caller must have cell->vl_sem write-locked
157 */ 87 */
158static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vlocation, 88static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
159 afs_volid_t volid, 89 afs_volid_t volid,
160 afs_voltype_t voltype, 90 afs_voltype_t voltype,
161 struct afs_cache_vlocation *vldb) 91 struct afs_cache_vlocation *vldb)
162{ 92{
163 struct afs_server *server = NULL; 93 struct afs_cell *cell = vl->cell;
164 struct afs_cell *cell = vlocation->cell; 94 struct in_addr addr;
165 int count, ret; 95 int count, ret;
166 96
167 _enter("%s,%x,%d,", cell->name, volid, voltype); 97 _enter("%s,%x,%d,", cell->name, volid, voltype);
168 98
99 down_write(&vl->cell->vl_sem);
169 ret = -ENOMEDIUM; 100 ret = -ENOMEDIUM;
170 for (count = cell->vl_naddrs; count > 0; count--) { 101 for (count = cell->vl_naddrs; count > 0; count--) {
171 _debug("CellServ[%hu]: %08x", 102 addr = cell->vl_addrs[cell->vl_curr_svix];
172 cell->vl_curr_svix, 103
173 cell->vl_addrs[cell->vl_curr_svix].s_addr); 104 _debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
174
175 /* try and create a server */
176 ret = afs_server_lookup(cell,
177 &cell->vl_addrs[cell->vl_curr_svix],
178 &server);
179 switch (ret) {
180 case 0:
181 break;
182 case -ENOMEM:
183 case -ENONET:
184 goto out;
185 default:
186 goto rotate;
187 }
188 105
189 /* attempt to access the VL server */ 106 /* attempt to access the VL server */
190 ret = afs_rxvl_get_entry_by_id(server, volid, voltype, vldb); 107 ret = afs_vl_get_entry_by_id(&addr, volid, voltype, vldb,
108 &afs_sync_call);
191 switch (ret) { 109 switch (ret) {
192 case 0: 110 case 0:
193 afs_put_server(server);
194 goto out; 111 goto out;
195 case -ENOMEM: 112 case -ENOMEM:
196 case -ENONET: 113 case -ENONET:
197 case -ENETUNREACH: 114 case -ENETUNREACH:
198 case -EHOSTUNREACH: 115 case -EHOSTUNREACH:
199 case -ECONNREFUSED: 116 case -ECONNREFUSED:
200 down_write(&server->sem);
201 if (server->vlserver) {
202 rxrpc_put_connection(server->vlserver);
203 server->vlserver = NULL;
204 }
205 up_write(&server->sem);
206 afs_put_server(server);
207 if (ret == -ENOMEM || ret == -ENONET) 117 if (ret == -ENOMEM || ret == -ENONET)
208 goto out; 118 goto out;
209 goto rotate; 119 goto rotate;
120 case -EBUSY:
121 vl->upd_busy_cnt++;
122 if (vl->upd_busy_cnt <= 3) {
123 if (vl->upd_busy_cnt > 1) {
124 /* second+ BUSY - sleep a little bit */
125 set_current_state(TASK_UNINTERRUPTIBLE);
126 schedule_timeout(1);
127 __set_current_state(TASK_RUNNING);
128 }
129 continue;
130 }
131 break;
210 case -ENOMEDIUM: 132 case -ENOMEDIUM:
211 afs_put_server(server); 133 vl->upd_rej_cnt++;
212 goto out; 134 goto rotate;
213 default: 135 default:
214 afs_put_server(server); 136 ret = -EIO;
215 ret = -ENOMEDIUM;
216 goto rotate; 137 goto rotate;
217 } 138 }
218 139
@@ -220,150 +141,83 @@ static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vlocation,
220 rotate: 141 rotate:
221 cell->vl_curr_svix++; 142 cell->vl_curr_svix++;
222 cell->vl_curr_svix %= cell->vl_naddrs; 143 cell->vl_curr_svix %= cell->vl_naddrs;
144 vl->upd_busy_cnt = 0;
223 } 145 }
224 146
225out: 147out:
148 if (ret < 0 && vl->upd_rej_cnt > 0) {
149 printk(KERN_NOTICE "kAFS:"
150 " Active volume no longer valid '%s'\n",
151 vl->vldb.name);
152 vl->valid = 0;
153 ret = -ENOMEDIUM;
154 }
155
156 up_write(&vl->cell->vl_sem);
226 _leave(" = %d", ret); 157 _leave(" = %d", ret);
227 return ret; 158 return ret;
228} 159}
229 160
230/* 161/*
231 * lookup volume location 162 * allocate a volume location record
232 * - caller must have cell->vol_sem write-locked
233 * - iterate through the VL servers in a cell until one of them admits knowing
234 * about the volume in question
235 * - lookup in the local cache if not able to find on the VL server
236 * - insert/update in the local cache if did get a VL response
237 */ 163 */
238int afs_vlocation_lookup(struct afs_cell *cell, 164static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
239 const char *name, 165 const char *name,
240 unsigned namesz, 166 size_t namesz)
241 struct afs_vlocation **_vlocation)
242{ 167{
243 struct afs_cache_vlocation vldb; 168 struct afs_vlocation *vl;
244 struct afs_vlocation *vlocation; 169
245 afs_voltype_t voltype; 170 vl = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
246 afs_volid_t vid; 171 if (vl) {
247 int active = 0, ret; 172 vl->cell = cell;
248 173 vl->state = AFS_VL_NEW;
249 _enter("{%s},%*.*s,%u,", cell->name, namesz, namesz, name, namesz); 174 atomic_set(&vl->usage, 1);
250 175 INIT_LIST_HEAD(&vl->link);
251 if (namesz > sizeof(vlocation->vldb.name)) { 176 INIT_LIST_HEAD(&vl->grave);
252 _leave(" = -ENAMETOOLONG"); 177 INIT_LIST_HEAD(&vl->update);
253 return -ENAMETOOLONG; 178 init_waitqueue_head(&vl->waitq);
254 } 179 rwlock_init(&vl->lock);
255 180 memcpy(vl->vldb.name, name, namesz);
256 /* search the cell's active list first */
257 list_for_each_entry(vlocation, &cell->vl_list, link) {
258 if (namesz < sizeof(vlocation->vldb.name) &&
259 vlocation->vldb.name[namesz] != '\0')
260 continue;
261
262 if (memcmp(vlocation->vldb.name, name, namesz) == 0)
263 goto found_in_memory;
264 }
265
266 /* search the cell's graveyard list second */
267 spin_lock(&cell->vl_gylock);
268 list_for_each_entry(vlocation, &cell->vl_graveyard, link) {
269 if (namesz < sizeof(vlocation->vldb.name) &&
270 vlocation->vldb.name[namesz] != '\0')
271 continue;
272
273 if (memcmp(vlocation->vldb.name, name, namesz) == 0)
274 goto found_in_graveyard;
275 }
276 spin_unlock(&cell->vl_gylock);
277
278 /* not in the cell's in-memory lists - create a new record */
279 vlocation = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
280 if (!vlocation)
281 return -ENOMEM;
282
283 atomic_set(&vlocation->usage, 1);
284 INIT_LIST_HEAD(&vlocation->link);
285 rwlock_init(&vlocation->lock);
286 memcpy(vlocation->vldb.name, name, namesz);
287
288 afs_timer_init(&vlocation->timeout, &afs_vlocation_timer_ops);
289 afs_timer_init(&vlocation->upd_timer, &afs_vlocation_update_timer_ops);
290 afs_async_op_init(&vlocation->upd_op, &afs_vlocation_update_op_ops);
291
292 afs_get_cell(cell);
293 vlocation->cell = cell;
294
295 list_add_tail(&vlocation->link, &cell->vl_list);
296
297#ifdef AFS_CACHING_SUPPORT
298 /* we want to store it in the cache, plus it might already be
299 * encached */
300 cachefs_acquire_cookie(cell->cache,
301 &afs_volume_cache_index_def,
302 vlocation,
303 &vlocation->cache);
304
305 if (vlocation->valid)
306 goto found_in_cache;
307#endif
308
309 /* try to look up an unknown volume in the cell VL databases by name */
310 ret = afs_vlocation_access_vl_by_name(vlocation, name, namesz, &vldb);
311 if (ret < 0) {
312 printk("kAFS: failed to locate '%*.*s' in cell '%s'\n",
313 namesz, namesz, name, cell->name);
314 goto error;
315 } 181 }
316 182
317 goto found_on_vlserver; 183 _leave(" = %p", vl);
318 184 return vl;
319found_in_graveyard: 185}
320 /* found in the graveyard - resurrect */
321 _debug("found in graveyard");
322 atomic_inc(&vlocation->usage);
323 list_move_tail(&vlocation->link, &cell->vl_list);
324 spin_unlock(&cell->vl_gylock);
325
326 afs_kafstimod_del_timer(&vlocation->timeout);
327 goto active;
328
329found_in_memory:
330 /* found in memory - check to see if it's active */
331 _debug("found in memory");
332 atomic_inc(&vlocation->usage);
333 186
334active: 187/*
335 active = 1; 188 * update record if we found it in the cache
189 */
190static int afs_vlocation_update_record(struct afs_vlocation *vl,
191 struct afs_cache_vlocation *vldb)
192{
193 afs_voltype_t voltype;
194 afs_volid_t vid;
195 int ret;
336 196
337#ifdef AFS_CACHING_SUPPORT
338found_in_cache:
339#endif
340 /* try to look up a cached volume in the cell VL databases by ID */ 197 /* try to look up a cached volume in the cell VL databases by ID */
341 _debug("found in cache");
342
343 _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }", 198 _debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
344 vlocation->vldb.name, 199 vl->vldb.name,
345 vlocation->vldb.vidmask, 200 vl->vldb.vidmask,
346 ntohl(vlocation->vldb.servers[0].s_addr), 201 ntohl(vl->vldb.servers[0].s_addr),
347 vlocation->vldb.srvtmask[0], 202 vl->vldb.srvtmask[0],
348 ntohl(vlocation->vldb.servers[1].s_addr), 203 ntohl(vl->vldb.servers[1].s_addr),
349 vlocation->vldb.srvtmask[1], 204 vl->vldb.srvtmask[1],
350 ntohl(vlocation->vldb.servers[2].s_addr), 205 ntohl(vl->vldb.servers[2].s_addr),
351 vlocation->vldb.srvtmask[2] 206 vl->vldb.srvtmask[2]);
352 );
353 207
354 _debug("Vids: %08x %08x %08x", 208 _debug("Vids: %08x %08x %08x",
355 vlocation->vldb.vid[0], 209 vl->vldb.vid[0],
356 vlocation->vldb.vid[1], 210 vl->vldb.vid[1],
357 vlocation->vldb.vid[2]); 211 vl->vldb.vid[2]);
358 212
359 if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) { 213 if (vl->vldb.vidmask & AFS_VOL_VTM_RW) {
360 vid = vlocation->vldb.vid[0]; 214 vid = vl->vldb.vid[0];
361 voltype = AFSVL_RWVOL; 215 voltype = AFSVL_RWVOL;
362 } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) { 216 } else if (vl->vldb.vidmask & AFS_VOL_VTM_RO) {
363 vid = vlocation->vldb.vid[1]; 217 vid = vl->vldb.vid[1];
364 voltype = AFSVL_ROVOL; 218 voltype = AFSVL_ROVOL;
365 } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) { 219 } else if (vl->vldb.vidmask & AFS_VOL_VTM_BAK) {
366 vid = vlocation->vldb.vid[2]; 220 vid = vl->vldb.vid[2];
367 voltype = AFSVL_BACKVOL; 221 voltype = AFSVL_BACKVOL;
368 } else { 222 } else {
369 BUG(); 223 BUG();
@@ -371,551 +225,482 @@ found_in_cache:
371 voltype = 0; 225 voltype = 0;
372 } 226 }
373 227
374 ret = afs_vlocation_access_vl_by_id(vlocation, vid, voltype, &vldb); 228 /* contact the server to make sure the volume is still available
229 * - TODO: need to handle disconnected operation here
230 */
231 ret = afs_vlocation_access_vl_by_id(vl, vid, voltype, vldb);
375 switch (ret) { 232 switch (ret) {
376 /* net error */ 233 /* net error */
377 default: 234 default:
378 printk("kAFS: failed to volume '%*.*s' (%x) up in '%s': %d\n", 235 printk(KERN_WARNING "kAFS:"
379 namesz, namesz, name, vid, cell->name, ret); 236 " failed to update volume '%s' (%x) up in '%s': %d\n",
380 goto error; 237 vl->vldb.name, vid, vl->cell->name, ret);
238 _leave(" = %d", ret);
239 return ret;
381 240
382 /* pulled from local cache into memory */ 241 /* pulled from local cache into memory */
383 case 0: 242 case 0:
384 goto found_on_vlserver; 243 _leave(" = 0");
244 return 0;
385 245
386 /* uh oh... looks like the volume got deleted */ 246 /* uh oh... looks like the volume got deleted */
387 case -ENOMEDIUM: 247 case -ENOMEDIUM:
388 printk("kAFS: volume '%*.*s' (%x) does not exist '%s'\n", 248 printk(KERN_ERR "kAFS:"
389 namesz, namesz, name, vid, cell->name); 249 " volume '%s' (%x) does not exist '%s'\n",
250 vl->vldb.name, vid, vl->cell->name);
390 251
391 /* TODO: make existing record unavailable */ 252 /* TODO: make existing record unavailable */
392 goto error; 253 _leave(" = %d", ret);
254 return ret;
393 } 255 }
256}
394 257
395found_on_vlserver: 258/*
396 _debug("Done VL Lookup: %*.*s %02x { %08x(%x) %08x(%x) %08x(%x) }", 259 * apply the update to a VL record
397 namesz, namesz, name, 260 */
398 vldb.vidmask, 261static void afs_vlocation_apply_update(struct afs_vlocation *vl,
399 ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0], 262 struct afs_cache_vlocation *vldb)
400 ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1], 263{
401 ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2] 264 _debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
402 ); 265 vldb->name, vldb->vidmask,
403 266 ntohl(vldb->servers[0].s_addr), vldb->srvtmask[0],
404 _debug("Vids: %08x %08x %08x", vldb.vid[0], vldb.vid[1], vldb.vid[2]); 267 ntohl(vldb->servers[1].s_addr), vldb->srvtmask[1],
268 ntohl(vldb->servers[2].s_addr), vldb->srvtmask[2]);
405 269
406 if ((namesz < sizeof(vlocation->vldb.name) && 270 _debug("Vids: %08x %08x %08x",
407 vlocation->vldb.name[namesz] != '\0') || 271 vldb->vid[0], vldb->vid[1], vldb->vid[2]);
408 memcmp(vldb.name, name, namesz) != 0)
409 printk("kAFS: name of volume '%*.*s' changed to '%s' on server\n",
410 namesz, namesz, name, vldb.name);
411 272
412 memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb)); 273 if (strcmp(vldb->name, vl->vldb.name) != 0)
274 printk(KERN_NOTICE "kAFS:"
275 " name of volume '%s' changed to '%s' on server\n",
276 vl->vldb.name, vldb->name);
413 277
414 afs_kafstimod_add_timer(&vlocation->upd_timer, 10 * HZ); 278 vl->vldb = *vldb;
415 279
416#ifdef AFS_CACHING_SUPPORT 280#ifdef AFS_CACHING_SUPPORT
417 /* update volume entry in local cache */ 281 /* update volume entry in local cache */
418 cachefs_update_cookie(vlocation->cache); 282 cachefs_update_cookie(vl->cache);
419#endif
420
421 *_vlocation = vlocation;
422 _leave(" = 0 (%p)",vlocation);
423 return 0;
424
425error:
426 if (vlocation) {
427 if (active) {
428 __afs_put_vlocation(vlocation);
429 } else {
430 list_del(&vlocation->link);
431#ifdef AFS_CACHING_SUPPORT
432 cachefs_relinquish_cookie(vlocation->cache, 0);
433#endif 283#endif
434 afs_put_cell(vlocation->cell);
435 kfree(vlocation);
436 }
437 }
438
439 _leave(" = %d", ret);
440 return ret;
441} 284}
442 285
443/* 286/*
444 * finish using a volume location record 287 * fill in a volume location record, consulting the cache and the VL server
445 * - caller must have cell->vol_sem write-locked 288 * both
446 */ 289 */
447static void __afs_put_vlocation(struct afs_vlocation *vlocation) 290static int afs_vlocation_fill_in_record(struct afs_vlocation *vl)
448{ 291{
449 struct afs_cell *cell; 292 struct afs_cache_vlocation vldb;
293 int ret;
450 294
451 if (!vlocation) 295 _enter("");
452 return;
453 296
454 _enter("%s", vlocation->vldb.name); 297 ASSERTCMP(vl->valid, ==, 0);
455 298
456 cell = vlocation->cell; 299 memset(&vldb, 0, sizeof(vldb));
457 300
458 /* sanity check */ 301 /* see if we have an in-cache copy (will set vl->valid if there is) */
459 BUG_ON(atomic_read(&vlocation->usage) <= 0); 302#ifdef AFS_CACHING_SUPPORT
303 cachefs_acquire_cookie(cell->cache,
304 &afs_volume_cache_index_def,
305 vlocation,
306 &vl->cache);
307#endif
460 308
461 spin_lock(&cell->vl_gylock); 309 if (vl->valid) {
462 if (likely(!atomic_dec_and_test(&vlocation->usage))) { 310 /* try to update a known volume in the cell VL databases by
463 spin_unlock(&cell->vl_gylock); 311 * ID as the name may have changed */
464 _leave(""); 312 _debug("found in cache");
465 return; 313 ret = afs_vlocation_update_record(vl, &vldb);
314 } else {
315 /* try to look up an unknown volume in the cell VL databases by
316 * name */
317 ret = afs_vlocation_access_vl_by_name(vl, &vldb);
318 if (ret < 0) {
319 printk("kAFS: failed to locate '%s' in cell '%s'\n",
320 vl->vldb.name, vl->cell->name);
321 return ret;
322 }
466 } 323 }
467 324
468 /* move to graveyard queue */ 325 afs_vlocation_apply_update(vl, &vldb);
469 list_move_tail(&vlocation->link,&cell->vl_graveyard); 326 _leave(" = 0");
470 327 return 0;
471 /* remove from pending timeout queue (refcounted if actually being
472 * updated) */
473 list_del_init(&vlocation->upd_op.link);
474
475 /* time out in 10 secs */
476 afs_kafstimod_del_timer(&vlocation->upd_timer);
477 afs_kafstimod_add_timer(&vlocation->timeout, 10 * HZ);
478
479 spin_unlock(&cell->vl_gylock);
480
481 _leave(" [killed]");
482} 328}
483 329
484/* 330/*
485 * finish using a volume location record 331 * queue a vlocation record for updates
486 */ 332 */
487void afs_put_vlocation(struct afs_vlocation *vlocation) 333void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
488{ 334{
489 if (vlocation) { 335 struct afs_vlocation *xvl;
490 struct afs_cell *cell = vlocation->cell;
491 336
492 down_write(&cell->vl_sem); 337 /* wait at least 10 minutes before updating... */
493 __afs_put_vlocation(vlocation); 338 vl->update_at = get_seconds() + afs_vlocation_update_timeout;
494 up_write(&cell->vl_sem); 339
340 spin_lock(&afs_vlocation_updates_lock);
341
342 if (!list_empty(&afs_vlocation_updates)) {
343 /* ... but wait at least 1 second more than the newest record
344 * already queued so that we don't spam the VL server suddenly
345 * with lots of requests
346 */
347 xvl = list_entry(afs_vlocation_updates.prev,
348 struct afs_vlocation, update);
349 if (vl->update_at <= xvl->update_at)
350 vl->update_at = xvl->update_at + 1;
351 } else {
352 queue_delayed_work(afs_vlocation_update_worker,
353 &afs_vlocation_update,
354 afs_vlocation_update_timeout * HZ);
495 } 355 }
356
357 list_add_tail(&vl->update, &afs_vlocation_updates);
358 spin_unlock(&afs_vlocation_updates_lock);
496} 359}
497 360
498/* 361/*
499 * timeout vlocation record 362 * lookup volume location
500 * - removes from the cell's graveyard if the usage count is zero 363 * - iterate through the VL servers in a cell until one of them admits knowing
364 * about the volume in question
365 * - lookup in the local cache if not able to find on the VL server
366 * - insert/update in the local cache if did get a VL response
501 */ 367 */
502void afs_vlocation_do_timeout(struct afs_vlocation *vlocation) 368struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
369 const char *name,
370 size_t namesz)
503{ 371{
504 struct afs_cell *cell; 372 struct afs_vlocation *vl;
505 373 int ret;
506 _enter("%s", vlocation->vldb.name);
507
508 cell = vlocation->cell;
509 374
510 BUG_ON(atomic_read(&vlocation->usage) < 0); 375 _enter("{%s},%*.*s,%zu",
376 cell->name, (int) namesz, (int) namesz, name, namesz);
511 377
512 /* remove from graveyard if still dead */ 378 if (namesz > sizeof(vl->vldb.name)) {
513 spin_lock(&cell->vl_gylock); 379 _leave(" = -ENAMETOOLONG");
514 if (atomic_read(&vlocation->usage) == 0) 380 return ERR_PTR(-ENAMETOOLONG);
515 list_del_init(&vlocation->link); 381 }
516 else
517 vlocation = NULL;
518 spin_unlock(&cell->vl_gylock);
519 382
520 if (!vlocation) { 383 /* see if we have an in-memory copy first */
521 _leave(""); 384 down_write(&cell->vl_sem);
522 return; /* resurrected */ 385 spin_lock(&cell->vl_lock);
386 list_for_each_entry(vl, &cell->vl_list, link) {
387 if (vl->vldb.name[namesz] != '\0')
388 continue;
389 if (memcmp(vl->vldb.name, name, namesz) == 0)
390 goto found_in_memory;
523 } 391 }
392 spin_unlock(&cell->vl_lock);
524 393
525 /* we can now destroy it properly */ 394 /* not in the cell's in-memory lists - create a new record */
526#ifdef AFS_CACHING_SUPPORT 395 vl = afs_vlocation_alloc(cell, name, namesz);
527 cachefs_relinquish_cookie(vlocation->cache, 0); 396 if (!vl) {
528#endif 397 up_write(&cell->vl_sem);
529 afs_put_cell(cell); 398 return ERR_PTR(-ENOMEM);
399 }
530 400
531 kfree(vlocation); 401 afs_get_cell(cell);
532 402
533 _leave(" [destroyed]"); 403 list_add_tail(&vl->link, &cell->vl_list);
534} 404 vl->state = AFS_VL_CREATING;
405 up_write(&cell->vl_sem);
535 406
536/* 407fill_in_record:
537 * send an update operation to the currently selected server 408 ret = afs_vlocation_fill_in_record(vl);
538 */ 409 if (ret < 0)
539static int afs_vlocation_update_begin(struct afs_vlocation *vlocation) 410 goto error_abandon;
540{ 411 vl->state = AFS_VL_VALID;
541 afs_voltype_t voltype; 412 wake_up(&vl->waitq);
542 afs_volid_t vid;
543 int ret;
544 413
545 _enter("%s{ufs=%u ucs=%u}", 414 /* schedule for regular updates */
546 vlocation->vldb.name, 415 afs_vlocation_queue_for_updates(vl);
547 vlocation->upd_first_svix, 416 goto success;
548 vlocation->upd_curr_svix);
549 417
550 /* try to look up a cached volume in the cell VL databases by ID */ 418found_in_memory:
551 if (vlocation->vldb.vidmask & AFS_VOL_VTM_RW) { 419 /* found in memory */
552 vid = vlocation->vldb.vid[0]; 420 _debug("found in memory");
553 voltype = AFSVL_RWVOL; 421 atomic_inc(&vl->usage);
554 } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_RO) { 422 spin_unlock(&cell->vl_lock);
555 vid = vlocation->vldb.vid[1]; 423 if (!list_empty(&vl->grave)) {
556 voltype = AFSVL_ROVOL; 424 spin_lock(&afs_vlocation_graveyard_lock);
557 } else if (vlocation->vldb.vidmask & AFS_VOL_VTM_BAK) { 425 list_del_init(&vl->grave);
558 vid = vlocation->vldb.vid[2]; 426 spin_unlock(&afs_vlocation_graveyard_lock);
559 voltype = AFSVL_BACKVOL;
560 } else {
561 BUG();
562 vid = 0;
563 voltype = 0;
564 } 427 }
428 up_write(&cell->vl_sem);
565 429
566 /* contact the chosen server */ 430 /* see if it was an abandoned record that we might try filling in */
567 ret = afs_server_lookup( 431 while (vl->state != AFS_VL_VALID) {
568 vlocation->cell, 432 afs_vlocation_state_t state = vl->state;
569 &vlocation->cell->vl_addrs[vlocation->upd_curr_svix],
570 &vlocation->upd_op.server);
571 433
572 switch (ret) { 434 _debug("invalid [state %d]", state);
573 case 0:
574 break;
575 case -ENOMEM:
576 case -ENONET:
577 default:
578 _leave(" = %d", ret);
579 return ret;
580 }
581 435
582 /* initiate the update operation */ 436 if ((state == AFS_VL_NEW || state == AFS_VL_NO_VOLUME)) {
583 ret = afs_rxvl_get_entry_by_id_async(&vlocation->upd_op, vid, voltype); 437 if (cmpxchg(&vl->state, state, AFS_VL_CREATING) ==
584 if (ret < 0) { 438 state)
585 _leave(" = %d", ret); 439 goto fill_in_record;
586 return ret; 440 continue;
441 }
442
443 /* must now wait for creation or update by someone else to
444 * complete */
445 _debug("wait");
446
447 ret = wait_event_interruptible(
448 vl->waitq,
449 vl->state == AFS_VL_NEW ||
450 vl->state == AFS_VL_VALID ||
451 vl->state == AFS_VL_NO_VOLUME);
452 if (ret < 0)
453 goto error;
587 } 454 }
588 455
456success:
457 _leave(" = %p",vl);
458 return vl;
459
460error_abandon:
461 vl->state = AFS_VL_NEW;
462 wake_up(&vl->waitq);
463error:
464 ASSERT(vl != NULL);
465 afs_put_vlocation(vl);
589 _leave(" = %d", ret); 466 _leave(" = %d", ret);
590 return ret; 467 return ERR_PTR(ret);
591} 468}
592 469
593/* 470/*
594 * abandon updating a VL record 471 * finish using a volume location record
595 * - does not restart the update timer
596 */ 472 */
597static void afs_vlocation_update_abandon(struct afs_vlocation *vlocation, 473void afs_put_vlocation(struct afs_vlocation *vl)
598 afs_vlocation_upd_t state,
599 int ret)
600{ 474{
601 _enter("%s,%u", vlocation->vldb.name, state); 475 if (!vl)
602 476 return;
603 if (ret < 0)
604 printk("kAFS: Abandoning VL update '%s': %d\n",
605 vlocation->vldb.name, ret);
606
607 /* discard the server record */
608 afs_put_server(vlocation->upd_op.server);
609 vlocation->upd_op.server = NULL;
610 477
611 spin_lock(&afs_vlocation_update_lock); 478 _enter("%s", vl->vldb.name);
612 afs_vlocation_update = NULL;
613 vlocation->upd_state = state;
614 479
615 /* TODO: start updating next VL record on pending list */ 480 ASSERTCMP(atomic_read(&vl->usage), >, 0);
616 481
617 spin_unlock(&afs_vlocation_update_lock); 482 if (likely(!atomic_dec_and_test(&vl->usage))) {
483 _leave("");
484 return;
485 }
618 486
619 _leave(""); 487 spin_lock(&afs_vlocation_graveyard_lock);
488 if (atomic_read(&vl->usage) == 0) {
489 _debug("buried");
490 list_move_tail(&vl->grave, &afs_vlocation_graveyard);
491 vl->time_of_death = get_seconds();
492 schedule_delayed_work(&afs_vlocation_reap,
493 afs_vlocation_timeout * HZ);
494
495 /* suspend updates on this record */
496 if (!list_empty(&vl->update)) {
497 spin_lock(&afs_vlocation_updates_lock);
498 list_del_init(&vl->update);
499 spin_unlock(&afs_vlocation_updates_lock);
500 }
501 }
502 spin_unlock(&afs_vlocation_graveyard_lock);
503 _leave(" [killed?]");
620} 504}
621 505
622/* 506/*
623 * handle periodic update timeouts and busy retry timeouts 507 * destroy a dead volume location record
624 * - called from kafstimod
625 */ 508 */
626static void afs_vlocation_update_timer(struct afs_timer *timer) 509static void afs_vlocation_destroy(struct afs_vlocation *vl)
627{ 510{
628 struct afs_vlocation *vlocation = 511 _enter("%p", vl);
629 list_entry(timer, struct afs_vlocation, upd_timer);
630 int ret;
631 512
632 _enter("%s", vlocation->vldb.name); 513#ifdef AFS_CACHING_SUPPORT
514 cachefs_relinquish_cookie(vl->cache, 0);
515#endif
633 516
634 /* only update if not in the graveyard (defend against putting too) */ 517 afs_put_cell(vl->cell);
635 spin_lock(&vlocation->cell->vl_gylock); 518 kfree(vl);
519}
520
521/*
522 * reap dead volume location records
523 */
524static void afs_vlocation_reaper(struct work_struct *work)
525{
526 LIST_HEAD(corpses);
527 struct afs_vlocation *vl;
528 unsigned long delay, expiry;
529 time_t now;
636 530
637 if (!atomic_read(&vlocation->usage)) 531 _enter("");
638 goto out_unlock1;
639 532
640 spin_lock(&afs_vlocation_update_lock); 533 now = get_seconds();
534 spin_lock(&afs_vlocation_graveyard_lock);
535
536 while (!list_empty(&afs_vlocation_graveyard)) {
537 vl = list_entry(afs_vlocation_graveyard.next,
538 struct afs_vlocation, grave);
539
540 _debug("check %p", vl);
541
542 /* the queue is ordered most dead first */
543 expiry = vl->time_of_death + afs_vlocation_timeout;
544 if (expiry > now) {
545 delay = (expiry - now) * HZ;
546 _debug("delay %lu", delay);
547 if (!schedule_delayed_work(&afs_vlocation_reap,
548 delay)) {
549 cancel_delayed_work(&afs_vlocation_reap);
550 schedule_delayed_work(&afs_vlocation_reap,
551 delay);
552 }
553 break;
554 }
641 555
642 /* if we were woken up due to EBUSY sleep then restart immediately if 556 spin_lock(&vl->cell->vl_lock);
643 * possible or else jump to front of pending queue */ 557 if (atomic_read(&vl->usage) > 0) {
644 if (vlocation->upd_state == AFS_VLUPD_BUSYSLEEP) { 558 _debug("no reap");
645 if (afs_vlocation_update) { 559 list_del_init(&vl->grave);
646 list_add(&vlocation->upd_op.link,
647 &afs_vlocation_update_pendq);
648 } else { 560 } else {
649 afs_get_vlocation(vlocation); 561 _debug("reap");
650 afs_vlocation_update = vlocation; 562 list_move_tail(&vl->grave, &corpses);
651 vlocation->upd_state = AFS_VLUPD_INPROGRESS; 563 list_del_init(&vl->link);
652 } 564 }
653 goto out_unlock2; 565 spin_unlock(&vl->cell->vl_lock);
654 } 566 }
655 567
656 /* put on pending queue if there's already another update in progress */ 568 spin_unlock(&afs_vlocation_graveyard_lock);
657 if (afs_vlocation_update) {
658 vlocation->upd_state = AFS_VLUPD_PENDING;
659 list_add_tail(&vlocation->upd_op.link,
660 &afs_vlocation_update_pendq);
661 goto out_unlock2;
662 }
663 569
664 /* hold a ref on it while actually updating */ 570 /* now reap the corpses we've extracted */
665 afs_get_vlocation(vlocation); 571 while (!list_empty(&corpses)) {
666 afs_vlocation_update = vlocation; 572 vl = list_entry(corpses.next, struct afs_vlocation, grave);
667 vlocation->upd_state = AFS_VLUPD_INPROGRESS; 573 list_del(&vl->grave);
668 574 afs_vlocation_destroy(vl);
669 spin_unlock(&afs_vlocation_update_lock);
670 spin_unlock(&vlocation->cell->vl_gylock);
671
672 /* okay... we can start the update */
673 _debug("BEGIN VL UPDATE [%s]", vlocation->vldb.name);
674 vlocation->upd_first_svix = vlocation->cell->vl_curr_svix;
675 vlocation->upd_curr_svix = vlocation->upd_first_svix;
676 vlocation->upd_rej_cnt = 0;
677 vlocation->upd_busy_cnt = 0;
678
679 ret = afs_vlocation_update_begin(vlocation);
680 if (ret < 0) {
681 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret);
682 afs_kafstimod_add_timer(&vlocation->upd_timer,
683 AFS_VLDB_TIMEOUT);
684 afs_put_vlocation(vlocation);
685 } 575 }
686 576
687 _leave(""); 577 _leave("");
688 return; 578}
689 579
690out_unlock2: 580/*
691 spin_unlock(&afs_vlocation_update_lock); 581 * initialise the VL update process
692out_unlock1: 582 */
693 spin_unlock(&vlocation->cell->vl_gylock); 583int __init afs_vlocation_update_init(void)
694 _leave(""); 584{
585 afs_vlocation_update_worker =
586 create_singlethread_workqueue("kafs_vlupdated");
587 return afs_vlocation_update_worker ? 0 : -ENOMEM;
588}
589
590/*
591 * discard all the volume location records for rmmod
592 */
593void __exit afs_vlocation_purge(void)
594{
595 afs_vlocation_timeout = 0;
596
597 spin_lock(&afs_vlocation_updates_lock);
598 list_del_init(&afs_vlocation_updates);
599 spin_unlock(&afs_vlocation_updates_lock);
600 cancel_delayed_work(&afs_vlocation_update);
601 queue_delayed_work(afs_vlocation_update_worker,
602 &afs_vlocation_update, 0);
603 destroy_workqueue(afs_vlocation_update_worker);
604
605 cancel_delayed_work(&afs_vlocation_reap);
606 schedule_delayed_work(&afs_vlocation_reap, 0);
695} 607}
696 608
697/* 609/*
698 * attend to an update operation upon which an event happened 610 * update a volume location
699 * - called in kafsasyncd context
700 */ 611 */
701static void afs_vlocation_update_attend(struct afs_async_op *op) 612static void afs_vlocation_updater(struct work_struct *work)
702{ 613{
703 struct afs_cache_vlocation vldb; 614 struct afs_cache_vlocation vldb;
704 struct afs_vlocation *vlocation = 615 struct afs_vlocation *vl, *xvl;
705 list_entry(op, struct afs_vlocation, upd_op); 616 time_t now;
706 unsigned tmp; 617 long timeout;
707 int ret; 618 int ret;
708 619
709 _enter("%s", vlocation->vldb.name); 620 _enter("");
710
711 ret = afs_rxvl_get_entry_by_id_async2(op, &vldb);
712 switch (ret) {
713 case -EAGAIN:
714 _leave(" [unfinished]");
715 return;
716
717 case 0:
718 _debug("END VL UPDATE: %d\n", ret);
719 vlocation->valid = 1;
720
721 _debug("Done VL Lookup: %02x { %08x(%x) %08x(%x) %08x(%x) }",
722 vldb.vidmask,
723 ntohl(vldb.servers[0].s_addr), vldb.srvtmask[0],
724 ntohl(vldb.servers[1].s_addr), vldb.srvtmask[1],
725 ntohl(vldb.servers[2].s_addr), vldb.srvtmask[2]
726 );
727
728 _debug("Vids: %08x %08x %08x",
729 vldb.vid[0], vldb.vid[1], vldb.vid[2]);
730
731 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0);
732
733 down_write(&vlocation->cell->vl_sem);
734
735 /* actually update the cache */
736 if (strncmp(vldb.name, vlocation->vldb.name,
737 sizeof(vlocation->vldb.name)) != 0)
738 printk("kAFS: name of volume '%s'"
739 " changed to '%s' on server\n",
740 vlocation->vldb.name, vldb.name);
741
742 memcpy(&vlocation->vldb, &vldb, sizeof(vlocation->vldb));
743
744#if 0
745 /* TODO update volume entry in local cache */
746#endif
747
748 up_write(&vlocation->cell->vl_sem);
749
750 if (ret < 0)
751 printk("kAFS: failed to update local cache: %d\n", ret);
752
753 afs_kafstimod_add_timer(&vlocation->upd_timer,
754 AFS_VLDB_TIMEOUT);
755 afs_put_vlocation(vlocation);
756 _leave(" [found]");
757 return;
758
759 case -ENOMEDIUM:
760 vlocation->upd_rej_cnt++;
761 goto try_next;
762
763 /* the server is locked - retry in a very short while */
764 case -EBUSY:
765 vlocation->upd_busy_cnt++;
766 if (vlocation->upd_busy_cnt > 3)
767 goto try_next; /* too many retries */
768
769 afs_vlocation_update_abandon(vlocation,
770 AFS_VLUPD_BUSYSLEEP, 0);
771 afs_kafstimod_add_timer(&vlocation->upd_timer, HZ / 2);
772 afs_put_vlocation(vlocation);
773 _leave(" [busy]");
774 return;
775
776 case -ENETUNREACH:
777 case -EHOSTUNREACH:
778 case -ECONNREFUSED:
779 case -EREMOTEIO:
780 /* record bad vlserver info in the cell too
781 * - TODO: use down_write_trylock() if available
782 */
783 if (vlocation->upd_curr_svix == vlocation->cell->vl_curr_svix)
784 vlocation->cell->vl_curr_svix =
785 vlocation->cell->vl_curr_svix %
786 vlocation->cell->vl_naddrs;
787
788 case -EBADRQC:
789 case -EINVAL:
790 case -EACCES:
791 case -EBADMSG:
792 goto try_next;
793
794 default:
795 goto abandon;
796 }
797
798 /* try contacting the next server */
799try_next:
800 vlocation->upd_busy_cnt = 0;
801
802 /* discard the server record */
803 afs_put_server(vlocation->upd_op.server);
804 vlocation->upd_op.server = NULL;
805 621
806 tmp = vlocation->cell->vl_naddrs; 622 now = get_seconds();
807 if (tmp == 0)
808 goto abandon;
809 623
810 vlocation->upd_curr_svix++; 624 /* find a record to update */
811 if (vlocation->upd_curr_svix >= tmp) 625 spin_lock(&afs_vlocation_updates_lock);
812 vlocation->upd_curr_svix = 0; 626 for (;;) {
813 if (vlocation->upd_first_svix >= tmp) 627 if (list_empty(&afs_vlocation_updates)) {
814 vlocation->upd_first_svix = tmp - 1; 628 spin_unlock(&afs_vlocation_updates_lock);
629 _leave(" [nothing]");
630 return;
631 }
815 632
816 /* move to the next server */ 633 vl = list_entry(afs_vlocation_updates.next,
817 if (vlocation->upd_curr_svix != vlocation->upd_first_svix) { 634 struct afs_vlocation, update);
818 afs_vlocation_update_begin(vlocation); 635 if (atomic_read(&vl->usage) > 0)
819 _leave(" [next]"); 636 break;
820 return; 637 list_del_init(&vl->update);
821 } 638 }
822 639
823 /* run out of servers to try - was the volume rejected? */ 640 timeout = vl->update_at - now;
824 if (vlocation->upd_rej_cnt > 0) { 641 if (timeout > 0) {
825 printk("kAFS: Active volume no longer valid '%s'\n", 642 queue_delayed_work(afs_vlocation_update_worker,
826 vlocation->vldb.name); 643 &afs_vlocation_update, timeout * HZ);
827 vlocation->valid = 0; 644 spin_unlock(&afs_vlocation_updates_lock);
828 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, 0); 645 _leave(" [nothing]");
829 afs_kafstimod_add_timer(&vlocation->upd_timer,
830 AFS_VLDB_TIMEOUT);
831 afs_put_vlocation(vlocation);
832 _leave(" [invalidated]");
833 return; 646 return;
834 } 647 }
835 648
836 /* abandon the update */ 649 list_del_init(&vl->update);
837abandon: 650 atomic_inc(&vl->usage);
838 afs_vlocation_update_abandon(vlocation, AFS_VLUPD_SLEEP, ret); 651 spin_unlock(&afs_vlocation_updates_lock);
839 afs_kafstimod_add_timer(&vlocation->upd_timer, HZ * 10);
840 afs_put_vlocation(vlocation);
841 _leave(" [abandoned]");
842}
843 652
844/* 653 /* we can now perform the update */
845 * deal with an update operation being discarded 654 _debug("update %s", vl->vldb.name);
846 * - called in kafsasyncd context when it's dying due to rmmod 655 vl->state = AFS_VL_UPDATING;
847 * - the call has already been aborted and put()'d 656 vl->upd_rej_cnt = 0;
848 */ 657 vl->upd_busy_cnt = 0;
849static void afs_vlocation_update_discard(struct afs_async_op *op)
850{
851 struct afs_vlocation *vlocation =
852 list_entry(op, struct afs_vlocation, upd_op);
853
854 _enter("%s", vlocation->vldb.name);
855 658
856 afs_put_server(op->server); 659 ret = afs_vlocation_update_record(vl, &vldb);
857 op->server = NULL; 660 switch (ret) {
858 661 case 0:
859 afs_put_vlocation(vlocation); 662 afs_vlocation_apply_update(vl, &vldb);
663 vl->state = AFS_VL_VALID;
664 break;
665 case -ENOMEDIUM:
666 vl->state = AFS_VL_VOLUME_DELETED;
667 break;
668 default:
669 vl->state = AFS_VL_UNCERTAIN;
670 break;
671 }
860 672
861 _leave(""); 673 /* and then reschedule */
862} 674 _debug("reschedule");
675 vl->update_at = get_seconds() + afs_vlocation_update_timeout;
863 676
864/* 677 spin_lock(&afs_vlocation_updates_lock);
865 * match a VLDB record stored in the cache
866 * - may also load target from entry
867 */
868#ifdef AFS_CACHING_SUPPORT
869static cachefs_match_val_t afs_vlocation_cache_match(void *target,
870 const void *entry)
871{
872 const struct afs_cache_vlocation *vldb = entry;
873 struct afs_vlocation *vlocation = target;
874
875 _enter("{%s},{%s}", vlocation->vldb.name, vldb->name);
876
877 if (strncmp(vlocation->vldb.name, vldb->name, sizeof(vldb->name)) == 0
878 ) {
879 if (!vlocation->valid ||
880 vlocation->vldb.rtime == vldb->rtime
881 ) {
882 vlocation->vldb = *vldb;
883 vlocation->valid = 1;
884 _leave(" = SUCCESS [c->m]");
885 return CACHEFS_MATCH_SUCCESS;
886 } else if (memcmp(&vlocation->vldb, vldb, sizeof(*vldb)) != 0) {
887 /* delete if VIDs for this name differ */
888 if (memcmp(&vlocation->vldb.vid,
889 &vldb->vid,
890 sizeof(vldb->vid)) != 0) {
891 _leave(" = DELETE");
892 return CACHEFS_MATCH_SUCCESS_DELETE;
893 }
894 678
895 _leave(" = UPDATE"); 679 if (!list_empty(&afs_vlocation_updates)) {
896 return CACHEFS_MATCH_SUCCESS_UPDATE; 680 /* next update in 10 minutes, but wait at least 1 second more
897 } else { 681 * than the newest record already queued so that we don't spam
898 _leave(" = SUCCESS"); 682 * the VL server suddenly with lots of requests
899 return CACHEFS_MATCH_SUCCESS; 683 */
900 } 684 xvl = list_entry(afs_vlocation_updates.prev,
685 struct afs_vlocation, update);
686 if (vl->update_at <= xvl->update_at)
687 vl->update_at = xvl->update_at + 1;
688 xvl = list_entry(afs_vlocation_updates.next,
689 struct afs_vlocation, update);
690 timeout = xvl->update_at - now;
691 if (timeout < 0)
692 timeout = 0;
693 } else {
694 timeout = afs_vlocation_update_timeout;
901 } 695 }
902 696
903 _leave(" = FAILED"); 697 ASSERT(list_empty(&vl->update));
904 return CACHEFS_MATCH_FAILED;
905}
906#endif
907 698
908/* 699 list_add_tail(&vl->update, &afs_vlocation_updates);
909 * update a VLDB record stored in the cache
910 */
911#ifdef AFS_CACHING_SUPPORT
912static void afs_vlocation_cache_update(void *source, void *entry)
913{
914 struct afs_cache_vlocation *vldb = entry;
915 struct afs_vlocation *vlocation = source;
916
917 _enter("");
918 700
919 *vldb = vlocation->vldb; 701 _debug("timeout %ld", timeout);
702 queue_delayed_work(afs_vlocation_update_worker,
703 &afs_vlocation_update, timeout * HZ);
704 spin_unlock(&afs_vlocation_updates_lock);
705 afs_put_vlocation(vl);
920} 706}
921#endif