Blame view

fs/afs/vlocation.c 17.7 KB
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
1
  /* AFS volume location management
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
   *
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
3
   * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
9
10
11
12
13
   * Written by David Howells (dhowells@redhat.com)
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
14
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
15
  #include <linux/init.h>
e8edc6e03   Alexey Dobriyan   Detach sched.h fr...
16
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17
  #include "internal.h"
c1206a2c6   Adrian Bunk   fs/afs/: possible...
18
19
  static unsigned afs_vlocation_timeout = 10;	/* volume location timeout in seconds */
  static unsigned afs_vlocation_update_timeout = 10 * 60;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
21
22
  static void afs_vlocation_reaper(struct work_struct *);
  static void afs_vlocation_updater(struct work_struct *);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
24
25
26
27
28
29
30
  static LIST_HEAD(afs_vlocation_updates);
  static LIST_HEAD(afs_vlocation_graveyard);
  static DEFINE_SPINLOCK(afs_vlocation_updates_lock);
  static DEFINE_SPINLOCK(afs_vlocation_graveyard_lock);
  static DECLARE_DELAYED_WORK(afs_vlocation_reap, afs_vlocation_reaper);
  static DECLARE_DELAYED_WORK(afs_vlocation_update, afs_vlocation_updater);
  static struct workqueue_struct *afs_vlocation_update_worker;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
31

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
  /*
   * iterate through the VL servers in a cell until one of them admits knowing
   * about the volume in question
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
36
  static int afs_vlocation_access_vl_by_name(struct afs_vlocation *vl,
00d3b7a45   David Howells   [AFS]: Add securi...
37
  					   struct key *key,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38
39
  					   struct afs_cache_vlocation *vldb)
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
40
41
  	struct afs_cell *cell = vl->cell;
  	struct in_addr addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
  	int count, ret;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
43
  	_enter("%s,%s", cell->name, vl->vldb.name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
45
  	down_write(&vl->cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
47
  	ret = -ENOMEDIUM;
  	for (count = cell->vl_naddrs; count > 0; count--) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
48
49
50
  		addr = cell->vl_addrs[cell->vl_curr_svix];
  
  		_debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
52
  
  		/* attempt to access the VL server */
00d3b7a45   David Howells   [AFS]: Add securi...
53
  		ret = afs_vl_get_entry_by_name(&addr, key, vl->vldb.name, vldb,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
54
  					       &afs_sync_call);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
55
56
  		switch (ret) {
  		case 0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
57
58
59
60
61
62
  			goto out;
  		case -ENOMEM:
  		case -ENONET:
  		case -ENETUNREACH:
  		case -EHOSTUNREACH:
  		case -ECONNREFUSED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
63
64
65
66
  			if (ret == -ENOMEM || ret == -ENONET)
  				goto out;
  			goto rotate;
  		case -ENOMEDIUM:
005411c3e   David Howells   AFS: Correctly tr...
67
68
  		case -EKEYREJECTED:
  		case -EKEYEXPIRED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
  			goto out;
  		default:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
71
  			ret = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
72
73
74
75
76
77
78
79
  			goto rotate;
  		}
  
  		/* rotate the server records upon lookup failure */
  	rotate:
  		cell->vl_curr_svix++;
  		cell->vl_curr_svix %= cell->vl_naddrs;
  	}
ec26815ad   David Howells   [AFS]: Clean up t...
80
  out:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
