diff options
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/cache.c | 12 | ||||
-rw-r--r-- | fs/afs/cell.c | 2 | ||||
-rw-r--r-- | fs/afs/cmservice.c | 12 | ||||
-rw-r--r-- | fs/afs/dir.c | 23 | ||||
-rw-r--r-- | fs/afs/flock.c | 5 | ||||
-rw-r--r-- | fs/afs/fsclient.c | 3 | ||||
-rw-r--r-- | fs/afs/inode.c | 13 | ||||
-rw-r--r-- | fs/afs/internal.h | 5 | ||||
-rw-r--r-- | fs/afs/main.c | 13 | ||||
-rw-r--r-- | fs/afs/mntpt.c | 64 | ||||
-rw-r--r-- | fs/afs/rxrpc.c | 2 | ||||
-rw-r--r-- | fs/afs/security.c | 7 | ||||
-rw-r--r-- | fs/afs/server.c | 13 | ||||
-rw-r--r-- | fs/afs/super.c | 109 | ||||
-rw-r--r-- | fs/afs/vlocation.c | 14 | ||||
-rw-r--r-- | fs/afs/write.c | 41 |
16 files changed, 150 insertions, 188 deletions
diff --git a/fs/afs/cache.c b/fs/afs/cache.c index 0fb315dd4d2a..577763c3d88b 100644 --- a/fs/afs/cache.c +++ b/fs/afs/cache.c | |||
@@ -98,7 +98,7 @@ static uint16_t afs_cell_cache_get_key(const void *cookie_netfs_data, | |||
98 | } | 98 | } |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * provide new auxilliary cache data | 101 | * provide new auxiliary cache data |
102 | */ | 102 | */ |
103 | static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, | 103 | static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, |
104 | void *buffer, uint16_t bufmax) | 104 | void *buffer, uint16_t bufmax) |
@@ -117,7 +117,7 @@ static uint16_t afs_cell_cache_get_aux(const void *cookie_netfs_data, | |||
117 | } | 117 | } |
118 | 118 | ||
119 | /* | 119 | /* |
120 | * check that the auxilliary data indicates that the entry is still valid | 120 | * check that the auxiliary data indicates that the entry is still valid |
121 | */ | 121 | */ |
122 | static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data, | 122 | static enum fscache_checkaux afs_cell_cache_check_aux(void *cookie_netfs_data, |
123 | const void *buffer, | 123 | const void *buffer, |
@@ -150,7 +150,7 @@ static uint16_t afs_vlocation_cache_get_key(const void *cookie_netfs_data, | |||
150 | } | 150 | } |
151 | 151 | ||
152 | /* | 152 | /* |
153 | * provide new auxilliary cache data | 153 | * provide new auxiliary cache data |
154 | */ | 154 | */ |
155 | static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, | 155 | static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, |
156 | void *buffer, uint16_t bufmax) | 156 | void *buffer, uint16_t bufmax) |
@@ -172,7 +172,7 @@ static uint16_t afs_vlocation_cache_get_aux(const void *cookie_netfs_data, | |||
172 | } | 172 | } |
173 | 173 | ||
174 | /* | 174 | /* |
175 | * check that the auxilliary data indicates that the entry is still valid | 175 | * check that the auxiliary data indicates that the entry is still valid |
176 | */ | 176 | */ |
177 | static | 177 | static |
178 | enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data, | 178 | enum fscache_checkaux afs_vlocation_cache_check_aux(void *cookie_netfs_data, |
@@ -283,7 +283,7 @@ static void afs_vnode_cache_get_attr(const void *cookie_netfs_data, | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * provide new auxilliary cache data | 286 | * provide new auxiliary cache data |
287 | */ | 287 | */ |
288 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | 288 | static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, |
289 | void *buffer, uint16_t bufmax) | 289 | void *buffer, uint16_t bufmax) |
@@ -309,7 +309,7 @@ static uint16_t afs_vnode_cache_get_aux(const void *cookie_netfs_data, | |||
309 | } | 309 | } |
310 | 310 | ||
311 | /* | 311 | /* |
312 | * check that the auxilliary data indicates that the entry is still valid | 312 | * check that the auxiliary data indicates that the entry is still valid |
313 | */ | 313 | */ |
314 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, | 314 | static enum fscache_checkaux afs_vnode_cache_check_aux(void *cookie_netfs_data, |
315 | const void *buffer, | 315 | const void *buffer, |
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index 0d5eeadf6121..3c090b7555ea 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -293,7 +293,7 @@ struct afs_cell *afs_cell_lookup(const char *name, unsigned namesz, | |||
293 | if (!cell) { | 293 | if (!cell) { |
294 | /* this should not happen unless user tries to mount | 294 | /* this should not happen unless user tries to mount |
295 | * when root cell is not set. Return an impossibly | 295 | * when root cell is not set. Return an impossibly |
296 | * bizzare errno to alert the user. Things like | 296 | * bizarre errno to alert the user. Things like |
297 | * ENOENT might be "more appropriate" but they happen | 297 | * ENOENT might be "more appropriate" but they happen |
298 | * for other reasons. | 298 | * for other reasons. |
299 | */ | 299 | */ |
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index a3bcec75c54a..1c8c6cc6de30 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
@@ -289,7 +289,7 @@ static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, | |||
289 | call->server = server; | 289 | call->server = server; |
290 | 290 | ||
291 | INIT_WORK(&call->work, SRXAFSCB_CallBack); | 291 | INIT_WORK(&call->work, SRXAFSCB_CallBack); |
292 | schedule_work(&call->work); | 292 | queue_work(afs_wq, &call->work); |
293 | return 0; | 293 | return 0; |
294 | } | 294 | } |
295 | 295 | ||
@@ -336,7 +336,7 @@ static int afs_deliver_cb_init_call_back_state(struct afs_call *call, | |||
336 | call->server = server; | 336 | call->server = server; |
337 | 337 | ||
338 | INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); | 338 | INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); |
339 | schedule_work(&call->work); | 339 | queue_work(afs_wq, &call->work); |
340 | return 0; | 340 | return 0; |
341 | } | 341 | } |
342 | 342 | ||
@@ -367,7 +367,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, | |||
367 | call->server = server; | 367 | call->server = server; |
368 | 368 | ||
369 | INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); | 369 | INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); |
370 | schedule_work(&call->work); | 370 | queue_work(afs_wq, &call->work); |
371 | return 0; | 371 | return 0; |
372 | } | 372 | } |
373 | 373 | ||
@@ -400,7 +400,7 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb, | |||
400 | call->state = AFS_CALL_REPLYING; | 400 | call->state = AFS_CALL_REPLYING; |
401 | 401 | ||
402 | INIT_WORK(&call->work, SRXAFSCB_Probe); | 402 | INIT_WORK(&call->work, SRXAFSCB_Probe); |
403 | schedule_work(&call->work); | 403 | queue_work(afs_wq, &call->work); |
404 | return 0; | 404 | return 0; |
405 | } | 405 | } |
406 | 406 | ||
@@ -496,7 +496,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, | |||
496 | call->state = AFS_CALL_REPLYING; | 496 | call->state = AFS_CALL_REPLYING; |
497 | 497 | ||
498 | INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); | 498 | INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); |
499 | schedule_work(&call->work); | 499 | queue_work(afs_wq, &call->work); |
500 | return 0; | 500 | return 0; |
501 | } | 501 | } |
502 | 502 | ||
@@ -580,6 +580,6 @@ static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call, | |||
580 | call->state = AFS_CALL_REPLYING; | 580 | call->state = AFS_CALL_REPLYING; |
581 | 581 | ||
582 | INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); | 582 | INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); |
583 | schedule_work(&call->work); | 583 | queue_work(afs_wq, &call->work); |
584 | return 0; | 584 | return 0; |
585 | } | 585 | } |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 0d38c09bd55e..1b0b19550015 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
16 | #include <linux/namei.h> | ||
16 | #include <linux/pagemap.h> | 17 | #include <linux/pagemap.h> |
17 | #include <linux/ctype.h> | 18 | #include <linux/ctype.h> |
18 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
@@ -23,7 +24,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
23 | static int afs_dir_open(struct inode *inode, struct file *file); | 24 | static int afs_dir_open(struct inode *inode, struct file *file); |
24 | static int afs_readdir(struct file *file, void *dirent, filldir_t filldir); | 25 | static int afs_readdir(struct file *file, void *dirent, filldir_t filldir); |
25 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); | 26 | static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); |
26 | static int afs_d_delete(struct dentry *dentry); | 27 | static int afs_d_delete(const struct dentry *dentry); |
27 | static void afs_d_release(struct dentry *dentry); | 28 | static void afs_d_release(struct dentry *dentry); |
28 | static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, | 29 | static int afs_lookup_filldir(void *_cookie, const char *name, int nlen, |
29 | loff_t fpos, u64 ino, unsigned dtype); | 30 | loff_t fpos, u64 ino, unsigned dtype); |
@@ -61,10 +62,11 @@ const struct inode_operations afs_dir_inode_operations = { | |||
61 | .setattr = afs_setattr, | 62 | .setattr = afs_setattr, |
62 | }; | 63 | }; |
63 | 64 | ||
64 | static const struct dentry_operations afs_fs_dentry_operations = { | 65 | const struct dentry_operations afs_fs_dentry_operations = { |
65 | .d_revalidate = afs_d_revalidate, | 66 | .d_revalidate = afs_d_revalidate, |
66 | .d_delete = afs_d_delete, | 67 | .d_delete = afs_d_delete, |
67 | .d_release = afs_d_release, | 68 | .d_release = afs_d_release, |
69 | .d_automount = afs_d_automount, | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | #define AFS_DIR_HASHTBL_SIZE 128 | 72 | #define AFS_DIR_HASHTBL_SIZE 128 |
@@ -581,14 +583,12 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
581 | } | 583 | } |
582 | 584 | ||
583 | success: | 585 | success: |
584 | dentry->d_op = &afs_fs_dentry_operations; | ||
585 | |||
586 | d_add(dentry, inode); | 586 | d_add(dentry, inode); |
587 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }", | 587 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }", |
588 | fid.vnode, | 588 | fid.vnode, |
589 | fid.unique, | 589 | fid.unique, |
590 | dentry->d_inode->i_ino, | 590 | dentry->d_inode->i_ino, |
591 | (unsigned long long)dentry->d_inode->i_version); | 591 | dentry->d_inode->i_generation); |
592 | 592 | ||
593 | return NULL; | 593 | return NULL; |
594 | } | 594 | } |
@@ -607,6 +607,9 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
607 | void *dir_version; | 607 | void *dir_version; |
608 | int ret; | 608 | int ret; |
609 | 609 | ||
610 | if (nd->flags & LOOKUP_RCU) | ||
611 | return -ECHILD; | ||
612 | |||
610 | vnode = AFS_FS_I(dentry->d_inode); | 613 | vnode = AFS_FS_I(dentry->d_inode); |
611 | 614 | ||
612 | if (dentry->d_inode) | 615 | if (dentry->d_inode) |
@@ -668,10 +671,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
668 | * been deleted and replaced, and the original vnode ID has | 671 | * been deleted and replaced, and the original vnode ID has |
669 | * been reused */ | 672 | * been reused */ |
670 | if (fid.unique != vnode->fid.unique) { | 673 | if (fid.unique != vnode->fid.unique) { |
671 | _debug("%s: file deleted (uq %u -> %u I:%llu)", | 674 | _debug("%s: file deleted (uq %u -> %u I:%u)", |
672 | dentry->d_name.name, fid.unique, | 675 | dentry->d_name.name, fid.unique, |
673 | vnode->fid.unique, | 676 | vnode->fid.unique, |
674 | (unsigned long long)dentry->d_inode->i_version); | 677 | dentry->d_inode->i_generation); |
675 | spin_lock(&vnode->lock); | 678 | spin_lock(&vnode->lock); |
676 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 679 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
677 | spin_unlock(&vnode->lock); | 680 | spin_unlock(&vnode->lock); |
@@ -730,7 +733,7 @@ out_bad: | |||
730 | * - called from dput() when d_count is going to 0. | 733 | * - called from dput() when d_count is going to 0. |
731 | * - return 1 to request dentry be unhashed, 0 otherwise | 734 | * - return 1 to request dentry be unhashed, 0 otherwise |
732 | */ | 735 | */ |
733 | static int afs_d_delete(struct dentry *dentry) | 736 | static int afs_d_delete(const struct dentry *dentry) |
734 | { | 737 | { |
735 | _enter("%s", dentry->d_name.name); | 738 | _enter("%s", dentry->d_name.name); |
736 | 739 | ||
@@ -1045,7 +1048,7 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
1045 | if (ret < 0) | 1048 | if (ret < 0) |
1046 | goto link_error; | 1049 | goto link_error; |
1047 | 1050 | ||
1048 | atomic_inc(&vnode->vfs_inode.i_count); | 1051 | ihold(&vnode->vfs_inode); |
1049 | d_instantiate(dentry, &vnode->vfs_inode); | 1052 | d_instantiate(dentry, &vnode->vfs_inode); |
1050 | key_put(key); | 1053 | key_put(key); |
1051 | _leave(" = 0"); | 1054 | _leave(" = 0"); |
diff --git a/fs/afs/flock.c b/fs/afs/flock.c index 0931bc1325eb..757d664575dd 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c | |||
@@ -9,7 +9,6 @@ | |||
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/smp_lock.h> | ||
13 | #include "internal.h" | 12 | #include "internal.h" |
14 | 13 | ||
15 | #define AFS_LOCK_GRANTED 0 | 14 | #define AFS_LOCK_GRANTED 0 |
@@ -274,7 +273,7 @@ static int afs_do_setlk(struct file *file, struct file_lock *fl) | |||
274 | 273 | ||
275 | type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE; | 274 | type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE; |
276 | 275 | ||
277 | lock_kernel(); | 276 | lock_flocks(); |
278 | 277 | ||
279 | /* make sure we've got a callback on this file and that our view of the | 278 | /* make sure we've got a callback on this file and that our view of the |
280 | * data version is up to date */ | 279 | * data version is up to date */ |
@@ -421,7 +420,7 @@ given_lock: | |||
421 | afs_vnode_fetch_status(vnode, NULL, key); | 420 | afs_vnode_fetch_status(vnode, NULL, key); |
422 | 421 | ||
423 | error: | 422 | error: |
424 | unlock_kernel(); | 423 | unlock_flocks(); |
425 | _leave(" = %d", ret); | 424 | _leave(" = %d", ret); |
426 | return ret; | 425 | return ret; |
427 | 426 | ||
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 4bd0218473a9..346e3289abd7 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
@@ -89,7 +89,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
89 | i_size_write(&vnode->vfs_inode, size); | 89 | i_size_write(&vnode->vfs_inode, size); |
90 | vnode->vfs_inode.i_uid = status->owner; | 90 | vnode->vfs_inode.i_uid = status->owner; |
91 | vnode->vfs_inode.i_gid = status->group; | 91 | vnode->vfs_inode.i_gid = status->group; |
92 | vnode->vfs_inode.i_version = vnode->fid.unique; | 92 | vnode->vfs_inode.i_generation = vnode->fid.unique; |
93 | vnode->vfs_inode.i_nlink = status->nlink; | 93 | vnode->vfs_inode.i_nlink = status->nlink; |
94 | 94 | ||
95 | mode = vnode->vfs_inode.i_mode; | 95 | mode = vnode->vfs_inode.i_mode; |
@@ -102,6 +102,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
102 | vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; | 102 | vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; |
103 | vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; | 103 | vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; |
104 | vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; | 104 | vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; |
105 | vnode->vfs_inode.i_version = data_version; | ||
105 | } | 106 | } |
106 | 107 | ||
107 | expected_version = status->data_version; | 108 | expected_version = status->data_version; |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index 0747339011c3..0fdab6e03d87 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
@@ -75,7 +75,8 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) | |||
75 | inode->i_ctime.tv_nsec = 0; | 75 | inode->i_ctime.tv_nsec = 0; |
76 | inode->i_atime = inode->i_mtime = inode->i_ctime; | 76 | inode->i_atime = inode->i_mtime = inode->i_ctime; |
77 | inode->i_blocks = 0; | 77 | inode->i_blocks = 0; |
78 | inode->i_version = vnode->fid.unique; | 78 | inode->i_generation = vnode->fid.unique; |
79 | inode->i_version = vnode->status.data_version; | ||
79 | inode->i_mapping->a_ops = &afs_fs_aops; | 80 | inode->i_mapping->a_ops = &afs_fs_aops; |
80 | 81 | ||
81 | /* check to see whether a symbolic link is really a mountpoint */ | 82 | /* check to see whether a symbolic link is really a mountpoint */ |
@@ -100,7 +101,7 @@ static int afs_iget5_test(struct inode *inode, void *opaque) | |||
100 | struct afs_iget_data *data = opaque; | 101 | struct afs_iget_data *data = opaque; |
101 | 102 | ||
102 | return inode->i_ino == data->fid.vnode && | 103 | return inode->i_ino == data->fid.vnode && |
103 | inode->i_version == data->fid.unique; | 104 | inode->i_generation == data->fid.unique; |
104 | } | 105 | } |
105 | 106 | ||
106 | /* | 107 | /* |
@@ -122,7 +123,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque) | |||
122 | struct afs_vnode *vnode = AFS_FS_I(inode); | 123 | struct afs_vnode *vnode = AFS_FS_I(inode); |
123 | 124 | ||
124 | inode->i_ino = data->fid.vnode; | 125 | inode->i_ino = data->fid.vnode; |
125 | inode->i_version = data->fid.unique; | 126 | inode->i_generation = data->fid.unique; |
126 | vnode->fid = data->fid; | 127 | vnode->fid = data->fid; |
127 | vnode->volume = data->volume; | 128 | vnode->volume = data->volume; |
128 | 129 | ||
@@ -184,7 +185,8 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, | |||
184 | inode->i_generation = 0; | 185 | inode->i_generation = 0; |
185 | 186 | ||
186 | set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags); | 187 | set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags); |
187 | inode->i_flags |= S_NOATIME; | 188 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); |
189 | inode->i_flags |= S_AUTOMOUNT | S_NOATIME; | ||
188 | unlock_new_inode(inode); | 190 | unlock_new_inode(inode); |
189 | _leave(" = %p", inode); | 191 | _leave(" = %p", inode); |
190 | return inode; | 192 | return inode; |
@@ -379,8 +381,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
379 | 381 | ||
380 | inode = dentry->d_inode; | 382 | inode = dentry->d_inode; |
381 | 383 | ||
382 | _enter("{ ino=%lu v=%llu }", inode->i_ino, | 384 | _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation); |
383 | (unsigned long long)inode->i_version); | ||
384 | 385 | ||
385 | generic_fillattr(inode, stat); | 386 | generic_fillattr(inode, stat); |
386 | return 0; | 387 | return 0; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index cca8eef736fc..5a9b6843bac1 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
@@ -486,6 +486,7 @@ extern bool afs_cm_incoming_call(struct afs_call *); | |||
486 | * dir.c | 486 | * dir.c |
487 | */ | 487 | */ |
488 | extern const struct inode_operations afs_dir_inode_operations; | 488 | extern const struct inode_operations afs_dir_inode_operations; |
489 | extern const struct dentry_operations afs_fs_dentry_operations; | ||
489 | extern const struct file_operations afs_dir_file_operations; | 490 | extern const struct file_operations afs_dir_file_operations; |
490 | 491 | ||
491 | /* | 492 | /* |
@@ -576,6 +577,7 @@ extern int afs_drop_inode(struct inode *); | |||
576 | /* | 577 | /* |
577 | * main.c | 578 | * main.c |
578 | */ | 579 | */ |
580 | extern struct workqueue_struct *afs_wq; | ||
579 | extern struct afs_uuid afs_uuid; | 581 | extern struct afs_uuid afs_uuid; |
580 | 582 | ||
581 | /* | 583 | /* |
@@ -590,6 +592,7 @@ extern const struct inode_operations afs_mntpt_inode_operations; | |||
590 | extern const struct inode_operations afs_autocell_inode_operations; | 592 | extern const struct inode_operations afs_autocell_inode_operations; |
591 | extern const struct file_operations afs_mntpt_file_operations; | 593 | extern const struct file_operations afs_mntpt_file_operations; |
592 | 594 | ||
595 | extern struct vfsmount *afs_d_automount(struct path *); | ||
593 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); | 596 | extern int afs_mntpt_check_symlink(struct afs_vnode *, struct key *); |
594 | extern void afs_mntpt_kill_timer(void); | 597 | extern void afs_mntpt_kill_timer(void); |
595 | 598 | ||
@@ -624,7 +627,7 @@ extern void afs_clear_permits(struct afs_vnode *); | |||
624 | extern void afs_cache_permit(struct afs_vnode *, struct key *, long); | 627 | extern void afs_cache_permit(struct afs_vnode *, struct key *, long); |
625 | extern void afs_zap_permits(struct rcu_head *); | 628 | extern void afs_zap_permits(struct rcu_head *); |
626 | extern struct key *afs_request_key(struct afs_cell *); | 629 | extern struct key *afs_request_key(struct afs_cell *); |
627 | extern int afs_permission(struct inode *, int); | 630 | extern int afs_permission(struct inode *, int, unsigned int); |
628 | 631 | ||
629 | /* | 632 | /* |
630 | * server.c | 633 | * server.c |
diff --git a/fs/afs/main.c b/fs/afs/main.c index cfd1cbe25b22..42dd2e499ed8 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
@@ -30,6 +30,7 @@ module_param(rootcell, charp, 0); | |||
30 | MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); | 30 | MODULE_PARM_DESC(rootcell, "root AFS cell name and VL server IP addr list"); |
31 | 31 | ||
32 | struct afs_uuid afs_uuid; | 32 | struct afs_uuid afs_uuid; |
33 | struct workqueue_struct *afs_wq; | ||
33 | 34 | ||
34 | /* | 35 | /* |
35 | * get a client UUID | 36 | * get a client UUID |
@@ -87,10 +88,16 @@ static int __init afs_init(void) | |||
87 | if (ret < 0) | 88 | if (ret < 0) |
88 | return ret; | 89 | return ret; |
89 | 90 | ||
91 | /* create workqueue */ | ||
92 | ret = -ENOMEM; | ||
93 | afs_wq = alloc_workqueue("afs", 0, 0); | ||
94 | if (!afs_wq) | ||
95 | return ret; | ||
96 | |||
90 | /* register the /proc stuff */ | 97 | /* register the /proc stuff */ |
91 | ret = afs_proc_init(); | 98 | ret = afs_proc_init(); |
92 | if (ret < 0) | 99 | if (ret < 0) |
93 | return ret; | 100 | goto error_proc; |
94 | 101 | ||
95 | #ifdef CONFIG_AFS_FSCACHE | 102 | #ifdef CONFIG_AFS_FSCACHE |
96 | /* we want to be able to cache */ | 103 | /* we want to be able to cache */ |
@@ -140,6 +147,8 @@ error_cell_init: | |||
140 | error_cache: | 147 | error_cache: |
141 | #endif | 148 | #endif |
142 | afs_proc_cleanup(); | 149 | afs_proc_cleanup(); |
150 | error_proc: | ||
151 | destroy_workqueue(afs_wq); | ||
143 | rcu_barrier(); | 152 | rcu_barrier(); |
144 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); | 153 | printk(KERN_ERR "kAFS: failed to register: %d\n", ret); |
145 | return ret; | 154 | return ret; |
@@ -163,7 +172,7 @@ static void __exit afs_exit(void) | |||
163 | afs_purge_servers(); | 172 | afs_purge_servers(); |
164 | afs_callback_update_kill(); | 173 | afs_callback_update_kill(); |
165 | afs_vlocation_purge(); | 174 | afs_vlocation_purge(); |
166 | flush_scheduled_work(); | 175 | destroy_workqueue(afs_wq); |
167 | afs_cell_purge(); | 176 | afs_cell_purge(); |
168 | #ifdef CONFIG_AFS_FSCACHE | 177 | #ifdef CONFIG_AFS_FSCACHE |
169 | fscache_unregister_netfs(&afs_cache_netfs); | 178 | fscache_unregister_netfs(&afs_cache_netfs); |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 6d552686c498..aa59184151d0 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -24,22 +24,20 @@ static struct dentry *afs_mntpt_lookup(struct inode *dir, | |||
24 | struct dentry *dentry, | 24 | struct dentry *dentry, |
25 | struct nameidata *nd); | 25 | struct nameidata *nd); |
26 | static int afs_mntpt_open(struct inode *inode, struct file *file); | 26 | static int afs_mntpt_open(struct inode *inode, struct file *file); |
27 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd); | ||
28 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); | 27 | static void afs_mntpt_expiry_timed_out(struct work_struct *work); |
29 | 28 | ||
30 | const struct file_operations afs_mntpt_file_operations = { | 29 | const struct file_operations afs_mntpt_file_operations = { |
31 | .open = afs_mntpt_open, | 30 | .open = afs_mntpt_open, |
31 | .llseek = noop_llseek, | ||
32 | }; | 32 | }; |
33 | 33 | ||
34 | const struct inode_operations afs_mntpt_inode_operations = { | 34 | const struct inode_operations afs_mntpt_inode_operations = { |
35 | .lookup = afs_mntpt_lookup, | 35 | .lookup = afs_mntpt_lookup, |
36 | .follow_link = afs_mntpt_follow_link, | ||
37 | .readlink = page_readlink, | 36 | .readlink = page_readlink, |
38 | .getattr = afs_getattr, | 37 | .getattr = afs_getattr, |
39 | }; | 38 | }; |
40 | 39 | ||
41 | const struct inode_operations afs_autocell_inode_operations = { | 40 | const struct inode_operations afs_autocell_inode_operations = { |
42 | .follow_link = afs_mntpt_follow_link, | ||
43 | .getattr = afs_getattr, | 41 | .getattr = afs_getattr, |
44 | }; | 42 | }; |
45 | 43 | ||
@@ -87,6 +85,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode, struct key *key) | |||
87 | _debug("symlink is a mountpoint"); | 85 | _debug("symlink is a mountpoint"); |
88 | spin_lock(&vnode->lock); | 86 | spin_lock(&vnode->lock); |
89 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); | 87 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); |
88 | vnode->vfs_inode.i_flags |= S_AUTOMOUNT; | ||
90 | spin_unlock(&vnode->lock); | 89 | spin_unlock(&vnode->lock); |
91 | } | 90 | } |
92 | 91 | ||
@@ -237,52 +236,24 @@ error_no_devname: | |||
237 | } | 236 | } |
238 | 237 | ||
239 | /* | 238 | /* |
240 | * follow a link from a mountpoint directory, thus causing it to be mounted | 239 | * handle an automount point |
241 | */ | 240 | */ |
242 | static void *afs_mntpt_follow_link(struct dentry *dentry, struct nameidata *nd) | 241 | struct vfsmount *afs_d_automount(struct path *path) |
243 | { | 242 | { |
244 | struct vfsmount *newmnt; | 243 | struct vfsmount *newmnt; |
245 | int err; | ||
246 | 244 | ||
247 | _enter("%p{%s},{%s:%p{%s},}", | 245 | _enter("{%s,%s}", path->mnt->mnt_devname, path->dentry->d_name.name); |
248 | dentry, | ||
249 | dentry->d_name.name, | ||
250 | nd->path.mnt->mnt_devname, | ||
251 | dentry, | ||
252 | nd->path.dentry->d_name.name); | ||
253 | |||
254 | dput(nd->path.dentry); | ||
255 | nd->path.dentry = dget(dentry); | ||
256 | 246 | ||
257 | newmnt = afs_mntpt_do_automount(nd->path.dentry); | 247 | newmnt = afs_mntpt_do_automount(path->dentry); |
258 | if (IS_ERR(newmnt)) { | 248 | if (IS_ERR(newmnt)) |
259 | path_put(&nd->path); | 249 | return newmnt; |
260 | return (void *)newmnt; | ||
261 | } | ||
262 | |||
263 | mntget(newmnt); | ||
264 | err = do_add_mount(newmnt, &nd->path, MNT_SHRINKABLE, &afs_vfsmounts); | ||
265 | switch (err) { | ||
266 | case 0: | ||
267 | path_put(&nd->path); | ||
268 | nd->path.mnt = newmnt; | ||
269 | nd->path.dentry = dget(newmnt->mnt_root); | ||
270 | schedule_delayed_work(&afs_mntpt_expiry_timer, | ||
271 | afs_mntpt_expiry_timeout * HZ); | ||
272 | break; | ||
273 | case -EBUSY: | ||
274 | /* someone else made a mount here whilst we were busy */ | ||
275 | while (d_mountpoint(nd->path.dentry) && | ||
276 | follow_down(&nd->path)) | ||
277 | ; | ||
278 | err = 0; | ||
279 | default: | ||
280 | mntput(newmnt); | ||
281 | break; | ||
282 | } | ||
283 | 250 | ||
284 | _leave(" = %d", err); | 251 | mntget(newmnt); /* prevent immediate expiration */ |
285 | return ERR_PTR(err); | 252 | mnt_set_expiry(newmnt, &afs_vfsmounts); |
253 | queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, | ||
254 | afs_mntpt_expiry_timeout * HZ); | ||
255 | _leave(" = %p {%s}", newmnt, newmnt->mnt_devname); | ||
256 | return newmnt; | ||
286 | } | 257 | } |
287 | 258 | ||
288 | /* | 259 | /* |
@@ -294,8 +265,8 @@ static void afs_mntpt_expiry_timed_out(struct work_struct *work) | |||
294 | 265 | ||
295 | if (!list_empty(&afs_vfsmounts)) { | 266 | if (!list_empty(&afs_vfsmounts)) { |
296 | mark_mounts_for_expiry(&afs_vfsmounts); | 267 | mark_mounts_for_expiry(&afs_vfsmounts); |
297 | schedule_delayed_work(&afs_mntpt_expiry_timer, | 268 | queue_delayed_work(afs_wq, &afs_mntpt_expiry_timer, |
298 | afs_mntpt_expiry_timeout * HZ); | 269 | afs_mntpt_expiry_timeout * HZ); |
299 | } | 270 | } |
300 | 271 | ||
301 | _leave(""); | 272 | _leave(""); |
@@ -309,6 +280,5 @@ void afs_mntpt_kill_timer(void) | |||
309 | _enter(""); | 280 | _enter(""); |
310 | 281 | ||
311 | ASSERT(list_empty(&afs_vfsmounts)); | 282 | ASSERT(list_empty(&afs_vfsmounts)); |
312 | cancel_delayed_work(&afs_mntpt_expiry_timer); | 283 | cancel_delayed_work_sync(&afs_mntpt_expiry_timer); |
313 | flush_scheduled_work(); | ||
314 | } | 284 | } |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 654d8fdbf01f..e45a323aebb4 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
@@ -410,7 +410,7 @@ static void afs_rx_interceptor(struct sock *sk, unsigned long user_call_ID, | |||
410 | if (!call) { | 410 | if (!call) { |
411 | /* its an incoming call for our callback service */ | 411 | /* its an incoming call for our callback service */ |
412 | skb_queue_tail(&afs_incoming_calls, skb); | 412 | skb_queue_tail(&afs_incoming_calls, skb); |
413 | schedule_work(&afs_collect_incoming_call_work); | 413 | queue_work(afs_wq, &afs_collect_incoming_call_work); |
414 | } else { | 414 | } else { |
415 | /* route the messages directly to the appropriate call */ | 415 | /* route the messages directly to the appropriate call */ |
416 | skb_queue_tail(&call->rx_queue, skb); | 416 | skb_queue_tail(&call->rx_queue, skb); |
diff --git a/fs/afs/security.c b/fs/afs/security.c index bb4ed144d0e4..f44b9d355377 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
@@ -285,13 +285,16 @@ static int afs_check_permit(struct afs_vnode *vnode, struct key *key, | |||
285 | * - AFS ACLs are attached to directories only, and a file is controlled by its | 285 | * - AFS ACLs are attached to directories only, and a file is controlled by its |
286 | * parent directory's ACL | 286 | * parent directory's ACL |
287 | */ | 287 | */ |
288 | int afs_permission(struct inode *inode, int mask) | 288 | int afs_permission(struct inode *inode, int mask, unsigned int flags) |
289 | { | 289 | { |
290 | struct afs_vnode *vnode = AFS_FS_I(inode); | 290 | struct afs_vnode *vnode = AFS_FS_I(inode); |
291 | afs_access_t uninitialized_var(access); | 291 | afs_access_t uninitialized_var(access); |
292 | struct key *key; | 292 | struct key *key; |
293 | int ret; | 293 | int ret; |
294 | 294 | ||
295 | if (flags & IPERM_FLAG_RCU) | ||
296 | return -ECHILD; | ||
297 | |||
295 | _enter("{{%x:%u},%lx},%x,", | 298 | _enter("{{%x:%u},%lx},%x,", |
296 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); | 299 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, mask); |
297 | 300 | ||
@@ -347,7 +350,7 @@ int afs_permission(struct inode *inode, int mask) | |||
347 | } | 350 | } |
348 | 351 | ||
349 | key_put(key); | 352 | key_put(key); |
350 | ret = generic_permission(inode, mask, NULL); | 353 | ret = generic_permission(inode, mask, flags, NULL); |
351 | _leave(" = %d", ret); | 354 | _leave(" = %d", ret); |
352 | return ret; | 355 | return ret; |
353 | 356 | ||
diff --git a/fs/afs/server.c b/fs/afs/server.c index 9fdc7fe3a7bc..d59b7516e943 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c | |||
@@ -238,8 +238,8 @@ void afs_put_server(struct afs_server *server) | |||
238 | if (atomic_read(&server->usage) == 0) { | 238 | if (atomic_read(&server->usage) == 0) { |
239 | list_move_tail(&server->grave, &afs_server_graveyard); | 239 | list_move_tail(&server->grave, &afs_server_graveyard); |
240 | server->time_of_death = get_seconds(); | 240 | server->time_of_death = get_seconds(); |
241 | schedule_delayed_work(&afs_server_reaper, | 241 | queue_delayed_work(afs_wq, &afs_server_reaper, |
242 | afs_server_timeout * HZ); | 242 | afs_server_timeout * HZ); |
243 | } | 243 | } |
244 | spin_unlock(&afs_server_graveyard_lock); | 244 | spin_unlock(&afs_server_graveyard_lock); |
245 | _leave(" [dead]"); | 245 | _leave(" [dead]"); |
@@ -285,10 +285,11 @@ static void afs_reap_server(struct work_struct *work) | |||
285 | expiry = server->time_of_death + afs_server_timeout; | 285 | expiry = server->time_of_death + afs_server_timeout; |
286 | if (expiry > now) { | 286 | if (expiry > now) { |
287 | delay = (expiry - now) * HZ; | 287 | delay = (expiry - now) * HZ; |
288 | if (!schedule_delayed_work(&afs_server_reaper, delay)) { | 288 | if (!queue_delayed_work(afs_wq, &afs_server_reaper, |
289 | delay)) { | ||
289 | cancel_delayed_work(&afs_server_reaper); | 290 | cancel_delayed_work(&afs_server_reaper); |
290 | schedule_delayed_work(&afs_server_reaper, | 291 | queue_delayed_work(afs_wq, &afs_server_reaper, |
291 | delay); | 292 | delay); |
292 | } | 293 | } |
293 | break; | 294 | break; |
294 | } | 295 | } |
@@ -323,5 +324,5 @@ void __exit afs_purge_servers(void) | |||
323 | { | 324 | { |
324 | afs_server_timeout = 0; | 325 | afs_server_timeout = 0; |
325 | cancel_delayed_work(&afs_server_reaper); | 326 | cancel_delayed_work(&afs_server_reaper); |
326 | schedule_delayed_work(&afs_server_reaper, 0); | 327 | queue_delayed_work(afs_wq, &afs_server_reaper, 0); |
327 | } | 328 | } |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 77e1e5a61154..356dcf0929e8 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -19,7 +19,6 @@ | |||
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/smp_lock.h> | ||
23 | #include <linux/fs.h> | 22 | #include <linux/fs.h> |
24 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
25 | #include <linux/parser.h> | 24 | #include <linux/parser.h> |
@@ -30,19 +29,18 @@ | |||
30 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ | 29 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ |
31 | 30 | ||
32 | static void afs_i_init_once(void *foo); | 31 | static void afs_i_init_once(void *foo); |
33 | static int afs_get_sb(struct file_system_type *fs_type, | 32 | static struct dentry *afs_mount(struct file_system_type *fs_type, |
34 | int flags, const char *dev_name, | 33 | int flags, const char *dev_name, void *data); |
35 | void *data, struct vfsmount *mnt); | 34 | static void afs_kill_super(struct super_block *sb); |
36 | static struct inode *afs_alloc_inode(struct super_block *sb); | 35 | static struct inode *afs_alloc_inode(struct super_block *sb); |
37 | static void afs_put_super(struct super_block *sb); | ||
38 | static void afs_destroy_inode(struct inode *inode); | 36 | static void afs_destroy_inode(struct inode *inode); |
39 | static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); | 37 | static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); |
40 | 38 | ||
41 | struct file_system_type afs_fs_type = { | 39 | struct file_system_type afs_fs_type = { |
42 | .owner = THIS_MODULE, | 40 | .owner = THIS_MODULE, |
43 | .name = "afs", | 41 | .name = "afs", |
44 | .get_sb = afs_get_sb, | 42 | .mount = afs_mount, |
45 | .kill_sb = kill_anon_super, | 43 | .kill_sb = afs_kill_super, |
46 | .fs_flags = 0, | 44 | .fs_flags = 0, |
47 | }; | 45 | }; |
48 | 46 | ||
@@ -52,7 +50,6 @@ static const struct super_operations afs_super_ops = { | |||
52 | .drop_inode = afs_drop_inode, | 50 | .drop_inode = afs_drop_inode, |
53 | .destroy_inode = afs_destroy_inode, | 51 | .destroy_inode = afs_destroy_inode, |
54 | .evict_inode = afs_evict_inode, | 52 | .evict_inode = afs_evict_inode, |
55 | .put_super = afs_put_super, | ||
56 | .show_options = generic_show_options, | 53 | .show_options = generic_show_options, |
57 | }; | 54 | }; |
58 | 55 | ||
@@ -284,19 +281,25 @@ static int afs_parse_device_name(struct afs_mount_params *params, | |||
284 | */ | 281 | */ |
285 | static int afs_test_super(struct super_block *sb, void *data) | 282 | static int afs_test_super(struct super_block *sb, void *data) |
286 | { | 283 | { |
287 | struct afs_mount_params *params = data; | 284 | struct afs_super_info *as1 = data; |
288 | struct afs_super_info *as = sb->s_fs_info; | 285 | struct afs_super_info *as = sb->s_fs_info; |
289 | 286 | ||
290 | return as->volume == params->volume; | 287 | return as->volume == as1->volume; |
288 | } | ||
289 | |||
290 | static int afs_set_super(struct super_block *sb, void *data) | ||
291 | { | ||
292 | sb->s_fs_info = data; | ||
293 | return set_anon_super(sb, NULL); | ||
291 | } | 294 | } |
292 | 295 | ||
293 | /* | 296 | /* |
294 | * fill in the superblock | 297 | * fill in the superblock |
295 | */ | 298 | */ |
296 | static int afs_fill_super(struct super_block *sb, void *data) | 299 | static int afs_fill_super(struct super_block *sb, |
300 | struct afs_mount_params *params) | ||
297 | { | 301 | { |
298 | struct afs_mount_params *params = data; | 302 | struct afs_super_info *as = sb->s_fs_info; |
299 | struct afs_super_info *as = NULL; | ||
300 | struct afs_fid fid; | 303 | struct afs_fid fid; |
301 | struct dentry *root = NULL; | 304 | struct dentry *root = NULL; |
302 | struct inode *inode = NULL; | 305 | struct inode *inode = NULL; |
@@ -304,23 +307,13 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
304 | 307 | ||
305 | _enter(""); | 308 | _enter(""); |
306 | 309 | ||
307 | /* allocate a superblock info record */ | ||
308 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); | ||
309 | if (!as) { | ||
310 | _leave(" = -ENOMEM"); | ||
311 | return -ENOMEM; | ||
312 | } | ||
313 | |||
314 | afs_get_volume(params->volume); | ||
315 | as->volume = params->volume; | ||
316 | |||
317 | /* fill in the superblock */ | 310 | /* fill in the superblock */ |
318 | sb->s_blocksize = PAGE_CACHE_SIZE; | 311 | sb->s_blocksize = PAGE_CACHE_SIZE; |
319 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 312 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
320 | sb->s_magic = AFS_FS_MAGIC; | 313 | sb->s_magic = AFS_FS_MAGIC; |
321 | sb->s_op = &afs_super_ops; | 314 | sb->s_op = &afs_super_ops; |
322 | sb->s_fs_info = as; | ||
323 | sb->s_bdi = &as->volume->bdi; | 315 | sb->s_bdi = &as->volume->bdi; |
316 | strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id)); | ||
324 | 317 | ||
325 | /* allocate the root inode and dentry */ | 318 | /* allocate the root inode and dentry */ |
326 | fid.vid = as->volume->vid; | 319 | fid.vid = as->volume->vid; |
@@ -328,7 +321,7 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
328 | fid.unique = 1; | 321 | fid.unique = 1; |
329 | inode = afs_iget(sb, params->key, &fid, NULL, NULL); | 322 | inode = afs_iget(sb, params->key, &fid, NULL, NULL); |
330 | if (IS_ERR(inode)) | 323 | if (IS_ERR(inode)) |
331 | goto error_inode; | 324 | return PTR_ERR(inode); |
332 | 325 | ||
333 | if (params->autocell) | 326 | if (params->autocell) |
334 | set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); | 327 | set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); |
@@ -338,21 +331,14 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
338 | if (!root) | 331 | if (!root) |
339 | goto error; | 332 | goto error; |
340 | 333 | ||
334 | sb->s_d_op = &afs_fs_dentry_operations; | ||
341 | sb->s_root = root; | 335 | sb->s_root = root; |
342 | 336 | ||
343 | _leave(" = 0"); | 337 | _leave(" = 0"); |
344 | return 0; | 338 | return 0; |
345 | 339 | ||
346 | error_inode: | ||
347 | ret = PTR_ERR(inode); | ||
348 | inode = NULL; | ||
349 | error: | 340 | error: |
350 | iput(inode); | 341 | iput(inode); |
351 | afs_put_volume(as->volume); | ||
352 | kfree(as); | ||
353 | |||
354 | sb->s_fs_info = NULL; | ||
355 | |||
356 | _leave(" = %d", ret); | 342 | _leave(" = %d", ret); |
357 | return ret; | 343 | return ret; |
358 | } | 344 | } |
@@ -360,17 +346,15 @@ error: | |||
360 | /* | 346 | /* |
361 | * get an AFS superblock | 347 | * get an AFS superblock |
362 | */ | 348 | */ |
363 | static int afs_get_sb(struct file_system_type *fs_type, | 349 | static struct dentry *afs_mount(struct file_system_type *fs_type, |
364 | int flags, | 350 | int flags, const char *dev_name, void *options) |
365 | const char *dev_name, | ||
366 | void *options, | ||
367 | struct vfsmount *mnt) | ||
368 | { | 351 | { |
369 | struct afs_mount_params params; | 352 | struct afs_mount_params params; |
370 | struct super_block *sb; | 353 | struct super_block *sb; |
371 | struct afs_volume *vol; | 354 | struct afs_volume *vol; |
372 | struct key *key; | 355 | struct key *key; |
373 | char *new_opts = kstrdup(options, GFP_KERNEL); | 356 | char *new_opts = kstrdup(options, GFP_KERNEL); |
357 | struct afs_super_info *as; | ||
374 | int ret; | 358 | int ret; |
375 | 359 | ||
376 | _enter(",,%s,%p", dev_name, options); | 360 | _enter(",,%s,%p", dev_name, options); |
@@ -403,12 +387,22 @@ static int afs_get_sb(struct file_system_type *fs_type, | |||
403 | ret = PTR_ERR(vol); | 387 | ret = PTR_ERR(vol); |
404 | goto error; | 388 | goto error; |
405 | } | 389 | } |
406 | params.volume = vol; | 390 | |
391 | /* allocate a superblock info record */ | ||
392 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); | ||
393 | if (!as) { | ||
394 | ret = -ENOMEM; | ||
395 | afs_put_volume(vol); | ||
396 | goto error; | ||
397 | } | ||
398 | as->volume = vol; | ||
407 | 399 | ||
408 | /* allocate a deviceless superblock */ | 400 | /* allocate a deviceless superblock */ |
409 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); | 401 | sb = sget(fs_type, afs_test_super, afs_set_super, as); |
410 | if (IS_ERR(sb)) { | 402 | if (IS_ERR(sb)) { |
411 | ret = PTR_ERR(sb); | 403 | ret = PTR_ERR(sb); |
404 | afs_put_volume(vol); | ||
405 | kfree(as); | ||
412 | goto error; | 406 | goto error; |
413 | } | 407 | } |
414 | 408 | ||
@@ -426,40 +420,29 @@ static int afs_get_sb(struct file_system_type *fs_type, | |||
426 | } else { | 420 | } else { |
427 | _debug("reuse"); | 421 | _debug("reuse"); |
428 | ASSERTCMP(sb->s_flags, &, MS_ACTIVE); | 422 | ASSERTCMP(sb->s_flags, &, MS_ACTIVE); |
423 | afs_put_volume(vol); | ||
424 | kfree(as); | ||
429 | } | 425 | } |
430 | 426 | ||
431 | simple_set_mnt(mnt, sb); | ||
432 | afs_put_volume(params.volume); | ||
433 | afs_put_cell(params.cell); | 427 | afs_put_cell(params.cell); |
434 | kfree(new_opts); | 428 | kfree(new_opts); |
435 | _leave(" = 0 [%p]", sb); | 429 | _leave(" = 0 [%p]", sb); |
436 | return 0; | 430 | return dget(sb->s_root); |
437 | 431 | ||
438 | error: | 432 | error: |
439 | afs_put_volume(params.volume); | ||
440 | afs_put_cell(params.cell); | 433 | afs_put_cell(params.cell); |
441 | key_put(params.key); | 434 | key_put(params.key); |
442 | kfree(new_opts); | 435 | kfree(new_opts); |
443 | _leave(" = %d", ret); | 436 | _leave(" = %d", ret); |
444 | return ret; | 437 | return ERR_PTR(ret); |
445 | } | 438 | } |
446 | 439 | ||
447 | /* | 440 | static void afs_kill_super(struct super_block *sb) |
448 | * finish the unmounting process on the superblock | ||
449 | */ | ||
450 | static void afs_put_super(struct super_block *sb) | ||
451 | { | 441 | { |
452 | struct afs_super_info *as = sb->s_fs_info; | 442 | struct afs_super_info *as = sb->s_fs_info; |
453 | 443 | kill_anon_super(sb); | |
454 | _enter(""); | ||
455 | |||
456 | lock_kernel(); | ||
457 | |||
458 | afs_put_volume(as->volume); | 444 | afs_put_volume(as->volume); |
459 | 445 | kfree(as); | |
460 | unlock_kernel(); | ||
461 | |||
462 | _leave(""); | ||
463 | } | 446 | } |
464 | 447 | ||
465 | /* | 448 | /* |
@@ -508,6 +491,14 @@ static struct inode *afs_alloc_inode(struct super_block *sb) | |||
508 | return &vnode->vfs_inode; | 491 | return &vnode->vfs_inode; |
509 | } | 492 | } |
510 | 493 | ||
494 | static void afs_i_callback(struct rcu_head *head) | ||
495 | { | ||
496 | struct inode *inode = container_of(head, struct inode, i_rcu); | ||
497 | struct afs_vnode *vnode = AFS_FS_I(inode); | ||
498 | INIT_LIST_HEAD(&inode->i_dentry); | ||
499 | kmem_cache_free(afs_inode_cachep, vnode); | ||
500 | } | ||
501 | |||
511 | /* | 502 | /* |
512 | * destroy an AFS inode struct | 503 | * destroy an AFS inode struct |
513 | */ | 504 | */ |
@@ -521,7 +512,7 @@ static void afs_destroy_inode(struct inode *inode) | |||
521 | 512 | ||
522 | ASSERTCMP(vnode->server, ==, NULL); | 513 | ASSERTCMP(vnode->server, ==, NULL); |
523 | 514 | ||
524 | kmem_cache_free(afs_inode_cachep, vnode); | 515 | call_rcu(&inode->i_rcu, afs_i_callback); |
525 | atomic_dec(&afs_count_active_inodes); | 516 | atomic_dec(&afs_count_active_inodes); |
526 | } | 517 | } |
527 | 518 | ||
diff --git a/fs/afs/vlocation.c b/fs/afs/vlocation.c index 9ac260d1361d..431984d2e372 100644 --- a/fs/afs/vlocation.c +++ b/fs/afs/vlocation.c | |||
@@ -507,8 +507,8 @@ void afs_put_vlocation(struct afs_vlocation *vl) | |||
507 | _debug("buried"); | 507 | _debug("buried"); |
508 | list_move_tail(&vl->grave, &afs_vlocation_graveyard); | 508 | list_move_tail(&vl->grave, &afs_vlocation_graveyard); |
509 | vl->time_of_death = get_seconds(); | 509 | vl->time_of_death = get_seconds(); |
510 | schedule_delayed_work(&afs_vlocation_reap, | 510 | queue_delayed_work(afs_wq, &afs_vlocation_reap, |
511 | afs_vlocation_timeout * HZ); | 511 | afs_vlocation_timeout * HZ); |
512 | 512 | ||
513 | /* suspend updates on this record */ | 513 | /* suspend updates on this record */ |
514 | if (!list_empty(&vl->update)) { | 514 | if (!list_empty(&vl->update)) { |
@@ -561,11 +561,11 @@ static void afs_vlocation_reaper(struct work_struct *work) | |||
561 | if (expiry > now) { | 561 | if (expiry > now) { |
562 | delay = (expiry - now) * HZ; | 562 | delay = (expiry - now) * HZ; |
563 | _debug("delay %lu", delay); | 563 | _debug("delay %lu", delay); |
564 | if (!schedule_delayed_work(&afs_vlocation_reap, | 564 | if (!queue_delayed_work(afs_wq, &afs_vlocation_reap, |
565 | delay)) { | 565 | delay)) { |
566 | cancel_delayed_work(&afs_vlocation_reap); | 566 | cancel_delayed_work(&afs_vlocation_reap); |
567 | schedule_delayed_work(&afs_vlocation_reap, | 567 | queue_delayed_work(afs_wq, &afs_vlocation_reap, |
568 | delay); | 568 | delay); |
569 | } | 569 | } |
570 | break; | 570 | break; |
571 | } | 571 | } |
@@ -620,7 +620,7 @@ void afs_vlocation_purge(void) | |||
620 | destroy_workqueue(afs_vlocation_update_worker); | 620 | destroy_workqueue(afs_vlocation_update_worker); |
621 | 621 | ||
622 | cancel_delayed_work(&afs_vlocation_reap); | 622 | cancel_delayed_work(&afs_vlocation_reap); |
623 | schedule_delayed_work(&afs_vlocation_reap, 0); | 623 | queue_delayed_work(afs_wq, &afs_vlocation_reap, 0); |
624 | } | 624 | } |
625 | 625 | ||
626 | /* | 626 | /* |
diff --git a/fs/afs/write.c b/fs/afs/write.c index 722743b152d8..b806285ff853 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
@@ -84,23 +84,21 @@ void afs_put_writeback(struct afs_writeback *wb) | |||
84 | * partly or wholly fill a page that's under preparation for writing | 84 | * partly or wholly fill a page that's under preparation for writing |
85 | */ | 85 | */ |
86 | static int afs_fill_page(struct afs_vnode *vnode, struct key *key, | 86 | static int afs_fill_page(struct afs_vnode *vnode, struct key *key, |
87 | loff_t pos, unsigned len, struct page *page) | 87 | loff_t pos, struct page *page) |
88 | { | 88 | { |
89 | loff_t i_size; | 89 | loff_t i_size; |
90 | unsigned eof; | ||
91 | int ret; | 90 | int ret; |
91 | int len; | ||
92 | 92 | ||
93 | _enter(",,%llu,%u", (unsigned long long)pos, len); | 93 | _enter(",,%llu", (unsigned long long)pos); |
94 | |||
95 | ASSERTCMP(len, <=, PAGE_CACHE_SIZE); | ||
96 | 94 | ||
97 | i_size = i_size_read(&vnode->vfs_inode); | 95 | i_size = i_size_read(&vnode->vfs_inode); |
98 | if (pos + len > i_size) | 96 | if (pos + PAGE_CACHE_SIZE > i_size) |
99 | eof = i_size; | 97 | len = i_size - pos; |
100 | else | 98 | else |
101 | eof = PAGE_CACHE_SIZE; | 99 | len = PAGE_CACHE_SIZE; |
102 | 100 | ||
103 | ret = afs_vnode_fetch_data(vnode, key, 0, eof, page); | 101 | ret = afs_vnode_fetch_data(vnode, key, pos, len, page); |
104 | if (ret < 0) { | 102 | if (ret < 0) { |
105 | if (ret == -ENOENT) { | 103 | if (ret == -ENOENT) { |
106 | _debug("got NOENT from server" | 104 | _debug("got NOENT from server" |
@@ -140,6 +138,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping, | |||
140 | candidate->first = candidate->last = index; | 138 | candidate->first = candidate->last = index; |
141 | candidate->offset_first = from; | 139 | candidate->offset_first = from; |
142 | candidate->to_last = to; | 140 | candidate->to_last = to; |
141 | INIT_LIST_HEAD(&candidate->link); | ||
143 | candidate->usage = 1; | 142 | candidate->usage = 1; |
144 | candidate->state = AFS_WBACK_PENDING; | 143 | candidate->state = AFS_WBACK_PENDING; |
145 | init_waitqueue_head(&candidate->waitq); | 144 | init_waitqueue_head(&candidate->waitq); |
@@ -152,9 +151,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, | |||
152 | *pagep = page; | 151 | *pagep = page; |
153 | /* page won't leak in error case: it eventually gets cleaned off LRU */ | 152 | /* page won't leak in error case: it eventually gets cleaned off LRU */ |
154 | 153 | ||
155 | if (!PageUptodate(page)) { | 154 | if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) { |
156 | _debug("not up to date"); | 155 | ret = afs_fill_page(vnode, key, index << PAGE_CACHE_SHIFT, page); |
157 | ret = afs_fill_page(vnode, key, pos, len, page); | ||
158 | if (ret < 0) { | 156 | if (ret < 0) { |
159 | kfree(candidate); | 157 | kfree(candidate); |
160 | _leave(" = %d [prep]", ret); | 158 | _leave(" = %d [prep]", ret); |
@@ -438,7 +436,6 @@ no_more: | |||
438 | */ | 436 | */ |
439 | int afs_writepage(struct page *page, struct writeback_control *wbc) | 437 | int afs_writepage(struct page *page, struct writeback_control *wbc) |
440 | { | 438 | { |
441 | struct backing_dev_info *bdi = page->mapping->backing_dev_info; | ||
442 | struct afs_writeback *wb; | 439 | struct afs_writeback *wb; |
443 | int ret; | 440 | int ret; |
444 | 441 | ||
@@ -455,8 +452,6 @@ int afs_writepage(struct page *page, struct writeback_control *wbc) | |||
455 | } | 452 | } |
456 | 453 | ||
457 | wbc->nr_to_write -= ret; | 454 | wbc->nr_to_write -= ret; |
458 | if (wbc->nonblocking && bdi_write_congested(bdi)) | ||
459 | wbc->encountered_congestion = 1; | ||
460 | 455 | ||
461 | _leave(" = 0"); | 456 | _leave(" = 0"); |
462 | return 0; | 457 | return 0; |
@@ -469,7 +464,6 @@ static int afs_writepages_region(struct address_space *mapping, | |||
469 | struct writeback_control *wbc, | 464 | struct writeback_control *wbc, |
470 | pgoff_t index, pgoff_t end, pgoff_t *_next) | 465 | pgoff_t index, pgoff_t end, pgoff_t *_next) |
471 | { | 466 | { |
472 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
473 | struct afs_writeback *wb; | 467 | struct afs_writeback *wb; |
474 | struct page *page; | 468 | struct page *page; |
475 | int ret, n; | 469 | int ret, n; |
@@ -529,11 +523,6 @@ static int afs_writepages_region(struct address_space *mapping, | |||
529 | 523 | ||
530 | wbc->nr_to_write -= ret; | 524 | wbc->nr_to_write -= ret; |
531 | 525 | ||
532 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
533 | wbc->encountered_congestion = 1; | ||
534 | break; | ||
535 | } | ||
536 | |||
537 | cond_resched(); | 526 | cond_resched(); |
538 | } while (index < end && wbc->nr_to_write > 0); | 527 | } while (index < end && wbc->nr_to_write > 0); |
539 | 528 | ||
@@ -548,24 +537,16 @@ static int afs_writepages_region(struct address_space *mapping, | |||
548 | int afs_writepages(struct address_space *mapping, | 537 | int afs_writepages(struct address_space *mapping, |
549 | struct writeback_control *wbc) | 538 | struct writeback_control *wbc) |
550 | { | 539 | { |
551 | struct backing_dev_info *bdi = mapping->backing_dev_info; | ||
552 | pgoff_t start, end, next; | 540 | pgoff_t start, end, next; |
553 | int ret; | 541 | int ret; |
554 | 542 | ||
555 | _enter(""); | 543 | _enter(""); |
556 | 544 | ||
557 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | ||
558 | wbc->encountered_congestion = 1; | ||
559 | _leave(" = 0 [congest]"); | ||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | if (wbc->range_cyclic) { | 545 | if (wbc->range_cyclic) { |
564 | start = mapping->writeback_index; | 546 | start = mapping->writeback_index; |
565 | end = -1; | 547 | end = -1; |
566 | ret = afs_writepages_region(mapping, wbc, start, end, &next); | 548 | ret = afs_writepages_region(mapping, wbc, start, end, &next); |
567 | if (start > 0 && wbc->nr_to_write > 0 && ret == 0 && | 549 | if (start > 0 && wbc->nr_to_write > 0 && ret == 0) |
568 | !(wbc->nonblocking && wbc->encountered_congestion)) | ||
569 | ret = afs_writepages_region(mapping, wbc, 0, start, | 550 | ret = afs_writepages_region(mapping, wbc, 0, start, |
570 | &next); | 551 | &next); |
571 | mapping->writeback_index = next; | 552 | mapping->writeback_index = next; |