diff options
author | David Howells <dhowells@redhat.com> | 2007-04-26 18:59:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2007-04-26 18:59:35 -0400 |
commit | 260a980317dac80182dd76140cf67c6e81d6d3dd (patch) | |
tree | 84f3e919fd33be56aad4fc57f5cb844df1a6b952 /fs/afs/callback.c | |
parent | c35eccb1f614954b10cba3f74b7c301993b2f42e (diff) |
[AFS]: Add "directory write" support.
Add support for the create, link, symlink, unlink, mkdir, rmdir and
rename VFS operations to the in-kernel AFS filesystem.
Also:
(1) Fix dentry and inode revalidation. d_revalidate should only look at
state of the dentry. Revalidation of the contents of an inode pointed to
by a dentry is now separate.
(2) Fix afs_lookup() to hash negative dentries as well as positive ones.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'fs/afs/callback.c')
-rw-r--r-- | fs/afs/callback.c | 36 |
1 files changed, 32 insertions, 4 deletions
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index e674bebbb8b1..639399f0ab6f 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
@@ -44,7 +44,8 @@ void afs_init_callback_state(struct afs_server *server) | |||
44 | while (!RB_EMPTY_ROOT(&server->cb_promises)) { | 44 | while (!RB_EMPTY_ROOT(&server->cb_promises)) { |
45 | vnode = rb_entry(server->cb_promises.rb_node, | 45 | vnode = rb_entry(server->cb_promises.rb_node, |
46 | struct afs_vnode, cb_promise); | 46 | struct afs_vnode, cb_promise); |
47 | printk("\nUNPROMISE on %p\n", vnode); | 47 | _debug("UNPROMISE { vid=%x vn=%u uq=%u}", |
48 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique); | ||
48 | rb_erase(&vnode->cb_promise, &server->cb_promises); | 49 | rb_erase(&vnode->cb_promise, &server->cb_promises); |
49 | vnode->cb_promised = false; | 50 | vnode->cb_promised = false; |
50 | } | 51 | } |
@@ -68,7 +69,7 @@ void afs_broken_callback_work(struct work_struct *work) | |||
68 | 69 | ||
69 | /* we're only interested in dealing with a broken callback on *this* | 70 | /* we're only interested in dealing with a broken callback on *this* |
70 | * vnode and only if no-one else has dealt with it yet */ | 71 | * vnode and only if no-one else has dealt with it yet */ |
71 | if (!mutex_trylock(&vnode->cb_broken_lock)) | 72 | if (!mutex_trylock(&vnode->validate_lock)) |
72 | return; /* someone else is dealing with it */ | 73 | return; /* someone else is dealing with it */ |
73 | 74 | ||
74 | if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { | 75 | if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { |
@@ -84,13 +85,14 @@ void afs_broken_callback_work(struct work_struct *work) | |||
84 | /* if the vnode's data version number changed then its contents | 85 | /* if the vnode's data version number changed then its contents |
85 | * are different */ | 86 | * are different */ |
86 | if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { | 87 | if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { |
87 | _debug("zap data"); | 88 | _debug("zap data {%x:%u}", |
89 | vnode->fid.vid, vnode->fid.vnode); | ||
88 | invalidate_remote_inode(&vnode->vfs_inode); | 90 | invalidate_remote_inode(&vnode->vfs_inode); |
89 | } | 91 | } |
90 | } | 92 | } |
91 | 93 | ||
92 | out: | 94 | out: |
93 | mutex_unlock(&vnode->cb_broken_lock); | 95 | mutex_unlock(&vnode->validate_lock); |
94 | 96 | ||
95 | /* avoid the potential race whereby the mutex_trylock() in this | 97 | /* avoid the potential race whereby the mutex_trylock() in this |
96 | * function happens again between the clear_bit() and the | 98 | * function happens again between the clear_bit() and the |
@@ -252,6 +254,32 @@ static void afs_do_give_up_callback(struct afs_server *server, | |||
252 | } | 254 | } |
253 | 255 | ||
254 | /* | 256 | /* |
257 | * discard the callback on a deleted item | ||
258 | */ | ||
259 | void afs_discard_callback_on_delete(struct afs_vnode *vnode) | ||
260 | { | ||
261 | struct afs_server *server = vnode->server; | ||
262 | |||
263 | _enter("%d", vnode->cb_promised); | ||
264 | |||
265 | if (!vnode->cb_promised) { | ||
266 | _leave(" [not promised]"); | ||
267 | return; | ||
268 | } | ||
269 | |||
270 | ASSERT(server != NULL); | ||
271 | |||
272 | spin_lock(&server->cb_lock); | ||
273 | if (vnode->cb_promised) { | ||
274 | ASSERT(server->cb_promises.rb_node != NULL); | ||
275 | rb_erase(&vnode->cb_promise, &server->cb_promises); | ||
276 | vnode->cb_promised = false; | ||
277 | } | ||
278 | spin_unlock(&server->cb_lock); | ||
279 | _leave(""); | ||
280 | } | ||
281 | |||
282 | /* | ||
255 | * give up the callback registered for a vnode on the file server when the | 283 | * give up the callback registered for a vnode on the file server when the |
256 | * inode is being cleared | 284 | * inode is being cleared |
257 | */ | 285 | */ |