81
  	up_write(&vl->cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
82
83
  	_leave(" = %d", ret);
  	return ret;
ec26815ad   David Howells   [AFS]: Clean up t...
84
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
85

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
88
  /*
   * iterate through the VL servers in a cell until one of them admits knowing
   * about the volume in question
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
90
  static int afs_vlocation_access_vl_by_id(struct afs_vlocation *vl,
00d3b7a45   David Howells   [AFS]: Add securi...
91
  					 struct key *key,
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
92
93
94
95
  					 afs_volid_t volid,
  					 afs_voltype_t voltype,
  					 struct afs_cache_vlocation *vldb)
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
96
97
  	struct afs_cell *cell = vl->cell;
  	struct in_addr addr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
  	int count, ret;
  
  	_enter("%s,%x,%d,", cell->name, volid, voltype);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
101
  	down_write(&vl->cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
102
103
  	ret = -ENOMEDIUM;
  	for (count = cell->vl_naddrs; count > 0; count--) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
104
105
106
  		addr = cell->vl_addrs[cell->vl_curr_svix];
  
  		_debug("CellServ[%hu]: %08x", cell->vl_curr_svix, addr.s_addr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
108
  
  		/* attempt to access the VL server */
00d3b7a45   David Howells   [AFS]: Add securi...
109
  		ret = afs_vl_get_entry_by_id(&addr, key, volid, voltype, vldb,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
110
  					     &afs_sync_call);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111
112
  		switch (ret) {
  		case 0:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
  			goto out;
  		case -ENOMEM:
  		case -ENONET:
  		case -ENETUNREACH:
  		case -EHOSTUNREACH:
  		case -ECONNREFUSED:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
119
120
121
  			if (ret == -ENOMEM || ret == -ENONET)
  				goto out;
  			goto rotate;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
122
123
124
125
126
127
128
129
130
131
132
133
  		case -EBUSY:
  			vl->upd_busy_cnt++;
  			if (vl->upd_busy_cnt <= 3) {
  				if (vl->upd_busy_cnt > 1) {
  					/* second+ BUSY - sleep a little bit */
  					set_current_state(TASK_UNINTERRUPTIBLE);
  					schedule_timeout(1);
  					__set_current_state(TASK_RUNNING);
  				}
  				continue;
  			}
  			break;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
134
  		case -ENOMEDIUM:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
135
136
  			vl->upd_rej_cnt++;
  			goto rotate;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
137
  		default:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
138
  			ret = -EIO;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
142
143
144
145
  			goto rotate;
  		}
  
  		/* rotate the server records upon lookup failure */
  	rotate:
  		cell->vl_curr_svix++;
  		cell->vl_curr_svix %= cell->vl_naddrs;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
146
  		vl->upd_busy_cnt = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
147
  	}
ec26815ad   David Howells   [AFS]: Clean up t...
148
  out:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
