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>
17 #include <linux/sched.h>
21 static noinline
bool dump_tree_aux(struct rb_node
*node
, struct rb_node
*parent
,
24 struct afs_vnode
*vnode
;
31 bad
= dump_tree_aux(node
->rb_left
, node
, depth
+ 2, '/');
33 vnode
= rb_entry(node
, struct afs_vnode
, cb_promise
);
34 _debug("%c %*.*s%c%p {%d}",
35 rb_is_red(node
) ? 'R' : 'B',
37 vnode
, vnode
->cb_expires_at
);
38 if (rb_parent(node
) != parent
) {
39 printk("BAD: %p != %p\n", rb_parent(node
), parent
);
44 bad
|= dump_tree_aux(node
->rb_right
, node
, depth
+ 2, '\\');
49 static noinline
void dump_tree(const char *name
, struct afs_server
*server
)
52 if (dump_tree_aux(server
->cb_promises
.rb_node
, NULL
, 0, '-'))
58 * insert a vnode into the backing server's vnode tree
60 static void afs_install_vnode(struct afs_vnode
*vnode
,
61 struct afs_server
*server
)
63 struct afs_server
*old_server
= vnode
->server
;
64 struct afs_vnode
*xvnode
;
65 struct rb_node
*parent
, **p
;
67 _enter("%p,%p", vnode
, server
);
70 spin_lock(&old_server
->fs_lock
);
71 rb_erase(&vnode
->server_rb
, &old_server
->fs_vnodes
);
72 spin_unlock(&old_server
->fs_lock
);
75 afs_get_server(server
);
76 vnode
->server
= server
;
77 afs_put_server(old_server
);
79 /* insert into the server's vnode tree in FID order */
80 spin_lock(&server
->fs_lock
);
83 p
= &server
->fs_vnodes
.rb_node
;
86 xvnode
= rb_entry(parent
, struct afs_vnode
, server_rb
);
87 if (vnode
->fid
.vid
< xvnode
->fid
.vid
)
89 else if (vnode
->fid
.vid
> xvnode
->fid
.vid
)
91 else if (vnode
->fid
.vnode
< xvnode
->fid
.vnode
)
93 else if (vnode
->fid
.vnode
> xvnode
->fid
.vnode
)
95 else if (vnode
->fid
.unique
< xvnode
->fid
.unique
)
97 else if (vnode
->fid
.unique
> xvnode
->fid
.unique
)
100 BUG(); /* can't happen unless afs_iget() malfunctions */
103 rb_link_node(&vnode
->server_rb
, parent
, p
);
104 rb_insert_color(&vnode
->server_rb
, &server
->fs_vnodes
);
106 spin_unlock(&server
->fs_lock
);
111 * insert a vnode into the promising server's update/expiration tree
112 * - caller must hold vnode->lock
114 static void afs_vnode_note_promise(struct afs_vnode
*vnode
,
115 struct afs_server
*server
)
117 struct afs_server
*old_server
;
118 struct afs_vnode
*xvnode
;
119 struct rb_node
*parent
, **p
;
121 _enter("%p,%p", vnode
, server
);
123 ASSERT(server
!= NULL
);
125 old_server
= vnode
->server
;
126 if (vnode
->cb_promised
) {
127 if (server
== old_server
&&
128 vnode
->cb_expires
== vnode
->cb_expires_at
) {
129 _leave(" [no change]");
133 spin_lock(&old_server
->cb_lock
);
134 if (vnode
->cb_promised
) {
136 rb_erase(&vnode
->cb_promise
, &old_server
->cb_promises
);
137 vnode
->cb_promised
= false;
139 spin_unlock(&old_server
->cb_lock
);
142 if (vnode
->server
!= server
)
143 afs_install_vnode(vnode
, server
);
145 vnode
->cb_expires_at
= vnode
->cb_expires
;
146 _debug("PROMISE on %p {%lu}",
147 vnode
, (unsigned long) vnode
->cb_expires_at
);
149 /* abuse an RB-tree to hold the expiration order (we may have multiple
150 * items with the same expiration time) */
151 spin_lock(&server
->cb_lock
);
154 p
= &server
->cb_promises
.rb_node
;
157 xvnode
= rb_entry(parent
, struct afs_vnode
, cb_promise
);
158 if (vnode
->cb_expires_at
< xvnode
->cb_expires_at
)
164 rb_link_node(&vnode
->cb_promise
, parent
, p
);
165 rb_insert_color(&vnode
->cb_promise
, &server
->cb_promises
);
166 vnode
->cb_promised
= true;
168 spin_unlock(&server
->cb_lock
);
173 * handle remote file deletion by discarding the callback promise
175 static void afs_vnode_deleted_remotely(struct afs_vnode
*vnode
)
177 struct afs_server
*server
;
179 _enter("{%p}", vnode
->server
);
181 set_bit(AFS_VNODE_DELETED
, &vnode
->flags
);
183 server
= vnode
->server
;
185 if (vnode
->cb_promised
) {
186 spin_lock(&server
->cb_lock
);
187 if (vnode
->cb_promised
) {
188 rb_erase(&vnode
->cb_promise
,
189 &server
->cb_promises
);
190 vnode
->cb_promised
= false;
192 spin_unlock(&server
->cb_lock
);
195 spin_lock(&server
->fs_lock
);
196 rb_erase(&vnode
->server_rb
, &server
->fs_vnodes
);
197 spin_unlock(&server
->fs_lock
);
199 vnode
->server
= NULL
;
200 afs_put_server(server
);
202 ASSERT(!vnode
->cb_promised
);
209 * finish off updating the recorded status of a file after a successful
210 * operation completion
211 * - starts callback expiry timer
212 * - adds to server's callback list
214 void afs_vnode_finalise_status_update(struct afs_vnode
*vnode
,
215 struct afs_server
*server
)
217 struct afs_server
*oldserver
= NULL
;
219 _enter("%p,%p", vnode
, server
);
221 spin_lock(&vnode
->lock
);
222 clear_bit(AFS_VNODE_CB_BROKEN
, &vnode
->flags
);
223 afs_vnode_note_promise(vnode
, server
);
225 ASSERTCMP(vnode
->update_cnt
, >=, 0);
226 spin_unlock(&vnode
->lock
);
228 wake_up_all(&vnode
->update_waitq
);
229 afs_put_server(oldserver
);
234 * finish off updating the recorded status of a file after an operation failed
236 static void afs_vnode_status_update_failed(struct afs_vnode
*vnode
, int ret
)
238 _enter("{%x:%u},%d", vnode
->fid
.vid
, vnode
->fid
.vnode
, ret
);
240 spin_lock(&vnode
->lock
);
242 clear_bit(AFS_VNODE_CB_BROKEN
, &vnode
->flags
);
244 if (ret
== -ENOENT
) {
245 /* the file was deleted on the server */
246 _debug("got NOENT from server - marking file deleted");
247 afs_vnode_deleted_remotely(vnode
);
251 ASSERTCMP(vnode
->update_cnt
, >=, 0);
252 spin_unlock(&vnode
->lock
);
254 wake_up_all(&vnode
->update_waitq
);
259 * fetch file status from the volume
260 * - don't issue a fetch if:
261 * - the changed bit is not set and there's a valid callback
262 * - there are any outstanding ops that will fetch the status
263 * - TODO implement local caching
265 int afs_vnode_fetch_status(struct afs_vnode
*vnode
,
266 struct afs_vnode
*auth_vnode
, struct key
*key
)
268 struct afs_server
*server
;
269 unsigned long acl_order
;
272 DECLARE_WAITQUEUE(myself
, current
);
274 _enter("%s,{%x:%u.%u}",
275 vnode
->volume
->vlocation
->vldb
.name
,
276 vnode
->fid
.vid
, vnode
->fid
.vnode
, vnode
->fid
.unique
);
278 if (!test_bit(AFS_VNODE_CB_BROKEN
, &vnode
->flags
) &&
279 vnode
->cb_promised
) {
280 _leave(" [unchanged]");
284 if (test_bit(AFS_VNODE_DELETED
, &vnode
->flags
)) {
285 _leave(" [deleted]");
291 acl_order
= auth_vnode
->acl_order
;
293 spin_lock(&vnode
->lock
);
295 if (!test_bit(AFS_VNODE_CB_BROKEN
, &vnode
->flags
) &&
296 vnode
->cb_promised
) {
297 spin_unlock(&vnode
->lock
);
298 _leave(" [unchanged]");
302 ASSERTCMP(vnode
->update_cnt
, >=, 0);
304 if (vnode
->update_cnt
> 0) {
305 /* someone else started a fetch */
306 _debug("wait on fetch %d", vnode
->update_cnt
);
308 set_current_state(TASK_UNINTERRUPTIBLE
);
309 ASSERT(myself
.func
!= NULL
);
310 add_wait_queue(&vnode
->update_waitq
, &myself
);
312 /* wait for the status to be updated */
314 if (!test_bit(AFS_VNODE_CB_BROKEN
, &vnode
->flags
))
316 if (test_bit(AFS_VNODE_DELETED
, &vnode
->flags
))
319 /* check to see if it got updated and invalidated all
320 * before we saw it */
321 if (vnode
->update_cnt
== 0) {
322 remove_wait_queue(&vnode
->update_waitq
,
324 set_current_state(TASK_RUNNING
);
328 spin_unlock(&vnode
->lock
);
331 set_current_state(TASK_UNINTERRUPTIBLE
);
333 spin_lock(&vnode
->lock
);
336 remove_wait_queue(&vnode
->update_waitq
, &myself
);
337 spin_unlock(&vnode
->lock
);
338 set_current_state(TASK_RUNNING
);
340 return test_bit(AFS_VNODE_DELETED
, &vnode
->flags
) ?
345 /* okay... we're going to have to initiate the op */
348 spin_unlock(&vnode
->lock
);
350 /* merge AFS status fetches and clear outstanding callback on this
353 /* pick a server to query */
354 server
= afs_volume_pick_fileserver(vnode
);
358 _debug("USING SERVER: %p{%08x}",
359 server
, ntohl(server
->addr
.s_addr
));
361 ret
= afs_fs_fetch_file_status(server
, key
, vnode
, NULL
,
364 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
366 /* adjust the flags */
370 afs_cache_permit(vnode
, key
, acl_order
);
371 afs_vnode_finalise_status_update(vnode
, server
);
372 afs_put_server(server
);
374 _debug("failed [%d]", ret
);
375 afs_vnode_status_update_failed(vnode
, ret
);
378 ASSERTCMP(vnode
->update_cnt
, >=, 0);
380 _leave(" = %d [cnt %d]", ret
, vnode
->update_cnt
);
384 spin_lock(&vnode
->lock
);
386 ASSERTCMP(vnode
->update_cnt
, >=, 0);
387 spin_unlock(&vnode
->lock
);
388 _leave(" = %ld [cnt %d]", PTR_ERR(server
), vnode
->update_cnt
);
389 return PTR_ERR(server
);
393 * fetch file data from the volume
394 * - TODO implement caching
396 int afs_vnode_fetch_data(struct afs_vnode
*vnode
, struct key
*key
,
397 off_t offset
, size_t length
, struct page
*page
)
399 struct afs_server
*server
;
402 _enter("%s{%x:%u.%u},%x,,,",
403 vnode
->volume
->vlocation
->vldb
.name
,
409 /* this op will fetch the status */
410 spin_lock(&vnode
->lock
);
412 spin_unlock(&vnode
->lock
);
414 /* merge in AFS status fetches and clear outstanding callback on this
417 /* pick a server to query */
418 server
= afs_volume_pick_fileserver(vnode
);
422 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
424 ret
= afs_fs_fetch_data(server
, key
, vnode
, offset
, length
,
425 page
, &afs_sync_call
);
427 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
429 /* adjust the flags */
431 afs_vnode_finalise_status_update(vnode
, server
);
432 afs_put_server(server
);
434 afs_vnode_status_update_failed(vnode
, ret
);
437 _leave(" = %d", ret
);
441 spin_lock(&vnode
->lock
);
443 ASSERTCMP(vnode
->update_cnt
, >=, 0);
444 spin_unlock(&vnode
->lock
);
445 return PTR_ERR(server
);
449 * make a file or a directory
451 int afs_vnode_create(struct afs_vnode
*vnode
, struct key
*key
,
452 const char *name
, umode_t mode
, struct afs_fid
*newfid
,
453 struct afs_file_status
*newstatus
,
454 struct afs_callback
*newcb
, struct afs_server
**_server
)
456 struct afs_server
*server
;
459 _enter("%s{%x:%u.%u},%x,%s,,",
460 vnode
->volume
->vlocation
->vldb
.name
,
467 /* this op will fetch the status on the directory we're creating in */
468 spin_lock(&vnode
->lock
);
470 spin_unlock(&vnode
->lock
);
473 /* pick a server to query */
474 server
= afs_volume_pick_fileserver(vnode
);
478 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
480 ret
= afs_fs_create(server
, key
, vnode
, name
, mode
, newfid
,
481 newstatus
, newcb
, &afs_sync_call
);
483 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
485 /* adjust the flags */
487 afs_vnode_finalise_status_update(vnode
, server
);
490 afs_vnode_status_update_failed(vnode
, ret
);
494 _leave(" = %d [cnt %d]", ret
, vnode
->update_cnt
);
498 spin_lock(&vnode
->lock
);
500 ASSERTCMP(vnode
->update_cnt
, >=, 0);
501 spin_unlock(&vnode
->lock
);
502 _leave(" = %ld [cnt %d]", PTR_ERR(server
), vnode
->update_cnt
);
503 return PTR_ERR(server
);
507 * remove a file or directory
509 int afs_vnode_remove(struct afs_vnode
*vnode
, struct key
*key
, const char *name
,
512 struct afs_server
*server
;
515 _enter("%s{%x:%u.%u},%x,%s",
516 vnode
->volume
->vlocation
->vldb
.name
,
523 /* this op will fetch the status on the directory we're removing from */
524 spin_lock(&vnode
->lock
);
526 spin_unlock(&vnode
->lock
);
529 /* pick a server to query */
530 server
= afs_volume_pick_fileserver(vnode
);
534 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
536 ret
= afs_fs_remove(server
, key
, vnode
, name
, isdir
,
539 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
541 /* adjust the flags */
543 afs_vnode_finalise_status_update(vnode
, server
);
544 afs_put_server(server
);
546 afs_vnode_status_update_failed(vnode
, ret
);
549 _leave(" = %d [cnt %d]", ret
, vnode
->update_cnt
);
553 spin_lock(&vnode
->lock
);
555 ASSERTCMP(vnode
->update_cnt
, >=, 0);
556 spin_unlock(&vnode
->lock
);
557 _leave(" = %ld [cnt %d]", PTR_ERR(server
), vnode
->update_cnt
);
558 return PTR_ERR(server
);
564 int afs_vnode_link(struct afs_vnode
*dvnode
, struct afs_vnode
*vnode
,
565 struct key
*key
, const char *name
)
567 struct afs_server
*server
;
570 _enter("%s{%x:%u.%u},%s{%x:%u.%u},%x,%s",
571 dvnode
->volume
->vlocation
->vldb
.name
,
575 vnode
->volume
->vlocation
->vldb
.name
,
582 /* this op will fetch the status on the directory we're removing from */
583 spin_lock(&vnode
->lock
);
585 spin_unlock(&vnode
->lock
);
586 spin_lock(&dvnode
->lock
);
587 dvnode
->update_cnt
++;
588 spin_unlock(&dvnode
->lock
);
591 /* pick a server to query */
592 server
= afs_volume_pick_fileserver(dvnode
);
596 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
598 ret
= afs_fs_link(server
, key
, dvnode
, vnode
, name
,
601 } while (!afs_volume_release_fileserver(dvnode
, server
, ret
));
603 /* adjust the flags */
605 afs_vnode_finalise_status_update(vnode
, server
);
606 afs_vnode_finalise_status_update(dvnode
, server
);
607 afs_put_server(server
);
609 afs_vnode_status_update_failed(vnode
, ret
);
610 afs_vnode_status_update_failed(dvnode
, ret
);
613 _leave(" = %d [cnt %d]", ret
, vnode
->update_cnt
);
617 spin_lock(&vnode
->lock
);
619 ASSERTCMP(vnode
->update_cnt
, >=, 0);
620 spin_unlock(&vnode
->lock
);
621 spin_lock(&dvnode
->lock
);
622 dvnode
->update_cnt
--;
623 ASSERTCMP(dvnode
->update_cnt
, >=, 0);
624 spin_unlock(&dvnode
->lock
);
625 _leave(" = %ld [cnt %d]", PTR_ERR(server
), vnode
->update_cnt
);
626 return PTR_ERR(server
);
630 * create a symbolic link
632 int afs_vnode_symlink(struct afs_vnode
*vnode
, struct key
*key
,
633 const char *name
, const char *content
,
634 struct afs_fid
*newfid
,
635 struct afs_file_status
*newstatus
,
636 struct afs_server
**_server
)
638 struct afs_server
*server
;
641 _enter("%s{%x:%u.%u},%x,%s,%s,,,",
642 vnode
->volume
->vlocation
->vldb
.name
,
649 /* this op will fetch the status on the directory we're creating in */
650 spin_lock(&vnode
->lock
);
652 spin_unlock(&vnode
->lock
);
655 /* pick a server to query */
656 server
= afs_volume_pick_fileserver(vnode
);
660 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
662 ret
= afs_fs_symlink(server
, key
, vnode
, name
, content
,
663 newfid
, newstatus
, &afs_sync_call
);
665 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
667 /* adjust the flags */
669 afs_vnode_finalise_status_update(vnode
, server
);
672 afs_vnode_status_update_failed(vnode
, ret
);
676 _leave(" = %d [cnt %d]", ret
, vnode
->update_cnt
);
680 spin_lock(&vnode
->lock
);
682 ASSERTCMP(vnode
->update_cnt
, >=, 0);
683 spin_unlock(&vnode
->lock
);
684 _leave(" = %ld [cnt %d]", PTR_ERR(server
), vnode
->update_cnt
);
685 return PTR_ERR(server
);
691 int afs_vnode_rename(struct afs_vnode
*orig_dvnode
,
692 struct afs_vnode
*new_dvnode
,
694 const char *orig_name
,
695 const char *new_name
)
697 struct afs_server
*server
;
700 _enter("%s{%x:%u.%u},%s{%u,%u,%u},%x,%s,%s",
701 orig_dvnode
->volume
->vlocation
->vldb
.name
,
702 orig_dvnode
->fid
.vid
,
703 orig_dvnode
->fid
.vnode
,
704 orig_dvnode
->fid
.unique
,
705 new_dvnode
->volume
->vlocation
->vldb
.name
,
707 new_dvnode
->fid
.vnode
,
708 new_dvnode
->fid
.unique
,
713 /* this op will fetch the status on both the directories we're dealing
715 spin_lock(&orig_dvnode
->lock
);
716 orig_dvnode
->update_cnt
++;
717 spin_unlock(&orig_dvnode
->lock
);
718 if (new_dvnode
!= orig_dvnode
) {
719 spin_lock(&new_dvnode
->lock
);
720 new_dvnode
->update_cnt
++;
721 spin_unlock(&new_dvnode
->lock
);
725 /* pick a server to query */
726 server
= afs_volume_pick_fileserver(orig_dvnode
);
730 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
732 ret
= afs_fs_rename(server
, key
, orig_dvnode
, orig_name
,
733 new_dvnode
, new_name
, &afs_sync_call
);
735 } while (!afs_volume_release_fileserver(orig_dvnode
, server
, ret
));
737 /* adjust the flags */
739 afs_vnode_finalise_status_update(orig_dvnode
, server
);
740 if (new_dvnode
!= orig_dvnode
)
741 afs_vnode_finalise_status_update(new_dvnode
, server
);
742 afs_put_server(server
);
744 afs_vnode_status_update_failed(orig_dvnode
, ret
);
745 if (new_dvnode
!= orig_dvnode
)
746 afs_vnode_status_update_failed(new_dvnode
, ret
);
749 _leave(" = %d [cnt %d]", ret
, orig_dvnode
->update_cnt
);
753 spin_lock(&orig_dvnode
->lock
);
754 orig_dvnode
->update_cnt
--;
755 ASSERTCMP(orig_dvnode
->update_cnt
, >=, 0);
756 spin_unlock(&orig_dvnode
->lock
);
757 if (new_dvnode
!= orig_dvnode
) {
758 spin_lock(&new_dvnode
->lock
);
759 new_dvnode
->update_cnt
--;
760 ASSERTCMP(new_dvnode
->update_cnt
, >=, 0);
761 spin_unlock(&new_dvnode
->lock
);
763 _leave(" = %ld [cnt %d]", PTR_ERR(server
), orig_dvnode
->update_cnt
);
764 return PTR_ERR(server
);
770 int afs_vnode_store_data(struct afs_writeback
*wb
, pgoff_t first
, pgoff_t last
,
771 unsigned offset
, unsigned to
)
773 struct afs_server
*server
;
774 struct afs_vnode
*vnode
= wb
->vnode
;
777 _enter("%s{%x:%u.%u},%x,%lx,%lx,%x,%x",
778 vnode
->volume
->vlocation
->vldb
.name
,
783 first
, last
, offset
, to
);
785 /* this op will fetch the status */
786 spin_lock(&vnode
->lock
);
788 spin_unlock(&vnode
->lock
);
791 /* pick a server to query */
792 server
= afs_volume_pick_fileserver(vnode
);
796 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
798 ret
= afs_fs_store_data(server
, wb
, first
, last
, offset
, to
,
801 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
803 /* adjust the flags */
805 afs_vnode_finalise_status_update(vnode
, server
);
806 afs_put_server(server
);
808 afs_vnode_status_update_failed(vnode
, ret
);
811 _leave(" = %d", ret
);
815 spin_lock(&vnode
->lock
);
817 ASSERTCMP(vnode
->update_cnt
, >=, 0);
818 spin_unlock(&vnode
->lock
);
819 return PTR_ERR(server
);
823 * set the attributes on a file
825 int afs_vnode_setattr(struct afs_vnode
*vnode
, struct key
*key
,
828 struct afs_server
*server
;
831 _enter("%s{%x:%u.%u},%x",
832 vnode
->volume
->vlocation
->vldb
.name
,
838 /* this op will fetch the status */
839 spin_lock(&vnode
->lock
);
841 spin_unlock(&vnode
->lock
);
844 /* pick a server to query */
845 server
= afs_volume_pick_fileserver(vnode
);
849 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
851 ret
= afs_fs_setattr(server
, key
, vnode
, attr
, &afs_sync_call
);
853 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
855 /* adjust the flags */
857 afs_vnode_finalise_status_update(vnode
, server
);
858 afs_put_server(server
);
860 afs_vnode_status_update_failed(vnode
, ret
);
863 _leave(" = %d", ret
);
867 spin_lock(&vnode
->lock
);
869 ASSERTCMP(vnode
->update_cnt
, >=, 0);
870 spin_unlock(&vnode
->lock
);
871 return PTR_ERR(server
);
875 * get the status of a volume
877 int afs_vnode_get_volume_status(struct afs_vnode
*vnode
, struct key
*key
,
878 struct afs_volume_status
*vs
)
880 struct afs_server
*server
;
883 _enter("%s{%x:%u.%u},%x,",
884 vnode
->volume
->vlocation
->vldb
.name
,
891 /* pick a server to query */
892 server
= afs_volume_pick_fileserver(vnode
);
896 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
898 ret
= afs_fs_get_volume_status(server
, key
, vnode
, vs
, &afs_sync_call
);
900 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
902 /* adjust the flags */
904 afs_put_server(server
);
906 _leave(" = %d", ret
);
910 return PTR_ERR(server
);
914 * get a lock on a file
916 int afs_vnode_set_lock(struct afs_vnode
*vnode
, struct key
*key
,
917 afs_lock_type_t type
)
919 struct afs_server
*server
;
922 _enter("%s{%x:%u.%u},%x,%u",
923 vnode
->volume
->vlocation
->vldb
.name
,
927 key_serial(key
), type
);
930 /* pick a server to query */
931 server
= afs_volume_pick_fileserver(vnode
);
935 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
937 ret
= afs_fs_set_lock(server
, key
, vnode
, type
, &afs_sync_call
);
939 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
941 /* adjust the flags */
943 afs_put_server(server
);
945 _leave(" = %d", ret
);
949 return PTR_ERR(server
);
953 * extend a lock on a file
955 int afs_vnode_extend_lock(struct afs_vnode
*vnode
, struct key
*key
)
957 struct afs_server
*server
;
960 _enter("%s{%x:%u.%u},%x",
961 vnode
->volume
->vlocation
->vldb
.name
,
968 /* pick a server to query */
969 server
= afs_volume_pick_fileserver(vnode
);
973 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
975 ret
= afs_fs_extend_lock(server
, key
, vnode
, &afs_sync_call
);
977 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
979 /* adjust the flags */
981 afs_put_server(server
);
983 _leave(" = %d", ret
);
987 return PTR_ERR(server
);
991 * release a lock on a file
993 int afs_vnode_release_lock(struct afs_vnode
*vnode
, struct key
*key
)
995 struct afs_server
*server
;
998 _enter("%s{%x:%u.%u},%x",
999 vnode
->volume
->vlocation
->vldb
.name
,
1006 /* pick a server to query */
1007 server
= afs_volume_pick_fileserver(vnode
);
1011 _debug("USING SERVER: %08x\n", ntohl(server
->addr
.s_addr
));
1013 ret
= afs_fs_release_lock(server
, key
, vnode
, &afs_sync_call
);
1015 } while (!afs_volume_release_fileserver(vnode
, server
, ret
));
1017 /* adjust the flags */
1019 afs_put_server(server
);
1021 _leave(" = %d", ret
);
1025 return PTR_ERR(server
);