1 /* AFS vnode management
3 * Copyright (C) 2002, 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
20 static noinline bool dump_tree_aux(struct rb_node *node, struct rb_node *parent,
23 struct afs_vnode *vnode;
30 bad = dump_tree_aux(node->rb_left, node, depth + 2, '/');
32 vnode = rb_entry(node, struct afs_vnode, cb_promise);
33 _debug("%c %*.*s%c%p {%d}",
34 rb_is_red(node) ? 'R' : 'B',
36 vnode, vnode->cb_expires_at);
37 if (rb_parent(node) != parent) {
38 printk("BAD: %p != %p\n", rb_parent(node), parent);
43 bad |= dump_tree_aux(node->rb_right, node, depth + 2, '\\');
48 static noinline void dump_tree(const char *name, struct afs_server *server)
51 if (dump_tree_aux(server->cb_promises.rb_node, NULL, 0, '-'))
57 * insert a vnode into the backing server's vnode tree
59 static void afs_install_vnode(struct afs_vnode *vnode,
60 struct afs_server *server)
62 struct afs_server *old_server = vnode->server;
63 struct afs_vnode *xvnode;
64 struct rb_node *parent, **p;
66 _enter("%p,%p", vnode, server);
69 spin_lock(&old_server->fs_lock);
70 rb_erase(&vnode->server_rb, &old_server->fs_vnodes);
71 spin_unlock(&old_server->fs_lock);
74 afs_get_server(server);
75 vnode->server = server;
76 afs_put_server(old_server);
78 /* insert into the server's vnode tree in FID order */
79 spin_lock(&server->fs_lock);
82 p = &server->fs_vnodes.rb_node;
85 xvnode = rb_entry(parent, struct afs_vnode, server_rb);
86 if (vnode->fid.vid < xvnode->fid.vid)
88 else if (vnode->fid.vid > xvnode->fid.vid)
90 else if (vnode->fid.vnode < xvnode->fid.vnode)
92 else if (vnode->fid.vnode > xvnode->fid.vnode)
94 else if (vnode->fid.unique < xvnode->fid.unique)
96 else if (vnode->fid.unique > xvnode->fid.unique)
99 BUG(); /* can't happen unless afs_iget() malfunctions */
102 rb_link_node(&vnode->server_rb, parent, p);
103 rb_insert_color(&vnode->server_rb, &server->fs_vnodes);
105 spin_unlock(&server->fs_lock);
110 * insert a vnode into the promising server's update/expiration tree
111 * - caller must hold vnode->lock
113 static void afs_vnode_note_promise(struct afs_vnode *vnode,
114 struct afs_server *server)
116 struct afs_server *old_server;
117 struct afs_vnode *xvnode;
118 struct rb_node *parent, **p;
120 _enter("%p,%p", vnode, server);
122 ASSERT(server != NULL);
124 old_server = vnode->server;
125 if (vnode->cb_promised) {
126 if (server == old_server &&
127 vnode->cb_expires == vnode->cb_expires_at) {
128 _leave(" [no change]");
132 spin_lock(&old_server->cb_lock);
133 if (vnode->cb_promised) {
135 rb_erase(&vnode->cb_promise, &old_server->cb_promises);
136 vnode->cb_promised = false;
138 spin_unlock(&old_server->cb_lock);
141 if (vnode->server != server)
142 afs_install_vnode(vnode, server);
144 vnode->cb_expires_at = vnode->cb_expires;
145 _debug("PROMISE on %p {%lu}",
146 vnode, (unsigned long) vnode->cb_expires_at);
148 /* abuse an RB-tree to hold the expiration order (we may have multiple
149 * items with the same expiration time) */
150 spin_lock(&server->cb_lock);
153 p = &server->cb_promises.rb_node;
156 xvnode = rb_entry(parent, struct afs_vnode, cb_promise);
157 if (vnode->cb_expires_at < xvnode->cb_expires_at)
163 rb_link_node(&vnode->cb_promise, parent, p);
164 rb_insert_color(&vnode->cb_promise, &server->cb_promises);
165 vnode->cb_promised = true;
167 spin_unlock(&server->cb_lock);
172 * handle remote file deletion by discarding the callback promise
174 static void afs_vnode_deleted_remotely(struct afs_vnode *vnode)
176 struct afs_server *server;
178 set_bit(AFS_VNODE_DELETED, &vnode->flags);
180 server = vnode->server;
181 if (vnode->cb_promised) {
182 spin_lock(&server->cb_lock);
183 if (vnode->cb_promised) {
184 rb_erase(&vnode->cb_promise, &server->cb_promises);
185 vnode->cb_promised = false;
187 spin_unlock(&server->cb_lock);
190 spin_lock(&vnode->server->fs_lock);
191 rb_erase(&vnode->server_rb, &vnode->server->fs_vnodes);
192 spin_unlock(&vnode->server->fs_lock);
194 vnode->server = NULL;
195 afs_put_server(server);
199 * finish off updating the recorded status of a file after a successful
200 * operation completion
201 * - starts callback expiry timer
202 * - adds to server's callback list
204 void afs_vnode_finalise_status_update(struct afs_vnode *vnode,
205 struct afs_server *server)
207 struct afs_server *oldserver = NULL;
209 _enter("%p,%p", vnode, server);
211 spin_lock(&vnode->lock);
212 clear_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
213 afs_vnode_note_promise(vnode, server);
215 ASSERTCMP(vnode->update_cnt, >=, 0);
216 spin_unlock(&vnode->lock);
218 wake_up_all(&vnode->update_waitq);
219 afs_put_server(oldserver);
224 * finish off updating the recorded status of a file after an operation failed
226 static void afs_vnode_status_update_failed(struct afs_vnode *vnode, int ret)
228 _enter("%p,%d", vnode, ret);
230 spin_lock(&vnode->lock);
232 clear_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
234 if (ret == -ENOENT) {
235 /* the file was deleted on the server */
236 _debug("got NOENT from server - marking file deleted");
237 afs_vnode_deleted_remotely(vnode);
241 ASSERTCMP(vnode->update_cnt, >=, 0);
242 spin_unlock(&vnode->lock);
244 wake_up_all(&vnode->update_waitq);
249 * fetch file status from the volume
250 * - don't issue a fetch if:
251 * - the changed bit is not set and there's a valid callback
252 * - there are any outstanding ops that will fetch the status
253 * - TODO implement local caching
255 int afs_vnode_fetch_status(struct afs_vnode *vnode,
256 struct afs_vnode *auth_vnode, struct key *key)
258 struct afs_server *server;
259 unsigned long acl_order;
262 DECLARE_WAITQUEUE(myself, current);
264 _enter("%s,{%x:%u.%u}",
265 vnode->volume->vlocation->vldb.name,
266 vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
268 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
269 vnode->cb_promised) {
270 _leave(" [unchanged]");
274 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
275 _leave(" [deleted]");
281 acl_order = auth_vnode->acl_order;
283 spin_lock(&vnode->lock);
285 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags) &&
286 vnode->cb_promised) {
287 spin_unlock(&vnode->lock);
288 _leave(" [unchanged]");
292 ASSERTCMP(vnode->update_cnt, >=, 0);
294 if (vnode->update_cnt > 0) {
295 /* someone else started a fetch */
296 _debug("wait on fetch %d", vnode->update_cnt);
298 set_current_state(TASK_UNINTERRUPTIBLE);
299 ASSERT(myself.func != NULL);
300 add_wait_queue(&vnode->update_waitq, &myself);
302 /* wait for the status to be updated */
304 if (!test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))
306 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
309 /* check to see if it got updated and invalidated all
310 * before we saw it */
311 if (vnode->update_cnt == 0) {
312 remove_wait_queue(&vnode->update_waitq,
314 set_current_state(TASK_RUNNING);
318 spin_unlock(&vnode->lock);
321 set_current_state(TASK_UNINTERRUPTIBLE);
323 spin_lock(&vnode->lock);
326 remove_wait_queue(&vnode->update_waitq, &myself);
327 spin_unlock(&vnode->lock);
328 set_current_state(TASK_RUNNING);
330 return test_bit(AFS_VNODE_DELETED, &vnode->flags) ?
335 /* okay... we're going to have to initiate the op */
338 spin_unlock(&vnode->lock);
340 /* merge AFS status fetches and clear outstanding callback on this
343 /* pick a server to query */
344 server = afs_volume_pick_fileserver(vnode);
348 _debug("USING SERVER: %p{%08x}",
349 server, ntohl(server->addr.s_addr));
351 ret = afs_fs_fetch_file_status(server, key, vnode, NULL,
354 } while (!afs_volume_release_fileserver(vnode, server, ret));
356 /* adjust the flags */
360 afs_cache_permit(vnode, key, acl_order);
361 afs_vnode_finalise_status_update(vnode, server);
362 afs_put_server(server);
364 _debug("failed [%d]", ret);
365 afs_vnode_status_update_failed(vnode, ret);
368 ASSERTCMP(vnode->update_cnt, >=, 0);
370 _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
374 spin_lock(&vnode->lock);
376 ASSERTCMP(vnode->update_cnt, >=, 0);
377 spin_unlock(&vnode->lock);
378 _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
379 return PTR_ERR(server);
383 * fetch file data from the volume
384 * - TODO implement caching
386 int afs_vnode_fetch_data(struct afs_vnode *vnode, struct key *key,
387 off_t offset, size_t length, struct page *page)
389 struct afs_server *server;
392 _enter("%s{%x:%u.%u},%x,,,",
393 vnode->volume->vlocation->vldb.name,
399 /* this op will fetch the status */
400 spin_lock(&vnode->lock);
402 spin_unlock(&vnode->lock);
404 /* merge in AFS status fetches and clear outstanding callback on this
407 /* pick a server to query */
408 server = afs_volume_pick_fileserver(vnode);
412 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
414 ret = afs_fs_fetch_data(server, key, vnode, offset, length,
415 page, &afs_sync_call);
417 } while (!afs_volume_release_fileserver(vnode, server, ret));
419 /* adjust the flags */
421 afs_vnode_finalise_status_update(vnode, server);
422 afs_put_server(server);
424 afs_vnode_status_update_failed(vnode, ret);
427 _leave(" = %d", ret);
431 spin_lock(&vnode->lock);
433 ASSERTCMP(vnode->update_cnt, >=, 0);
434 spin_unlock(&vnode->lock);
435 return PTR_ERR(server);
439 * make a file or a directory
441 int afs_vnode_create(struct afs_vnode *vnode, struct key *key,
442 const char *name, umode_t mode, struct afs_fid *newfid,
443 struct afs_file_status *newstatus,
444 struct afs_callback *newcb, struct afs_server **_server)
446 struct afs_server *server;
449 _enter("%s{%x:%u.%u},%x,%s,,",
450 vnode->volume->vlocation->vldb.name,
457 /* this op will fetch the status on the directory we're creating in */
458 spin_lock(&vnode->lock);
460 spin_unlock(&vnode->lock);
463 /* pick a server to query */
464 server = afs_volume_pick_fileserver(vnode);
468 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
470 ret = afs_fs_create(server, key, vnode, name, mode, newfid,
471 newstatus, newcb, &afs_sync_call);
473 } while (!afs_volume_release_fileserver(vnode, server, ret));
475 /* adjust the flags */
477 afs_vnode_finalise_status_update(vnode, server);
480 afs_vnode_status_update_failed(vnode, ret);
484 _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
488 spin_lock(&vnode->lock);
490 ASSERTCMP(vnode->update_cnt, >=, 0);
491 spin_unlock(&vnode->lock);
492 _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
493 return PTR_ERR(server);
497 * remove a file or directory
499 int afs_vnode_remove(struct afs_vnode *vnode, struct key *key, const char *name,
502 struct afs_server *server;
505 _enter("%s{%x:%u.%u},%x,%s",
506 vnode->volume->vlocation->vldb.name,
513 /* this op will fetch the status on the directory we're removing from */
514 spin_lock(&vnode->lock);
516 spin_unlock(&vnode->lock);
519 /* pick a server to query */
520 server = afs_volume_pick_fileserver(vnode);
524 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
526 ret = afs_fs_remove(server, key, vnode, name, isdir,
529 } while (!afs_volume_release_fileserver(vnode, server, ret));
531 /* adjust the flags */
533 afs_vnode_finalise_status_update(vnode, server);
534 afs_put_server(server);
536 afs_vnode_status_update_failed(vnode, ret);
539 _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
543 spin_lock(&vnode->lock);
545 ASSERTCMP(vnode->update_cnt, >=, 0);
546 spin_unlock(&vnode->lock);
547 _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
548 return PTR_ERR(server);
554 extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode,
555 struct key *key, const char *name)
557 struct afs_server *server;
560 _enter("%s{%x:%u.%u},%s{%x:%u.%u},%x,%s",
561 dvnode->volume->vlocation->vldb.name,
565 vnode->volume->vlocation->vldb.name,
572 /* this op will fetch the status on the directory we're removing from */
573 spin_lock(&vnode->lock);
575 spin_unlock(&vnode->lock);
576 spin_lock(&dvnode->lock);
577 dvnode->update_cnt++;
578 spin_unlock(&dvnode->lock);
581 /* pick a server to query */
582 server = afs_volume_pick_fileserver(dvnode);
586 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
588 ret = afs_fs_link(server, key, dvnode, vnode, name,
591 } while (!afs_volume_release_fileserver(dvnode, server, ret));
593 /* adjust the flags */
595 afs_vnode_finalise_status_update(vnode, server);
596 afs_vnode_finalise_status_update(dvnode, server);
597 afs_put_server(server);
599 afs_vnode_status_update_failed(vnode, ret);
600 afs_vnode_status_update_failed(dvnode, ret);
603 _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
607 spin_lock(&vnode->lock);
609 ASSERTCMP(vnode->update_cnt, >=, 0);
610 spin_unlock(&vnode->lock);
611 spin_lock(&dvnode->lock);
612 dvnode->update_cnt--;
613 ASSERTCMP(dvnode->update_cnt, >=, 0);
614 spin_unlock(&dvnode->lock);
615 _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
616 return PTR_ERR(server);
620 * create a symbolic link
622 int afs_vnode_symlink(struct afs_vnode *vnode, struct key *key,
623 const char *name, const char *content,
624 struct afs_fid *newfid,
625 struct afs_file_status *newstatus,
626 struct afs_server **_server)
628 struct afs_server *server;
631 _enter("%s{%x:%u.%u},%x,%s,%s,,,",
632 vnode->volume->vlocation->vldb.name,
639 /* this op will fetch the status on the directory we're creating in */
640 spin_lock(&vnode->lock);
642 spin_unlock(&vnode->lock);
645 /* pick a server to query */
646 server = afs_volume_pick_fileserver(vnode);
650 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
652 ret = afs_fs_symlink(server, key, vnode, name, content,
653 newfid, newstatus, &afs_sync_call);
655 } while (!afs_volume_release_fileserver(vnode, server, ret));
657 /* adjust the flags */
659 afs_vnode_finalise_status_update(vnode, server);
662 afs_vnode_status_update_failed(vnode, ret);
666 _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
670 spin_lock(&vnode->lock);
672 ASSERTCMP(vnode->update_cnt, >=, 0);
673 spin_unlock(&vnode->lock);
674 _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
675 return PTR_ERR(server);
681 int afs_vnode_rename(struct afs_vnode *orig_dvnode,
682 struct afs_vnode *new_dvnode,
684 const char *orig_name,
685 const char *new_name)
687 struct afs_server *server;
690 _enter("%s{%x:%u.%u},%s{%u,%u,%u},%x,%s,%s",
691 orig_dvnode->volume->vlocation->vldb.name,
692 orig_dvnode->fid.vid,
693 orig_dvnode->fid.vnode,
694 orig_dvnode->fid.unique,
695 new_dvnode->volume->vlocation->vldb.name,
697 new_dvnode->fid.vnode,
698 new_dvnode->fid.unique,
703 /* this op will fetch the status on both the directories we're dealing
705 spin_lock(&orig_dvnode->lock);
706 orig_dvnode->update_cnt++;
707 spin_unlock(&orig_dvnode->lock);
708 if (new_dvnode != orig_dvnode) {
709 spin_lock(&new_dvnode->lock);
710 new_dvnode->update_cnt++;
711 spin_unlock(&new_dvnode->lock);
715 /* pick a server to query */
716 server = afs_volume_pick_fileserver(orig_dvnode);
720 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
722 ret = afs_fs_rename(server, key, orig_dvnode, orig_name,
723 new_dvnode, new_name, &afs_sync_call);
725 } while (!afs_volume_release_fileserver(orig_dvnode, server, ret));
727 /* adjust the flags */
729 afs_vnode_finalise_status_update(orig_dvnode, server);
730 if (new_dvnode != orig_dvnode)
731 afs_vnode_finalise_status_update(new_dvnode, server);
732 afs_put_server(server);
734 afs_vnode_status_update_failed(orig_dvnode, ret);
735 if (new_dvnode != orig_dvnode)
736 afs_vnode_status_update_failed(new_dvnode, ret);
739 _leave(" = %d [cnt %d]", ret, orig_dvnode->update_cnt);
743 spin_lock(&orig_dvnode->lock);
744 orig_dvnode->update_cnt--;
745 ASSERTCMP(orig_dvnode->update_cnt, >=, 0);
746 spin_unlock(&orig_dvnode->lock);
747 if (new_dvnode != orig_dvnode) {
748 spin_lock(&new_dvnode->lock);
749 new_dvnode->update_cnt--;
750 ASSERTCMP(new_dvnode->update_cnt, >=, 0);
751 spin_unlock(&new_dvnode->lock);
753 _leave(" = %ld [cnt %d]", PTR_ERR(server), orig_dvnode->update_cnt);
754 return PTR_ERR(server);
760 int afs_vnode_store_data(struct afs_writeback *wb, pgoff_t first, pgoff_t last,
761 unsigned offset, unsigned to)
763 struct afs_server *server;
764 struct afs_vnode *vnode = wb->vnode;
767 _enter("%s{%x:%u.%u},%x,%lx,%lx,%x,%x",
768 vnode->volume->vlocation->vldb.name,
773 first, last, offset, to);
775 /* this op will fetch the status */
776 spin_lock(&vnode->lock);
778 spin_unlock(&vnode->lock);
781 /* pick a server to query */
782 server = afs_volume_pick_fileserver(vnode);
786 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
788 ret = afs_fs_store_data(server, wb, first, last, offset, to,
791 } while (!afs_volume_release_fileserver(vnode, server, ret));
793 /* adjust the flags */
795 afs_vnode_finalise_status_update(vnode, server);
796 afs_put_server(server);
798 afs_vnode_status_update_failed(vnode, ret);
801 _leave(" = %d", ret);
805 spin_lock(&vnode->lock);
807 ASSERTCMP(vnode->update_cnt, >=, 0);
808 spin_unlock(&vnode->lock);
809 return PTR_ERR(server);
813 * set the attributes on a file
815 int afs_vnode_setattr(struct afs_vnode *vnode, struct key *key,
818 struct afs_server *server;
821 _enter("%s{%x:%u.%u},%x",
822 vnode->volume->vlocation->vldb.name,
828 /* this op will fetch the status */
829 spin_lock(&vnode->lock);
831 spin_unlock(&vnode->lock);
834 /* pick a server to query */
835 server = afs_volume_pick_fileserver(vnode);
839 _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
841 ret = afs_fs_setattr(server, key, vnode, attr, &afs_sync_call);
843 } while (!afs_volume_release_fileserver(vnode, server, ret));
845 /* adjust the flags */
847 afs_vnode_finalise_status_update(vnode, server);
848 afs_put_server(server);
850 afs_vnode_status_update_failed(vnode, ret);
853 _leave(" = %d", ret);
857 spin_lock(&vnode->lock);
859 ASSERTCMP(vnode->update_cnt, >=, 0);
860 spin_unlock(&vnode->lock);
861 return PTR_ERR(server);