149
150
151
152
153
154
155
156
157
158
  	if (ret < 0 && vl->upd_rej_cnt > 0) {
  		printk(KERN_NOTICE "kAFS:"
  		       " Active volume no longer valid '%s'
  ",
  		       vl->vldb.name);
  		vl->valid = 0;
  		ret = -ENOMEDIUM;
  	}
  
  	up_write(&vl->cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
159
160
  	_leave(" = %d", ret);
  	return ret;
ec26815ad   David Howells   [AFS]: Clean up t...
161
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
162

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
163
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
164
   * allocate a volume location record
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
165
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
166
167
168
  static struct afs_vlocation *afs_vlocation_alloc(struct afs_cell *cell,
  						 const char *name,
  						 size_t namesz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
169
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
170
171
172
173
174
175
176
177
178
179
180
  	struct afs_vlocation *vl;
  
  	vl = kzalloc(sizeof(struct afs_vlocation), GFP_KERNEL);
  	if (vl) {
  		vl->cell = cell;
  		vl->state = AFS_VL_NEW;
  		atomic_set(&vl->usage, 1);
  		INIT_LIST_HEAD(&vl->link);
  		INIT_LIST_HEAD(&vl->grave);
  		INIT_LIST_HEAD(&vl->update);
  		init_waitqueue_head(&vl->waitq);
39bf09493   David S. Miller   [AFS]: Eliminate ...
181
  		spin_lock_init(&vl->lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
182
  		memcpy(vl->vldb.name, name, namesz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
184
185
186
  	_leave(" = %p", vl);
  	return vl;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
188
189
190
191
  /*
   * update record if we found it in the cache
   */
  static int afs_vlocation_update_record(struct afs_vlocation *vl,
00d3b7a45   David Howells   [AFS]: Add securi...
192
  				       struct key *key,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
193
194
195
196
197
  				       struct afs_cache_vlocation *vldb)
  {
  	afs_voltype_t voltype;
  	afs_volid_t vid;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
198

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
  	/* try to look up a cached volume in the cell VL databases by ID */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	_debug("Locally Cached: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
201
202
203
204
205
206
207
208
  	       vl->vldb.name,
  	       vl->vldb.vidmask,
  	       ntohl(vl->vldb.servers[0].s_addr),
  	       vl->vldb.srvtmask[0],
  	       ntohl(vl->vldb.servers[1].s_addr),
  	       vl->vldb.srvtmask[1],
  	       ntohl(vl->vldb.servers[2].s_addr),
  	       vl->vldb.srvtmask[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
209
210
  
  	_debug("Vids: %08x %08x %08x",
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
211
212
213
  	       vl->vldb.vid[0],
  	       vl->vldb.vid[1],
  	       vl->vldb.vid[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
214

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
215
216
  	if (vl->vldb.vidmask & AFS_VOL_VTM_RW) {
  		vid = vl->vldb.vid[0];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
217
  		voltype = AFSVL_RWVOL;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
218
219
  	} else if (vl->vldb.vidmask & AFS_VOL_VTM_RO) {
  		vid = vl->vldb.vid[1];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  		voltype = AFSVL_ROVOL;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
221
222
  	} else if (vl->vldb.vidmask & AFS_VOL_VTM_BAK) {
  		vid = vl->vldb.vid[2];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223
  		voltype = AFSVL_BACKVOL;
ec26815ad   David Howells   [AFS]: Clean up t...
224
  	} else {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
225
226
227
228
  		BUG();
  		vid = 0;
  		voltype = 0;
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
229
230
231
  	/* contact the server to make sure the volume is still available
  	 * - TODO: need to handle disconnected operation here
  	 */
00d3b7a45   David Howells   [AFS]: Add securi...
232
  	ret = afs_vlocation_access_vl_by_id(vl, key, vid, voltype, vldb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
233
234
235
  	switch (ret) {
  		/* net error */
  	default:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
236
237
238
239
240
241
  		printk(KERN_WARNING "kAFS:"
  		       " failed to update volume '%s' (%x) up in '%s': %d
  ",
  		       vl->vldb.name, vid, vl->cell->name, ret);
  		_leave(" = %d", ret);
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
242
243
244
  
  		/* pulled from local cache into memory */
  	case 0:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
245
246
  		_leave(" = 0");
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
247
248
249
  
  		/* uh oh... looks like the volume got deleted */
  	case -ENOMEDIUM:
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
250
251
252
253
  		printk(KERN_ERR "kAFS:"
  		       " volume '%s' (%x) does not exist '%s'
  ",
  		       vl->vldb.name, vid, vl->cell->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
254
255
  
  		/* TODO: make existing record unavailable */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
256
257
  		_leave(" = %d", ret);
  		return ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
258
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
259
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
260

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
261
262
263
264
265
266
267
268
269
270
271
  /*
   * apply the update to a VL record
   */
  static void afs_vlocation_apply_update(struct afs_vlocation *vl,
  				       struct afs_cache_vlocation *vldb)
  {
  	_debug("Done VL Lookup: %s %02x { %08x(%x) %08x(%x) %08x(%x) }",
  	       vldb->name, vldb->vidmask,
  	       ntohl(vldb->servers[0].s_addr), vldb->srvtmask[0],
  	       ntohl(vldb->servers[1].s_addr), vldb->srvtmask[1],
  	       ntohl(vldb->servers[2].s_addr), vldb->srvtmask[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
272

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
273
274
  	_debug("Vids: %08x %08x %08x",
  	       vldb->vid[0], vldb->vid[1], vldb->vid[2]);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
275

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
276
277
278
279
280
  	if (strcmp(vldb->name, vl->vldb.name) != 0)
  		printk(KERN_NOTICE "kAFS:"
  		       " name of volume '%s' changed to '%s' on server
  ",
  		       vl->vldb.name, vldb->name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
281

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
282
  	vl->vldb = *vldb;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
283

9b3f26c91   David Howells   FS-Cache: Make kA...
284
285
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_update_cookie(vl->cache);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
286
  #endif
ec26815ad   David Howells   [AFS]: Clean up t...
287
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
288

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
289
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
290
291
   * fill in a volume location record, consulting the cache and the VL server
   * both
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
292
   */
00d3b7a45   David Howells   [AFS]: Add securi...
293
294
  static int afs_vlocation_fill_in_record(struct afs_vlocation *vl,
  					struct key *key)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
295
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
296
297
  	struct afs_cache_vlocation vldb;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
298

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
299
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
300

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
301
  	ASSERTCMP(vl->valid, ==, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
302

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
303
  	memset(&vldb, 0, sizeof(vldb));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
304

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
305
  	/* see if we have an in-cache copy (will set vl->valid if there is) */
9b3f26c91   David Howells   FS-Cache: Make kA...
306
307
308
  #ifdef CONFIG_AFS_FSCACHE
  	vl->cache = fscache_acquire_cookie(vl->cell->cache,
  					   &afs_vlocation_cache_index_def, vl);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
309
  #endif
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
310

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
311
312
313
314
  	if (vl->valid) {
  		/* try to update a known volume in the cell VL databases by
  		 * ID as the name may have changed */
  		_debug("found in cache");
00d3b7a45   David Howells   [AFS]: Add securi...
315
  		ret = afs_vlocation_update_record(vl, key, &vldb);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
316
317
318
  	} else {
  		/* try to look up an unknown volume in the cell VL databases by
  		 * name */
00d3b7a45   David Howells   [AFS]: Add securi...
319
  		ret = afs_vlocation_access_vl_by_name(vl, key, &vldb);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
320
321
322
323
324
325
  		if (ret < 0) {
  			printk("kAFS: failed to locate '%s' in cell '%s'
  ",
  			       vl->vldb.name, vl->cell->name);
  			return ret;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
326
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
327
328
329
  	afs_vlocation_apply_update(vl, &vldb);
  	_leave(" = 0");
  	return 0;
ec26815ad   David Howells   [AFS]: Clean up t...
330
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
331

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
332
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
333
   * queue a vlocation record for updates
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
334
   */
c1206a2c6   Adrian Bunk   fs/afs/: possible...
335
  static void afs_vlocation_queue_for_updates(struct afs_vlocation *vl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
336
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
337
  	struct afs_vlocation *xvl;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
338

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
  	/* wait at least 10 minutes before updating... */
  	vl->update_at = get_seconds() + afs_vlocation_update_timeout;
  
  	spin_lock(&afs_vlocation_updates_lock);
  
  	if (!list_empty(&afs_vlocation_updates)) {
  		/* ... but wait at least 1 second more than the newest record
  		 * already queued so that we don't spam the VL server suddenly
  		 * with lots of requests
  		 */
  		xvl = list_entry(afs_vlocation_updates.prev,
  				 struct afs_vlocation, update);
  		if (vl->update_at <= xvl->update_at)
  			vl->update_at = xvl->update_at + 1;
  	} else {
  		queue_delayed_work(afs_vlocation_update_worker,
  				   &afs_vlocation_update,
  				   afs_vlocation_update_timeout * HZ);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
357
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
358
359
360
  
  	list_add_tail(&vl->update, &afs_vlocation_updates);
  	spin_unlock(&afs_vlocation_updates_lock);
ec26815ad   David Howells   [AFS]: Clean up t...
361
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
362

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
363
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
364
365
366
367
368
   * lookup volume location
   * - iterate through the VL servers in a cell until one of them admits knowing
   *   about the volume in question
   * - lookup in the local cache if not able to find on the VL server
   * - insert/update in the local cache if did get a VL response
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
369
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
370
  struct afs_vlocation *afs_vlocation_lookup(struct afs_cell *cell,
00d3b7a45   David Howells   [AFS]: Add securi...
371
  					   struct key *key,
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
372
373
  					   const char *name,
  					   size_t namesz)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
374
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
375
376
  	struct afs_vlocation *vl;
  	int ret;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
377

00d3b7a45   David Howells   [AFS]: Add securi...
378
379
380
  	_enter("{%s},{%x},%*.*s,%zu",
  	       cell->name, key_serial(key),
  	       (int) namesz, (int) namesz, name, namesz);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381

6551198a2   Adrian Bunk   fs/afs/vlocation....
382
  	if (namesz >= sizeof(vl->vldb.name)) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
383
384
385
  		_leave(" = -ENAMETOOLONG");
  		return ERR_PTR(-ENAMETOOLONG);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
387
388
389
390
391
392
393
394
  	/* see if we have an in-memory copy first */
  	down_write(&cell->vl_sem);
  	spin_lock(&cell->vl_lock);
  	list_for_each_entry(vl, &cell->vl_list, link) {
  		if (vl->vldb.name[namesz] != '\0')
  			continue;
  		if (memcmp(vl->vldb.name, name, namesz) == 0)
  			goto found_in_memory;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
395
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
396
  	spin_unlock(&cell->vl_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
397

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
398
399
400
401
402
403
  	/* not in the cell's in-memory lists - create a new record */
  	vl = afs_vlocation_alloc(cell, name, namesz);
  	if (!vl) {
  		up_write(&cell->vl_sem);
  		return ERR_PTR(-ENOMEM);
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
404

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
405
  	afs_get_cell(cell);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
406

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
407
408
409
  	list_add_tail(&vl->link, &cell->vl_list);
  	vl->state = AFS_VL_CREATING;
  	up_write(&cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
410

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
411
  fill_in_record:
00d3b7a45   David Howells   [AFS]: Add securi...
412
  	ret = afs_vlocation_fill_in_record(vl, key);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
413
414
  	if (ret < 0)
  		goto error_abandon;
39bf09493   David S. Miller   [AFS]: Eliminate ...
415
  	spin_lock(&vl->lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
416
  	vl->state = AFS_VL_VALID;
39bf09493   David S. Miller   [AFS]: Eliminate ...
417
  	spin_unlock(&vl->lock);
47051a215   David Howells   [AFS]: Fix VLocat...
418
  	wake_up(&vl->waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
419

9b3f26c91   David Howells   FS-Cache: Make kA...
420
421
422
423
  	/* update volume entry in local cache */
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_update_cookie(vl->cache);
  #endif
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
424
425
426
  	/* schedule for regular updates */
  	afs_vlocation_queue_for_updates(vl);
  	goto success;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
427

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
428
429
430
431
432
433
434
435
436
  found_in_memory:
  	/* found in memory */
  	_debug("found in memory");
  	atomic_inc(&vl->usage);
  	spin_unlock(&cell->vl_lock);
  	if (!list_empty(&vl->grave)) {
  		spin_lock(&afs_vlocation_graveyard_lock);
  		list_del_init(&vl->grave);
  		spin_unlock(&afs_vlocation_graveyard_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
437
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
438
  	up_write(&cell->vl_sem);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
439

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
440
  	/* see if it was an abandoned record that we might try filling in */
39bf09493   David S. Miller   [AFS]: Eliminate ...
441
  	spin_lock(&vl->lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
442
443
  	while (vl->state != AFS_VL_VALID) {
  		afs_vlocation_state_t state = vl->state;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
444

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
445
  		_debug("invalid [state %d]", state);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
446

47051a215   David Howells   [AFS]: Fix VLocat...
447
  		if (state == AFS_VL_NEW || state == AFS_VL_NO_VOLUME) {
39bf09493   David S. Miller   [AFS]: Eliminate ...
448
449
450
  			vl->state = AFS_VL_CREATING;
  			spin_unlock(&vl->lock);
  			goto fill_in_record;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
451
452
453
454
455
  		}
  
  		/* must now wait for creation or update by someone else to
  		 * complete */
  		_debug("wait");
39bf09493   David S. Miller   [AFS]: Eliminate ...
456
  		spin_unlock(&vl->lock);
47051a215   David Howells   [AFS]: Fix VLocat...
457
458
459
460
  		ret = wait_event_interruptible(vl->waitq,
  					       vl->state == AFS_VL_NEW ||
  					       vl->state == AFS_VL_VALID ||
  					       vl->state == AFS_VL_NO_VOLUME);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
461
462
  		if (ret < 0)
  			goto error;
39bf09493   David S. Miller   [AFS]: Eliminate ...
463
  		spin_lock(&vl->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
464
  	}
39bf09493   David S. Miller   [AFS]: Eliminate ...
465
  	spin_unlock(&vl->lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
466

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
467
  success:
9b3f26c91   David Howells   FS-Cache: Make kA...
468
  	_leave(" = %p", vl);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
469
470
471
  	return vl;
  
  error_abandon:
39bf09493   David S. Miller   [AFS]: Eliminate ...
472
  	spin_lock(&vl->lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
473
  	vl->state = AFS_VL_NEW;
39bf09493   David S. Miller   [AFS]: Eliminate ...
474
  	spin_unlock(&vl->lock);
47051a215   David Howells   [AFS]: Fix VLocat...
475
  	wake_up(&vl->waitq);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
476
477
478
  error:
  	ASSERT(vl != NULL);
  	afs_put_vlocation(vl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
479
  	_leave(" = %d", ret);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
480
  	return ERR_PTR(ret);
ec26815ad   David Howells   [AFS]: Clean up t...
481
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
482

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
483
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
484
   * finish using a volume location record
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
485
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
486
  void afs_put_vlocation(struct afs_vlocation *vl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
487
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
488
489
  	if (!vl)
  		return;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
490

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
491
  	_enter("%s", vl->vldb.name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
492

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
493
  	ASSERTCMP(atomic_read(&vl->usage), >, 0);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
494

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
495
496
497
498
  	if (likely(!atomic_dec_and_test(&vl->usage))) {
  		_leave("");
  		return;
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
499

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
500
501
502
503
504
  	spin_lock(&afs_vlocation_graveyard_lock);
  	if (atomic_read(&vl->usage) == 0) {
  		_debug("buried");
  		list_move_tail(&vl->grave, &afs_vlocation_graveyard);
  		vl->time_of_death = get_seconds();
0ad53eeef   Tejun Heo   afs: add afs_wq a...
505
506
  		queue_delayed_work(afs_wq, &afs_vlocation_reap,
  				   afs_vlocation_timeout * HZ);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
507
508
509
510
511
512
513
514
515
516
  
  		/* suspend updates on this record */
  		if (!list_empty(&vl->update)) {
  			spin_lock(&afs_vlocation_updates_lock);
  			list_del_init(&vl->update);
  			spin_unlock(&afs_vlocation_updates_lock);
  		}
  	}
  	spin_unlock(&afs_vlocation_graveyard_lock);
  	_leave(" [killed?]");
ec26815ad   David Howells   [AFS]: Clean up t...
517
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
518

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
519
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
520
   * destroy a dead volume location record
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
521
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
522
  static void afs_vlocation_destroy(struct afs_vlocation *vl)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
523
  {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
524
  	_enter("%p", vl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
525

9b3f26c91   David Howells   FS-Cache: Make kA...
526
527
  #ifdef CONFIG_AFS_FSCACHE
  	fscache_relinquish_cookie(vl->cache, 0);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
528
  #endif
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
529
530
531
532
533
534
535
536
537
538
539
540
541
  	afs_put_cell(vl->cell);
  	kfree(vl);
  }
  
  /*
   * reap dead volume location records
   */
  static void afs_vlocation_reaper(struct work_struct *work)
  {
  	LIST_HEAD(corpses);
  	struct afs_vlocation *vl;
  	unsigned long delay, expiry;
  	time_t now;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
542

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
543
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
544

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
545
546
547
548
549
550
551
552
553
554
555
556
557
558
  	now = get_seconds();
  	spin_lock(&afs_vlocation_graveyard_lock);
  
  	while (!list_empty(&afs_vlocation_graveyard)) {
  		vl = list_entry(afs_vlocation_graveyard.next,
  				struct afs_vlocation, grave);
  
  		_debug("check %p", vl);
  
  		/* the queue is ordered most dead first */
  		expiry = vl->time_of_death + afs_vlocation_timeout;
  		if (expiry > now) {
  			delay = (expiry - now) * HZ;
  			_debug("delay %lu", delay);
0ad53eeef   Tejun Heo   afs: add afs_wq a...
559
560
  			if (!queue_delayed_work(afs_wq, &afs_vlocation_reap,
  						delay)) {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
561
  				cancel_delayed_work(&afs_vlocation_reap);
0ad53eeef   Tejun Heo   afs: add afs_wq a...
562
563
  				queue_delayed_work(afs_wq, &afs_vlocation_reap,
  						   delay);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
564
565
566
  			}
  			break;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
567

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
568
569
570
571
  		spin_lock(&vl->cell->vl_lock);
  		if (atomic_read(&vl->usage) > 0) {
  			_debug("no reap");
  			list_del_init(&vl->grave);
ec26815ad   David Howells   [AFS]: Clean up t...
572
  		} else {
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
573
574
575
  			_debug("reap");
  			list_move_tail(&vl->grave, &corpses);
  			list_del_init(&vl->link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
576
  		}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
577
  		spin_unlock(&vl->cell->vl_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
578
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
579
  	spin_unlock(&afs_vlocation_graveyard_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
580

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
581
582
583
584
585
  	/* now reap the corpses we've extracted */
  	while (!list_empty(&corpses)) {
  		vl = list_entry(corpses.next, struct afs_vlocation, grave);
  		list_del(&vl->grave);
  		afs_vlocation_destroy(vl);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
586
587
588
  	}
  
  	_leave("");
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
589
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
590

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
591
592
593
594
595
596
597
598
599
600
601
602
603
  /*
   * initialise the VL update process
   */
  int __init afs_vlocation_update_init(void)
  {
  	afs_vlocation_update_worker =
  		create_singlethread_workqueue("kafs_vlupdated");
  	return afs_vlocation_update_worker ? 0 : -ENOMEM;
  }
  
  /*
   * discard all the volume location records for rmmod
   */
fbb3fcba7   David Howells   [AFS]: Fix use of...
604
  void afs_vlocation_purge(void)
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
605
606
607
608
609
610
611
612
613
614
615
616
  {
  	afs_vlocation_timeout = 0;
  
  	spin_lock(&afs_vlocation_updates_lock);
  	list_del_init(&afs_vlocation_updates);
  	spin_unlock(&afs_vlocation_updates_lock);
  	cancel_delayed_work(&afs_vlocation_update);
  	queue_delayed_work(afs_vlocation_update_worker,
  			   &afs_vlocation_update, 0);
  	destroy_workqueue(afs_vlocation_update_worker);
  
  	cancel_delayed_work(&afs_vlocation_reap);
0ad53eeef   Tejun Heo   afs: add afs_wq a...
617
  	queue_delayed_work(afs_wq, &afs_vlocation_reap, 0);
ec26815ad   David Howells   [AFS]: Clean up t...
618
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
619

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
620
  /*
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
621
   * update a volume location
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
622
   */
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
623
  static void afs_vlocation_updater(struct work_struct *work)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
624
625
  {
  	struct afs_cache_vlocation vldb;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
626
627
628
  	struct afs_vlocation *vl, *xvl;
  	time_t now;
  	long timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
629
  	int ret;
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
630
  	_enter("");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
631

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
632
  	now = get_seconds();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
633

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
634
635
636
637
638
639
640
641
  	/* find a record to update */
  	spin_lock(&afs_vlocation_updates_lock);
  	for (;;) {
  		if (list_empty(&afs_vlocation_updates)) {
  			spin_unlock(&afs_vlocation_updates_lock);
  			_leave(" [nothing]");
  			return;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
642

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
643
644
645
646
647
  		vl = list_entry(afs_vlocation_updates.next,
  				struct afs_vlocation, update);
  		if (atomic_read(&vl->usage) > 0)
  			break;
  		list_del_init(&vl->update);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
648
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
649
650
651
652
653
654
  	timeout = vl->update_at - now;
  	if (timeout > 0) {
  		queue_delayed_work(afs_vlocation_update_worker,
  				   &afs_vlocation_update, timeout * HZ);
  		spin_unlock(&afs_vlocation_updates_lock);
  		_leave(" [nothing]");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
655
656
  		return;
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
657
658
659
  	list_del_init(&vl->update);
  	atomic_inc(&vl->usage);
  	spin_unlock(&afs_vlocation_updates_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
660

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
661
662
663
664
665
  	/* we can now perform the update */
  	_debug("update %s", vl->vldb.name);
  	vl->state = AFS_VL_UPDATING;
  	vl->upd_rej_cnt = 0;
  	vl->upd_busy_cnt = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
666

00d3b7a45   David Howells   [AFS]: Add securi...
667
  	ret = afs_vlocation_update_record(vl, NULL, &vldb);
39bf09493   David S. Miller   [AFS]: Eliminate ...
668
  	spin_lock(&vl->lock);
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
669
670
671
672
673
674
675
676
677
678
679
680
  	switch (ret) {
  	case 0:
  		afs_vlocation_apply_update(vl, &vldb);
  		vl->state = AFS_VL_VALID;
  		break;
  	case -ENOMEDIUM:
  		vl->state = AFS_VL_VOLUME_DELETED;
  		break;
  	default:
  		vl->state = AFS_VL_UNCERTAIN;
  		break;
  	}
39bf09493   David S. Miller   [AFS]: Eliminate ...
681
  	spin_unlock(&vl->lock);
47051a215   David Howells   [AFS]: Fix VLocat...
682
  	wake_up(&vl->waitq);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
683

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
684
685
686
  	/* and then reschedule */
  	_debug("reschedule");
  	vl->update_at = get_seconds() + afs_vlocation_update_timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
687

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
688
  	spin_lock(&afs_vlocation_updates_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
689

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
  	if (!list_empty(&afs_vlocation_updates)) {
  		/* next update in 10 minutes, but wait at least 1 second more
  		 * than the newest record already queued so that we don't spam
  		 * the VL server suddenly with lots of requests
  		 */
  		xvl = list_entry(afs_vlocation_updates.prev,
  				 struct afs_vlocation, update);
  		if (vl->update_at <= xvl->update_at)
  			vl->update_at = xvl->update_at + 1;
  		xvl = list_entry(afs_vlocation_updates.next,
  				 struct afs_vlocation, update);
  		timeout = xvl->update_at - now;
  		if (timeout < 0)
  			timeout = 0;
  	} else {
  		timeout = afs_vlocation_update_timeout;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
706
  	}
08e0e7c82   David Howells   [AF_RXRPC]: Make ...
707
  	ASSERT(list_empty(&vl->update));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
708

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
709
  	list_add_tail(&vl->update, &afs_vlocation_updates);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
710

08e0e7c82   David Howells   [AF_RXRPC]: Make ...
711
712
713
714
715
  	_debug("timeout %ld", timeout);
  	queue_delayed_work(afs_vlocation_update_worker,
  			   &afs_vlocation_update, timeout * HZ);
  	spin_unlock(&afs_vlocation_updates_lock);
  	afs_put_vlocation(vl);
ec26815ad   David Howells   [AFS]: Clean up t...
716
  }