diff options
Diffstat (limited to 'fs/afs/super.c')
-rw-r--r-- | fs/afs/super.c | 326 |
1 files changed, 203 insertions, 123 deletions
diff --git a/fs/afs/super.c b/fs/afs/super.c index eb7e32349da3..cebd03c91f57 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* AFS superblock handling |
2 | * Copyright (c) 2002 Red Hat, Inc. All rights reserved. | 2 | * |
3 | * Copyright (c) 2002, 2007 Red Hat, Inc. All rights reserved. | ||
3 | * | 4 | * |
4 | * This software may be freely redistributed under the terms of the | 5 | * This software may be freely redistributed under the terms of the |
5 | * GNU General Public License. | 6 | * GNU General Public License. |
@@ -9,7 +10,7 @@ | |||
9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 10 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
10 | * | 11 | * |
11 | * Authors: David Howells <dhowells@redhat.com> | 12 | * Authors: David Howells <dhowells@redhat.com> |
12 | * David Woodhouse <dwmw2@cambridge.redhat.com> | 13 | * David Woodhouse <dwmw2@redhat.com> |
13 | * | 14 | * |
14 | */ | 15 | */ |
15 | 16 | ||
@@ -19,22 +20,10 @@ | |||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
21 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
22 | #include "vnode.h" | ||
23 | #include "volume.h" | ||
24 | #include "cell.h" | ||
25 | #include "cmservice.h" | ||
26 | #include "fsclient.h" | ||
27 | #include "super.h" | ||
28 | #include "internal.h" | 23 | #include "internal.h" |
29 | 24 | ||
30 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ | 25 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ |
31 | 26 | ||
32 | struct afs_mount_params { | ||
33 | int rwpath; | ||
34 | struct afs_cell *default_cell; | ||
35 | struct afs_volume *volume; | ||
36 | }; | ||
37 | |||
38 | static void afs_i_init_once(void *foo, struct kmem_cache *cachep, | 27 | static void afs_i_init_once(void *foo, struct kmem_cache *cachep, |
39 | unsigned long flags); | 28 | unsigned long flags); |
40 | 29 | ||
@@ -62,13 +51,13 @@ static const struct super_operations afs_super_ops = { | |||
62 | .drop_inode = generic_delete_inode, | 51 | .drop_inode = generic_delete_inode, |
63 | .destroy_inode = afs_destroy_inode, | 52 | .destroy_inode = afs_destroy_inode, |
64 | .clear_inode = afs_clear_inode, | 53 | .clear_inode = afs_clear_inode, |
54 | .umount_begin = afs_umount_begin, | ||
65 | .put_super = afs_put_super, | 55 | .put_super = afs_put_super, |
66 | }; | 56 | }; |
67 | 57 | ||
68 | static struct kmem_cache *afs_inode_cachep; | 58 | static struct kmem_cache *afs_inode_cachep; |
69 | static atomic_t afs_count_active_inodes; | 59 | static atomic_t afs_count_active_inodes; |
70 | 60 | ||
71 | /*****************************************************************************/ | ||
72 | /* | 61 | /* |
73 | * initialise the filesystem | 62 | * initialise the filesystem |
74 | */ | 63 | */ |
@@ -78,8 +67,6 @@ int __init afs_fs_init(void) | |||
78 | 67 | ||
79 | _enter(""); | 68 | _enter(""); |
80 | 69 | ||
81 | afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops); | ||
82 | |||
83 | /* create ourselves an inode cache */ | 70 | /* create ourselves an inode cache */ |
84 | atomic_set(&afs_count_active_inodes, 0); | 71 | atomic_set(&afs_count_active_inodes, 0); |
85 | 72 | ||
@@ -99,20 +86,22 @@ int __init afs_fs_init(void) | |||
99 | ret = register_filesystem(&afs_fs_type); | 86 | ret = register_filesystem(&afs_fs_type); |
100 | if (ret < 0) { | 87 | if (ret < 0) { |
101 | kmem_cache_destroy(afs_inode_cachep); | 88 | kmem_cache_destroy(afs_inode_cachep); |
102 | kleave(" = %d", ret); | 89 | _leave(" = %d", ret); |
103 | return ret; | 90 | return ret; |
104 | } | 91 | } |
105 | 92 | ||
106 | kleave(" = 0"); | 93 | _leave(" = 0"); |
107 | return 0; | 94 | return 0; |
108 | } /* end afs_fs_init() */ | 95 | } |
109 | 96 | ||
110 | /*****************************************************************************/ | ||
111 | /* | 97 | /* |
112 | * clean up the filesystem | 98 | * clean up the filesystem |
113 | */ | 99 | */ |
114 | void __exit afs_fs_exit(void) | 100 | void __exit afs_fs_exit(void) |
115 | { | 101 | { |
102 | _enter(""); | ||
103 | |||
104 | afs_mntpt_kill_timer(); | ||
116 | unregister_filesystem(&afs_fs_type); | 105 | unregister_filesystem(&afs_fs_type); |
117 | 106 | ||
118 | if (atomic_read(&afs_count_active_inodes) != 0) { | 107 | if (atomic_read(&afs_count_active_inodes) != 0) { |
@@ -122,10 +111,9 @@ void __exit afs_fs_exit(void) | |||
122 | } | 111 | } |
123 | 112 | ||
124 | kmem_cache_destroy(afs_inode_cachep); | 113 | kmem_cache_destroy(afs_inode_cachep); |
114 | _leave(""); | ||
115 | } | ||
125 | 116 | ||
126 | } /* end afs_fs_exit() */ | ||
127 | |||
128 | /*****************************************************************************/ | ||
129 | /* | 117 | /* |
130 | * check that an argument has a value | 118 | * check that an argument has a value |
131 | */ | 119 | */ |
@@ -136,9 +124,8 @@ static int want_arg(char **_value, const char *option) | |||
136 | return 0; | 124 | return 0; |
137 | } | 125 | } |
138 | return 1; | 126 | return 1; |
139 | } /* end want_arg() */ | 127 | } |
140 | 128 | ||
141 | /*****************************************************************************/ | ||
142 | /* | 129 | /* |
143 | * check that there's no subsequent value | 130 | * check that there's no subsequent value |
144 | */ | 131 | */ |
@@ -150,18 +137,17 @@ static int want_no_value(char *const *_value, const char *option) | |||
150 | return 0; | 137 | return 0; |
151 | } | 138 | } |
152 | return 1; | 139 | return 1; |
153 | } /* end want_no_value() */ | 140 | } |
154 | 141 | ||
155 | /*****************************************************************************/ | ||
156 | /* | 142 | /* |
157 | * parse the mount options | 143 | * parse the mount options |
158 | * - this function has been shamelessly adapted from the ext3 fs which | 144 | * - this function has been shamelessly adapted from the ext3 fs which |
159 | * shamelessly adapted it from the msdos fs | 145 | * shamelessly adapted it from the msdos fs |
160 | */ | 146 | */ |
161 | static int afs_super_parse_options(struct afs_mount_params *params, | 147 | static int afs_parse_options(struct afs_mount_params *params, |
162 | char *options, | 148 | char *options, const char **devname) |
163 | const char **devname) | ||
164 | { | 149 | { |
150 | struct afs_cell *cell; | ||
165 | char *key, *value; | 151 | char *key, *value; |
166 | int ret; | 152 | int ret; |
167 | 153 | ||
@@ -170,51 +156,135 @@ static int afs_super_parse_options(struct afs_mount_params *params, | |||
170 | options[PAGE_SIZE - 1] = 0; | 156 | options[PAGE_SIZE - 1] = 0; |
171 | 157 | ||
172 | ret = 0; | 158 | ret = 0; |
173 | while ((key = strsep(&options, ",")) != 0) | 159 | while ((key = strsep(&options, ","))) { |
174 | { | ||
175 | value = strchr(key, '='); | 160 | value = strchr(key, '='); |
176 | if (value) | 161 | if (value) |
177 | *value++ = 0; | 162 | *value++ = 0; |
178 | 163 | ||
179 | printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-"); | 164 | _debug("kAFS: KEY: %s, VAL:%s", key, value ?: "-"); |
180 | 165 | ||
181 | if (strcmp(key, "rwpath") == 0) { | 166 | if (strcmp(key, "rwpath") == 0) { |
182 | if (!want_no_value(&value, "rwpath")) | 167 | if (!want_no_value(&value, "rwpath")) |
183 | return -EINVAL; | 168 | return -EINVAL; |
184 | params->rwpath = 1; | 169 | params->rwpath = 1; |
185 | continue; | 170 | } else if (strcmp(key, "vol") == 0) { |
186 | } | ||
187 | else if (strcmp(key, "vol") == 0) { | ||
188 | if (!want_arg(&value, "vol")) | 171 | if (!want_arg(&value, "vol")) |
189 | return -EINVAL; | 172 | return -EINVAL; |
190 | *devname = value; | 173 | *devname = value; |
191 | continue; | 174 | } else if (strcmp(key, "cell") == 0) { |
192 | } | ||
193 | else if (strcmp(key, "cell") == 0) { | ||
194 | if (!want_arg(&value, "cell")) | 175 | if (!want_arg(&value, "cell")) |
195 | return -EINVAL; | 176 | return -EINVAL; |
196 | afs_put_cell(params->default_cell); | 177 | cell = afs_cell_lookup(value, strlen(value)); |
197 | ret = afs_cell_lookup(value, | 178 | if (IS_ERR(cell)) |
198 | strlen(value), | 179 | return PTR_ERR(cell); |
199 | ¶ms->default_cell); | 180 | afs_put_cell(params->cell); |
200 | if (ret < 0) | 181 | params->cell = cell; |
201 | return -EINVAL; | 182 | } else { |
202 | continue; | 183 | printk("kAFS: Unknown mount option: '%s'\n", key); |
184 | ret = -EINVAL; | ||
185 | goto error; | ||
203 | } | 186 | } |
204 | |||
205 | printk("kAFS: Unknown mount option: '%s'\n", key); | ||
206 | ret = -EINVAL; | ||
207 | goto error; | ||
208 | } | 187 | } |
209 | 188 | ||
210 | ret = 0; | 189 | ret = 0; |
211 | 190 | error: | |
212 | error: | ||
213 | _leave(" = %d", ret); | 191 | _leave(" = %d", ret); |
214 | return ret; | 192 | return ret; |
215 | } /* end afs_super_parse_options() */ | 193 | } |
194 | |||
195 | /* | ||
196 | * parse a device name to get cell name, volume name, volume type and R/W | ||
197 | * selector | ||
198 | * - this can be one of the following: | ||
199 | * "%[cell:]volume[.]" R/W volume | ||
200 | * "#[cell:]volume[.]" R/O or R/W volume (rwpath=0), | ||
201 | * or R/W (rwpath=1) volume | ||
202 | * "%[cell:]volume.readonly" R/O volume | ||
203 | * "#[cell:]volume.readonly" R/O volume | ||
204 | * "%[cell:]volume.backup" Backup volume | ||
205 | * "#[cell:]volume.backup" Backup volume | ||
206 | */ | ||
207 | static int afs_parse_device_name(struct afs_mount_params *params, | ||
208 | const char *name) | ||
209 | { | ||
210 | struct afs_cell *cell; | ||
211 | const char *cellname, *suffix; | ||
212 | int cellnamesz; | ||
213 | |||
214 | _enter(",%s", name); | ||
215 | |||
216 | if (!name) { | ||
217 | printk(KERN_ERR "kAFS: no volume name specified\n"); | ||
218 | return -EINVAL; | ||
219 | } | ||
220 | |||
221 | if ((name[0] != '%' && name[0] != '#') || !name[1]) { | ||
222 | printk(KERN_ERR "kAFS: unparsable volume name\n"); | ||
223 | return -EINVAL; | ||
224 | } | ||
225 | |||
226 | /* determine the type of volume we're looking for */ | ||
227 | params->type = AFSVL_ROVOL; | ||
228 | params->force = false; | ||
229 | if (params->rwpath || name[0] == '%') { | ||
230 | params->type = AFSVL_RWVOL; | ||
231 | params->force = true; | ||
232 | } | ||
233 | name++; | ||
234 | |||
235 | /* split the cell name out if there is one */ | ||
236 | params->volname = strchr(name, ':'); | ||
237 | if (params->volname) { | ||
238 | cellname = name; | ||
239 | cellnamesz = params->volname - name; | ||
240 | params->volname++; | ||
241 | } else { | ||
242 | params->volname = name; | ||
243 | cellname = NULL; | ||
244 | cellnamesz = 0; | ||
245 | } | ||
246 | |||
247 | /* the volume type is further affected by a possible suffix */ | ||
248 | suffix = strrchr(params->volname, '.'); | ||
249 | if (suffix) { | ||
250 | if (strcmp(suffix, ".readonly") == 0) { | ||
251 | params->type = AFSVL_ROVOL; | ||
252 | params->force = true; | ||
253 | } else if (strcmp(suffix, ".backup") == 0) { | ||
254 | params->type = AFSVL_BACKVOL; | ||
255 | params->force = true; | ||
256 | } else if (suffix[1] == 0) { | ||
257 | } else { | ||
258 | suffix = NULL; | ||
259 | } | ||
260 | } | ||
261 | |||
262 | params->volnamesz = suffix ? | ||
263 | suffix - params->volname : strlen(params->volname); | ||
264 | |||
265 | _debug("cell %*.*s [%p]", | ||
266 | cellnamesz, cellnamesz, cellname ?: "", params->cell); | ||
267 | |||
268 | /* lookup the cell record */ | ||
269 | if (cellname || !params->cell) { | ||
270 | cell = afs_cell_lookup(cellname, cellnamesz); | ||
271 | if (IS_ERR(cell)) { | ||
272 | printk(KERN_ERR "kAFS: unable to lookup cell '%s'\n", | ||
273 | cellname ?: ""); | ||
274 | return PTR_ERR(cell); | ||
275 | } | ||
276 | afs_put_cell(params->cell); | ||
277 | params->cell = cell; | ||
278 | } | ||
279 | |||
280 | _debug("CELL:%s [%p] VOLUME:%*.*s SUFFIX:%s TYPE:%d%s", | ||
281 | params->cell->name, params->cell, | ||
282 | params->volnamesz, params->volnamesz, params->volname, | ||
283 | suffix ?: "-", params->type, params->force ? " FORCE" : ""); | ||
284 | |||
285 | return 0; | ||
286 | } | ||
216 | 287 | ||
217 | /*****************************************************************************/ | ||
218 | /* | 288 | /* |
219 | * check a superblock to see if it's the one we're looking for | 289 | * check a superblock to see if it's the one we're looking for |
220 | */ | 290 | */ |
@@ -224,13 +294,12 @@ static int afs_test_super(struct super_block *sb, void *data) | |||
224 | struct afs_super_info *as = sb->s_fs_info; | 294 | struct afs_super_info *as = sb->s_fs_info; |
225 | 295 | ||
226 | return as->volume == params->volume; | 296 | return as->volume == params->volume; |
227 | } /* end afs_test_super() */ | 297 | } |
228 | 298 | ||
229 | /*****************************************************************************/ | ||
230 | /* | 299 | /* |
231 | * fill in the superblock | 300 | * fill in the superblock |
232 | */ | 301 | */ |
233 | static int afs_fill_super(struct super_block *sb, void *data, int silent) | 302 | static int afs_fill_super(struct super_block *sb, void *data) |
234 | { | 303 | { |
235 | struct afs_mount_params *params = data; | 304 | struct afs_mount_params *params = data; |
236 | struct afs_super_info *as = NULL; | 305 | struct afs_super_info *as = NULL; |
@@ -239,7 +308,7 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) | |||
239 | struct inode *inode = NULL; | 308 | struct inode *inode = NULL; |
240 | int ret; | 309 | int ret; |
241 | 310 | ||
242 | kenter(""); | 311 | _enter(""); |
243 | 312 | ||
244 | /* allocate a superblock info record */ | 313 | /* allocate a superblock info record */ |
245 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); | 314 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); |
@@ -262,9 +331,9 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) | |||
262 | fid.vid = as->volume->vid; | 331 | fid.vid = as->volume->vid; |
263 | fid.vnode = 1; | 332 | fid.vnode = 1; |
264 | fid.unique = 1; | 333 | fid.unique = 1; |
265 | ret = afs_iget(sb, &fid, &inode); | 334 | inode = afs_iget(sb, params->key, &fid, NULL, NULL); |
266 | if (ret < 0) | 335 | if (IS_ERR(inode)) |
267 | goto error; | 336 | goto error_inode; |
268 | 337 | ||
269 | ret = -ENOMEM; | 338 | ret = -ENOMEM; |
270 | root = d_alloc_root(inode); | 339 | root = d_alloc_root(inode); |
@@ -273,21 +342,23 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) | |||
273 | 342 | ||
274 | sb->s_root = root; | 343 | sb->s_root = root; |
275 | 344 | ||
276 | kleave(" = 0"); | 345 | _leave(" = 0"); |
277 | return 0; | 346 | return 0; |
278 | 347 | ||
279 | error: | 348 | error_inode: |
349 | ret = PTR_ERR(inode); | ||
350 | inode = NULL; | ||
351 | error: | ||
280 | iput(inode); | 352 | iput(inode); |
281 | afs_put_volume(as->volume); | 353 | afs_put_volume(as->volume); |
282 | kfree(as); | 354 | kfree(as); |
283 | 355 | ||
284 | sb->s_fs_info = NULL; | 356 | sb->s_fs_info = NULL; |
285 | 357 | ||
286 | kleave(" = %d", ret); | 358 | _leave(" = %d", ret); |
287 | return ret; | 359 | return ret; |
288 | } /* end afs_fill_super() */ | 360 | } |
289 | 361 | ||
290 | /*****************************************************************************/ | ||
291 | /* | 362 | /* |
292 | * get an AFS superblock | 363 | * get an AFS superblock |
293 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly | 364 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly |
@@ -300,69 +371,80 @@ static int afs_get_sb(struct file_system_type *fs_type, | |||
300 | { | 371 | { |
301 | struct afs_mount_params params; | 372 | struct afs_mount_params params; |
302 | struct super_block *sb; | 373 | struct super_block *sb; |
374 | struct afs_volume *vol; | ||
375 | struct key *key; | ||
303 | int ret; | 376 | int ret; |
304 | 377 | ||
305 | _enter(",,%s,%p", dev_name, options); | 378 | _enter(",,%s,%p", dev_name, options); |
306 | 379 | ||
307 | memset(¶ms, 0, sizeof(params)); | 380 | memset(¶ms, 0, sizeof(params)); |
308 | 381 | ||
309 | /* start the cache manager */ | 382 | /* parse the options and device name */ |
310 | ret = afscm_start(); | ||
311 | if (ret < 0) { | ||
312 | _leave(" = %d", ret); | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | /* parse the options */ | ||
317 | if (options) { | 383 | if (options) { |
318 | ret = afs_super_parse_options(¶ms, options, &dev_name); | 384 | ret = afs_parse_options(¶ms, options, &dev_name); |
319 | if (ret < 0) | 385 | if (ret < 0) |
320 | goto error; | 386 | goto error; |
321 | if (!dev_name) { | ||
322 | printk("kAFS: no volume name specified\n"); | ||
323 | ret = -EINVAL; | ||
324 | goto error; | ||
325 | } | ||
326 | } | 387 | } |
327 | 388 | ||
328 | /* parse the device name */ | 389 | |
329 | ret = afs_volume_lookup(dev_name, | 390 | ret = afs_parse_device_name(¶ms, dev_name); |
330 | params.default_cell, | ||
331 | params.rwpath, | ||
332 | ¶ms.volume); | ||
333 | if (ret < 0) | 391 | if (ret < 0) |
334 | goto error; | 392 | goto error; |
335 | 393 | ||
336 | /* allocate a deviceless superblock */ | 394 | /* try and do the mount securely */ |
337 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); | 395 | key = afs_request_key(params.cell); |
338 | if (IS_ERR(sb)) | 396 | if (IS_ERR(key)) { |
397 | _leave(" = %ld [key]", PTR_ERR(key)); | ||
398 | ret = PTR_ERR(key); | ||
339 | goto error; | 399 | goto error; |
400 | } | ||
401 | params.key = key; | ||
340 | 402 | ||
341 | sb->s_flags = flags; | 403 | /* parse the device name */ |
404 | vol = afs_volume_lookup(¶ms); | ||
405 | if (IS_ERR(vol)) { | ||
406 | ret = PTR_ERR(vol); | ||
407 | goto error; | ||
408 | } | ||
409 | params.volume = vol; | ||
342 | 410 | ||
343 | ret = afs_fill_super(sb, ¶ms, flags & MS_SILENT ? 1 : 0); | 411 | /* allocate a deviceless superblock */ |
344 | if (ret < 0) { | 412 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); |
345 | up_write(&sb->s_umount); | 413 | if (IS_ERR(sb)) { |
346 | deactivate_super(sb); | 414 | ret = PTR_ERR(sb); |
347 | goto error; | 415 | goto error; |
348 | } | 416 | } |
349 | sb->s_flags |= MS_ACTIVE; | ||
350 | simple_set_mnt(mnt, sb); | ||
351 | 417 | ||
418 | if (!sb->s_root) { | ||
419 | /* initial superblock/root creation */ | ||
420 | _debug("create"); | ||
421 | sb->s_flags = flags; | ||
422 | ret = afs_fill_super(sb, ¶ms); | ||
423 | if (ret < 0) { | ||
424 | up_write(&sb->s_umount); | ||
425 | deactivate_super(sb); | ||
426 | goto error; | ||
427 | } | ||
428 | sb->s_flags |= MS_ACTIVE; | ||
429 | } else { | ||
430 | _debug("reuse"); | ||
431 | ASSERTCMP(sb->s_flags, &, MS_ACTIVE); | ||
432 | } | ||
433 | |||
434 | simple_set_mnt(mnt, sb); | ||
352 | afs_put_volume(params.volume); | 435 | afs_put_volume(params.volume); |
353 | afs_put_cell(params.default_cell); | 436 | afs_put_cell(params.cell); |
354 | _leave(" = 0 [%p]", 0, sb); | 437 | _leave(" = 0 [%p]", sb); |
355 | return 0; | 438 | return 0; |
356 | 439 | ||
357 | error: | 440 | error: |
358 | afs_put_volume(params.volume); | 441 | afs_put_volume(params.volume); |
359 | afs_put_cell(params.default_cell); | 442 | afs_put_cell(params.cell); |
360 | afscm_stop(); | 443 | key_put(params.key); |
361 | _leave(" = %d", ret); | 444 | _leave(" = %d", ret); |
362 | return ret; | 445 | return ret; |
363 | } /* end afs_get_sb() */ | 446 | } |
364 | 447 | ||
365 | /*****************************************************************************/ | ||
366 | /* | 448 | /* |
367 | * finish the unmounting process on the superblock | 449 | * finish the unmounting process on the superblock |
368 | */ | 450 | */ |
@@ -373,35 +455,30 @@ static void afs_put_super(struct super_block *sb) | |||
373 | _enter(""); | 455 | _enter(""); |
374 | 456 | ||
375 | afs_put_volume(as->volume); | 457 | afs_put_volume(as->volume); |
376 | afscm_stop(); | ||
377 | 458 | ||
378 | _leave(""); | 459 | _leave(""); |
379 | } /* end afs_put_super() */ | 460 | } |
380 | 461 | ||
381 | /*****************************************************************************/ | ||
382 | /* | 462 | /* |
383 | * initialise an inode cache slab element prior to any use | 463 | * initialise an inode cache slab element prior to any use |
384 | */ | 464 | */ |
385 | static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, | 465 | static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, |
386 | unsigned long flags) | 466 | unsigned long flags) |
387 | { | 467 | { |
388 | struct afs_vnode *vnode = (struct afs_vnode *) _vnode; | 468 | struct afs_vnode *vnode = _vnode; |
389 | 469 | ||
390 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 470 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
391 | SLAB_CTOR_CONSTRUCTOR) { | 471 | SLAB_CTOR_CONSTRUCTOR) { |
392 | memset(vnode, 0, sizeof(*vnode)); | 472 | memset(vnode, 0, sizeof(*vnode)); |
393 | inode_init_once(&vnode->vfs_inode); | 473 | inode_init_once(&vnode->vfs_inode); |
394 | init_waitqueue_head(&vnode->update_waitq); | 474 | init_waitqueue_head(&vnode->update_waitq); |
475 | mutex_init(&vnode->permits_lock); | ||
476 | mutex_init(&vnode->validate_lock); | ||
395 | spin_lock_init(&vnode->lock); | 477 | spin_lock_init(&vnode->lock); |
396 | INIT_LIST_HEAD(&vnode->cb_link); | 478 | INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); |
397 | INIT_LIST_HEAD(&vnode->cb_hash_link); | ||
398 | afs_timer_init(&vnode->cb_timeout, | ||
399 | &afs_vnode_cb_timed_out_ops); | ||
400 | } | 479 | } |
480 | } | ||
401 | 481 | ||
402 | } /* end afs_i_init_once() */ | ||
403 | |||
404 | /*****************************************************************************/ | ||
405 | /* | 482 | /* |
406 | * allocate an AFS inode struct from our slab cache | 483 | * allocate an AFS inode struct from our slab cache |
407 | */ | 484 | */ |
@@ -409,8 +486,7 @@ static struct inode *afs_alloc_inode(struct super_block *sb) | |||
409 | { | 486 | { |
410 | struct afs_vnode *vnode; | 487 | struct afs_vnode *vnode; |
411 | 488 | ||
412 | vnode = (struct afs_vnode *) | 489 | vnode = kmem_cache_alloc(afs_inode_cachep, GFP_KERNEL); |
413 | kmem_cache_alloc(afs_inode_cachep, GFP_KERNEL); | ||
414 | if (!vnode) | 490 | if (!vnode) |
415 | return NULL; | 491 | return NULL; |
416 | 492 | ||
@@ -421,21 +497,25 @@ static struct inode *afs_alloc_inode(struct super_block *sb) | |||
421 | 497 | ||
422 | vnode->volume = NULL; | 498 | vnode->volume = NULL; |
423 | vnode->update_cnt = 0; | 499 | vnode->update_cnt = 0; |
424 | vnode->flags = 0; | 500 | vnode->flags = 1 << AFS_VNODE_UNSET; |
501 | vnode->cb_promised = false; | ||
425 | 502 | ||
426 | return &vnode->vfs_inode; | 503 | return &vnode->vfs_inode; |
427 | } /* end afs_alloc_inode() */ | 504 | } |
428 | 505 | ||
429 | /*****************************************************************************/ | ||
430 | /* | 506 | /* |
431 | * destroy an AFS inode struct | 507 | * destroy an AFS inode struct |
432 | */ | 508 | */ |
433 | static void afs_destroy_inode(struct inode *inode) | 509 | static void afs_destroy_inode(struct inode *inode) |
434 | { | 510 | { |
511 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
512 | |||
435 | _enter("{%lu}", inode->i_ino); | 513 | _enter("{%lu}", inode->i_ino); |
436 | 514 | ||
437 | kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode)); | 515 | _debug("DESTROY INODE %p", inode); |
438 | 516 | ||
439 | atomic_dec(&afs_count_active_inodes); | 517 | ASSERTCMP(vnode->server, ==, NULL); |
440 | 518 | ||
441 | } /* end afs_destroy_inode() */ | 519 | kmem_cache_free(afs_inode_cachep, vnode); |
520 | atomic_dec(&afs_count_active_inodes); | ||
521 | } | ||