aboutsummaryrefslogtreecommitdiffstats
path: root/fs/afs/dir.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2007-04-26 18:59:35 -0400
committerDavid S. Miller <davem@davemloft.net>2007-04-26 18:59:35 -0400
commit260a980317dac80182dd76140cf67c6e81d6d3dd (patch)
tree84f3e919fd33be56aad4fc57f5cb844df1a6b952 /fs/afs/dir.c
parentc35eccb1f614954b10cba3f74b7c301993b2f42e (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/dir.c')
-rw-r--r--fs/afs/dir.c676
1 files changed, 536 insertions, 140 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c
index 87368417e4d3..dbbe75d6023b 100644
--- a/fs/afs/dir.c
+++ b/fs/afs/dir.c
@@ -18,40 +18,50 @@
18#include <linux/ctype.h> 18#include <linux/ctype.h>
19#include "internal.h" 19#include "internal.h"
20 20
21static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 21static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
22 struct nameidata *nd); 22 struct nameidata *nd);
23static int afs_dir_open(struct inode *inode, struct file *file); 23static int afs_dir_open(struct inode *inode, struct file *file);
24static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir); 24static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
25static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd); 25static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
26static int afs_d_delete(struct dentry *dentry); 26static int afs_d_delete(struct dentry *dentry);
27static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, 27static void afs_d_release(struct dentry *dentry);
28static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
28 loff_t fpos, u64 ino, unsigned dtype); 29 loff_t fpos, u64 ino, unsigned dtype);
30static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
31 struct nameidata *nd);
32static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode);
33static int afs_rmdir(struct inode *dir, struct dentry *dentry);
34static int afs_unlink(struct inode *dir, struct dentry *dentry);
35static int afs_link(struct dentry *from, struct inode *dir,
36 struct dentry *dentry);
37static int afs_symlink(struct inode *dir, struct dentry *dentry,
38 const char *content);
39static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
40 struct inode *new_dir, struct dentry *new_dentry);
29 41
30const struct file_operations afs_dir_file_operations = { 42const struct file_operations afs_dir_file_operations = {
31 .open = afs_dir_open, 43 .open = afs_dir_open,
32 .release = afs_release, 44 .release = afs_release,
33 .readdir = afs_dir_readdir, 45 .readdir = afs_readdir,
34}; 46};
35 47
36const struct inode_operations afs_dir_inode_operations = { 48const struct inode_operations afs_dir_inode_operations = {
37 .lookup = afs_dir_lookup, 49 .create = afs_create,
50 .lookup = afs_lookup,
51 .link = afs_link,
52 .unlink = afs_unlink,
53 .symlink = afs_symlink,
54 .mkdir = afs_mkdir,
55 .rmdir = afs_rmdir,
56 .rename = afs_rename,
38 .permission = afs_permission, 57 .permission = afs_permission,
39 .getattr = afs_inode_getattr, 58 .getattr = afs_inode_getattr,
40#if 0 /* TODO */
41 .create = afs_dir_create,
42 .link = afs_dir_link,
43 .unlink = afs_dir_unlink,
44 .symlink = afs_dir_symlink,
45 .mkdir = afs_dir_mkdir,
46 .rmdir = afs_dir_rmdir,
47 .mknod = afs_dir_mknod,
48 .rename = afs_dir_rename,
49#endif
50}; 59};
51 60
52static struct dentry_operations afs_fs_dentry_operations = { 61static struct dentry_operations afs_fs_dentry_operations = {
53 .d_revalidate = afs_d_revalidate, 62 .d_revalidate = afs_d_revalidate,
54 .d_delete = afs_d_delete, 63 .d_delete = afs_d_delete,
64 .d_release = afs_d_release,
55}; 65};
56 66
57#define AFS_DIR_HASHTBL_SIZE 128 67#define AFS_DIR_HASHTBL_SIZE 128
@@ -103,7 +113,7 @@ struct afs_dir_page {
103 union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)]; 113 union afs_dir_block blocks[PAGE_SIZE / sizeof(union afs_dir_block)];
104}; 114};
105 115
106struct afs_dir_lookup_cookie { 116struct afs_lookup_cookie {
107 struct afs_fid fid; 117 struct afs_fid fid;
108 const char *name; 118 const char *name;
109 size_t nlen; 119 size_t nlen;
@@ -299,7 +309,7 @@ static int afs_dir_iterate_block(unsigned *fpos,
299 nlen, 309 nlen,
300 blkoff + offset * sizeof(union afs_dirent), 310 blkoff + offset * sizeof(union afs_dirent),
301 ntohl(dire->u.vnode), 311 ntohl(dire->u.vnode),
302 filldir == afs_dir_lookup_filldir ? 312 filldir == afs_lookup_filldir ?
303 ntohl(dire->u.unique) : DT_UNKNOWN); 313 ntohl(dire->u.unique) : DT_UNKNOWN);
304 if (ret < 0) { 314 if (ret < 0) {
305 _leave(" = 0 [full]"); 315 _leave(" = 0 [full]");
@@ -379,7 +389,7 @@ out:
379/* 389/*
380 * read an AFS directory 390 * read an AFS directory
381 */ 391 */
382static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir) 392static int afs_readdir(struct file *file, void *cookie, filldir_t filldir)
383{ 393{
384 unsigned fpos; 394 unsigned fpos;
385 int ret; 395 int ret;
@@ -403,10 +413,10 @@ static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
403 * - if afs_dir_iterate_block() spots this function, it'll pass the FID 413 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
404 * uniquifier through dtype 414 * uniquifier through dtype
405 */ 415 */
406static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, 416static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
407 loff_t fpos, u64 ino, unsigned dtype) 417 loff_t fpos, u64 ino, unsigned dtype)
408{ 418{
409 struct afs_dir_lookup_cookie *cookie = _cookie; 419 struct afs_lookup_cookie *cookie = _cookie;
410 420
411 _enter("{%s,%Zu},%s,%u,,%llu,%u", 421 _enter("{%s,%Zu},%s,%u,,%llu,%u",
412 cookie->name, cookie->nlen, name, nlen, ino, dtype); 422 cookie->name, cookie->nlen, name, nlen, ino, dtype);
@@ -430,11 +440,12 @@ static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen,
430 440
431/* 441/*
432 * do a lookup in a directory 442 * do a lookup in a directory
443 * - just returns the FID the dentry name maps to if found
433 */ 444 */
434static int afs_do_lookup(struct inode *dir, struct dentry *dentry, 445static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
435 struct afs_fid *fid, struct key *key) 446 struct afs_fid *fid, struct key *key)
436{ 447{
437 struct afs_dir_lookup_cookie cookie; 448 struct afs_lookup_cookie cookie;
438 struct afs_super_info *as; 449 struct afs_super_info *as;
439 unsigned fpos; 450 unsigned fpos;
440 int ret; 451 int ret;
@@ -450,7 +461,7 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
450 cookie.found = 0; 461 cookie.found = 0;
451 462
452 fpos = 0; 463 fpos = 0;
453 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_dir_lookup_filldir, 464 ret = afs_dir_iterate(dir, &fpos, &cookie, afs_lookup_filldir,
454 key); 465 key);
455 if (ret < 0) { 466 if (ret < 0) {
456 _leave(" = %d [iter]", ret); 467 _leave(" = %d [iter]", ret);
@@ -471,8 +482,8 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry,
471/* 482/*
472 * look up an entry in a directory 483 * look up an entry in a directory
473 */ 484 */
474static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry, 485static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
475 struct nameidata *nd) 486 struct nameidata *nd)
476{ 487{
477 struct afs_vnode *vnode; 488 struct afs_vnode *vnode;
478 struct afs_fid fid; 489 struct afs_fid fid;
@@ -480,14 +491,18 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
480 struct key *key; 491 struct key *key;
481 int ret; 492 int ret;
482 493
483 _enter("{%lu},%p{%s}", dir->i_ino, dentry, dentry->d_name.name); 494 vnode = AFS_FS_I(dir);
495
496 _enter("{%x:%d},%p{%s},",
497 vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);
498
499 ASSERTCMP(dentry->d_inode, ==, NULL);
484 500
485 if (dentry->d_name.len > 255) { 501 if (dentry->d_name.len > 255) {
486 _leave(" = -ENAMETOOLONG"); 502 _leave(" = -ENAMETOOLONG");
487 return ERR_PTR(-ENAMETOOLONG); 503 return ERR_PTR(-ENAMETOOLONG);
488 } 504 }
489 505
490 vnode = AFS_FS_I(dir);
491 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 506 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
492 _leave(" = -ESTALE"); 507 _leave(" = -ESTALE");
493 return ERR_PTR(-ESTALE); 508 return ERR_PTR(-ESTALE);
@@ -499,15 +514,28 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
499 return ERR_PTR(PTR_ERR(key)); 514 return ERR_PTR(PTR_ERR(key));
500 } 515 }
501 516
517 ret = afs_validate(vnode, key);
518 if (ret < 0) {
519 key_put(key);
520 _leave(" = %d [val]", ret);
521 return ERR_PTR(ret);
522 }
523
502 ret = afs_do_lookup(dir, dentry, &fid, key); 524 ret = afs_do_lookup(dir, dentry, &fid, key);
503 if (ret < 0) { 525 if (ret < 0) {
504 key_put(key); 526 key_put(key);
527 if (ret == -ENOENT) {
528 d_add(dentry, NULL);
529 _leave(" = NULL [negative]");
530 return NULL;
531 }
505 _leave(" = %d [do]", ret); 532 _leave(" = %d [do]", ret);
506 return ERR_PTR(ret); 533 return ERR_PTR(ret);
507 } 534 }
535 dentry->d_fsdata = (void *)(unsigned long) vnode->status.data_version;
508 536
509 /* instantiate the dentry */ 537 /* instantiate the dentry */
510 inode = afs_iget(dir->i_sb, key, &fid); 538 inode = afs_iget(dir->i_sb, key, &fid, NULL, NULL);
511 key_put(key); 539 key_put(key);
512 if (IS_ERR(inode)) { 540 if (IS_ERR(inode)) {
513 _leave(" = %ld", PTR_ERR(inode)); 541 _leave(" = %ld", PTR_ERR(inode));
@@ -527,105 +555,64 @@ static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry,
527} 555}
528 556
529/* 557/*
530 * propagate changed and modified flags on a directory to all the children of
531 * that directory as they may indicate that the ACL on the dir has changed,
532 * potentially rendering the child inaccessible or that a file has been deleted
533 * or renamed
534 */
535static void afs_propagate_dir_changes(struct dentry *dir)
536{
537 struct dentry *child;
538 bool c, m;
539
540 c = test_bit(AFS_VNODE_CHANGED, &AFS_FS_I(dir->d_inode)->flags);
541 m = test_bit(AFS_VNODE_MODIFIED, &AFS_FS_I(dir->d_inode)->flags);
542
543 _enter("{%d,%d}", c, m);
544
545 spin_lock(&dir->d_lock);
546
547 list_for_each_entry(child, &dir->d_subdirs, d_u.d_child) {
548 if (child->d_inode) {
549 struct afs_vnode *vnode;
550
551 _debug("tag %s", child->d_name.name);
552 vnode = AFS_FS_I(child->d_inode);
553 if (c)
554 set_bit(AFS_VNODE_DIR_CHANGED, &vnode->flags);
555 if (m)
556 set_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags);
557 }
558 }
559
560 spin_unlock(&dir->d_lock);
561}
562
563/*
564 * check that a dentry lookup hit has found a valid entry 558 * check that a dentry lookup hit has found a valid entry
565 * - NOTE! the hit can be a negative hit too, so we can't assume we have an 559 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
566 * inode 560 * inode
567 * - there are several things we need to check
568 * - parent dir data changes (rm, rmdir, rename, mkdir, create, link,
569 * symlink)
570 * - parent dir metadata changed (security changes)
571 * - dentry data changed (write, truncate)
572 * - dentry metadata changed (security changes)
573 */ 561 */
574static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) 562static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
575{ 563{
576 struct afs_vnode *vnode; 564 struct afs_vnode *vnode, *dir;
577 struct afs_fid fid; 565 struct afs_fid fid;
578 struct dentry *parent; 566 struct dentry *parent;
579 struct inode *inode, *dir;
580 struct key *key; 567 struct key *key;
568 void *dir_version;
581 int ret; 569 int ret;
582 570
583 vnode = AFS_FS_I(dentry->d_inode); 571 vnode = AFS_FS_I(dentry->d_inode);
584 572
585 _enter("{sb=%p n=%s fl=%lx},", 573 if (dentry->d_inode)
586 dentry->d_sb, dentry->d_name.name, vnode->flags); 574 _enter("{v={%x:%u} n=%s fl=%lx},",
575 vnode->fid.vid, vnode->fid.vnode, dentry->d_name.name,
576 vnode->flags);
577 else
578 _enter("{neg n=%s}", dentry->d_name.name);
587 579
588 key = afs_request_key(vnode->volume->cell); 580 key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
589 if (IS_ERR(key)) 581 if (IS_ERR(key))
590 key = NULL; 582 key = NULL;
591 583
592 /* lock down the parent dentry so we can peer at it */ 584 /* lock down the parent dentry so we can peer at it */
593 parent = dget_parent(dentry); 585 parent = dget_parent(dentry);
594 586 if (!parent->d_inode)
595 dir = parent->d_inode;
596 inode = dentry->d_inode;
597
598 /* handle a negative dentry */
599 if (!inode)
600 goto out_bad; 587 goto out_bad;
601 588
602 /* handle a bad inode */ 589 dir = AFS_FS_I(parent->d_inode);
603 if (is_bad_inode(inode)) {
604 printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
605 parent->d_name.name, dentry->d_name.name);
606 goto out_bad;
607 }
608 590
609 /* check that this dirent still exists if the directory's contents were 591 /* validate the parent directory */
610 * modified */ 592 if (test_bit(AFS_VNODE_MODIFIED, &dir->flags))
611 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) { 593 afs_validate(dir, key);
594
595 if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
612 _debug("%s: parent dir deleted", dentry->d_name.name); 596 _debug("%s: parent dir deleted", dentry->d_name.name);
613 goto out_bad; 597 goto out_bad;
614 } 598 }
615 599
616 if (test_and_clear_bit(AFS_VNODE_DIR_MODIFIED, &vnode->flags)) { 600 dir_version = (void *) (unsigned long) dir->status.data_version;
617 /* rm/rmdir/rename may have occurred */ 601 if (dentry->d_fsdata == dir_version)
618 _debug("dir modified"); 602 goto out_valid; /* the dir contents are unchanged */
619 603
620 /* search the directory for this vnode */ 604 _debug("dir modified");
621 ret = afs_do_lookup(dir, dentry, &fid, key); 605
622 if (ret == -ENOENT) { 606 /* search the directory for this vnode */
623 _debug("%s: dirent not found", dentry->d_name.name); 607 ret = afs_do_lookup(&dir->vfs_inode, dentry, &fid, key);
624 goto not_found; 608 switch (ret) {
625 } 609 case 0:
626 if (ret < 0) { 610 /* the filename maps to something */
627 _debug("failed to iterate dir %s: %d", 611 if (!dentry->d_inode)
628 parent->d_name.name, ret); 612 goto out_bad;
613 if (is_bad_inode(dentry->d_inode)) {
614 printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
615 parent->d_name.name, dentry->d_name.name);
629 goto out_bad; 616 goto out_bad;
630 } 617 }
631 618
@@ -639,56 +626,35 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
639 } 626 }
640 627
641 /* if the vnode ID uniqifier has changed, then the file has 628 /* if the vnode ID uniqifier has changed, then the file has
642 * been deleted */ 629 * been deleted and replaced, and the original vnode ID has
630 * been reused */
643 if (fid.unique != vnode->fid.unique) { 631 if (fid.unique != vnode->fid.unique) {
644 _debug("%s: file deleted (uq %u -> %u I:%lu)", 632 _debug("%s: file deleted (uq %u -> %u I:%lu)",
645 dentry->d_name.name, fid.unique, 633 dentry->d_name.name, fid.unique,
646 vnode->fid.unique, inode->i_version); 634 vnode->fid.unique, dentry->d_inode->i_version);
647 spin_lock(&vnode->lock); 635 spin_lock(&vnode->lock);
648 set_bit(AFS_VNODE_DELETED, &vnode->flags); 636 set_bit(AFS_VNODE_DELETED, &vnode->flags);
649 spin_unlock(&vnode->lock); 637 spin_unlock(&vnode->lock);
650 invalidate_remote_inode(inode); 638 goto not_found;
651 goto out_bad;
652 } 639 }
653 } 640 goto out_valid;
654 641
655 /* if the directory's metadata were changed then the security may be 642 case -ENOENT:
656 * different and we may no longer have access */ 643 /* the filename is unknown */
657 mutex_lock(&vnode->cb_broken_lock); 644 _debug("%s: dirent not found", dentry->d_name.name);
658 645 if (dentry->d_inode)
659 if (test_and_clear_bit(AFS_VNODE_DIR_CHANGED, &vnode->flags) || 646 goto not_found;
660 test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) { 647 goto out_valid;
661 _debug("%s: changed", dentry->d_name.name);
662 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
663 if (afs_vnode_fetch_status(vnode, NULL, key) < 0) {
664 mutex_unlock(&vnode->cb_broken_lock);
665 goto out_bad;
666 }
667 }
668 648
669 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { 649 default:
670 _debug("%s: file already deleted", dentry->d_name.name); 650 _debug("failed to iterate dir %s: %d",
671 mutex_unlock(&vnode->cb_broken_lock); 651 parent->d_name.name, ret);
672 goto out_bad; 652 goto out_bad;
673 } 653 }
674 654
675 /* if the vnode's data version number changed then its contents are
676 * different */
677 if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
678 _debug("zap data");
679 invalidate_remote_inode(inode);
680 }
681
682 if (S_ISDIR(inode->i_mode) &&
683 (test_bit(AFS_VNODE_CHANGED, &vnode->flags) ||
684 test_bit(AFS_VNODE_MODIFIED, &vnode->flags)))
685 afs_propagate_dir_changes(dentry);
686
687 clear_bit(AFS_VNODE_CHANGED, &vnode->flags);
688 clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
689 mutex_unlock(&vnode->cb_broken_lock);
690
691out_valid: 655out_valid:
656 dentry->d_fsdata = dir_version;
657out_skip:
692 dput(parent); 658 dput(parent);
693 key_put(key); 659 key_put(key);
694 _leave(" = 1 [valid]"); 660 _leave(" = 1 [valid]");
@@ -701,10 +667,10 @@ not_found:
701 spin_unlock(&dentry->d_lock); 667 spin_unlock(&dentry->d_lock);
702 668
703out_bad: 669out_bad:
704 if (inode) { 670 if (dentry->d_inode) {
705 /* don't unhash if we have submounts */ 671 /* don't unhash if we have submounts */
706 if (have_submounts(dentry)) 672 if (have_submounts(dentry))
707 goto out_valid; 673 goto out_skip;
708 } 674 }
709 675
710 _debug("dropping dentry %s/%s", 676 _debug("dropping dentry %s/%s",
@@ -742,3 +708,433 @@ zap:
742 _leave(" = 1 [zap]"); 708 _leave(" = 1 [zap]");
743 return 1; 709 return 1;
744} 710}
711
712/*
713 * handle dentry release
714 */
715static void afs_d_release(struct dentry *dentry)
716{
717 _enter("%s", dentry->d_name.name);
718}
719
720/*
721 * create a directory on an AFS filesystem
722 */
723static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
724{
725 struct afs_file_status status;
726 struct afs_callback cb;
727 struct afs_server *server;
728 struct afs_vnode *dvnode, *vnode;
729 struct afs_fid fid;
730 struct inode *inode;
731 struct key *key;
732 int ret;
733
734 dvnode = AFS_FS_I(dir);
735
736 _enter("{%x:%d},{%s},%o",
737 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
738
739 ret = -ENAMETOOLONG;
740 if (dentry->d_name.len > 255)
741 goto error;
742
743 key = afs_request_key(dvnode->volume->cell);
744 if (IS_ERR(key)) {
745 ret = PTR_ERR(key);
746 goto error;
747 }
748
749 mode |= S_IFDIR;
750 ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
751 mode, &fid, &status, &cb, &server);
752 if (ret < 0)
753 goto mkdir_error;
754
755 inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
756 if (IS_ERR(inode)) {
757 /* ENOMEM at a really inconvenient time - just abandon the new
758 * directory on the server */
759 ret = PTR_ERR(inode);
760 goto iget_error;
761 }
762
763 /* apply the status report we've got for the new vnode */
764 vnode = AFS_FS_I(inode);
765 spin_lock(&vnode->lock);
766 vnode->update_cnt++;
767 spin_unlock(&vnode->lock);
768 afs_vnode_finalise_status_update(vnode, server);
769 afs_put_server(server);
770
771 d_instantiate(dentry, inode);
772 if (d_unhashed(dentry)) {
773 _debug("not hashed");
774 d_rehash(dentry);
775 }
776 key_put(key);
777 _leave(" = 0");
778 return 0;
779
780iget_error:
781 afs_put_server(server);
782mkdir_error:
783 key_put(key);
784error:
785 d_drop(dentry);
786 _leave(" = %d", ret);
787 return ret;
788}
789
790/*
791 * remove a directory from an AFS filesystem
792 */
793static int afs_rmdir(struct inode *dir, struct dentry *dentry)
794{
795 struct afs_vnode *dvnode, *vnode;
796 struct key *key;
797 int ret;
798
799 dvnode = AFS_FS_I(dir);
800
801 _enter("{%x:%d},{%s}",
802 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
803
804 ret = -ENAMETOOLONG;
805 if (dentry->d_name.len > 255)
806 goto error;
807
808 key = afs_request_key(dvnode->volume->cell);
809 if (IS_ERR(key)) {
810 ret = PTR_ERR(key);
811 goto error;
812 }
813
814 ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, true);
815 if (ret < 0)
816 goto rmdir_error;
817
818 if (dentry->d_inode) {
819 vnode = AFS_FS_I(dentry->d_inode);
820 clear_nlink(&vnode->vfs_inode);
821 set_bit(AFS_VNODE_DELETED, &vnode->flags);
822 afs_discard_callback_on_delete(vnode);
823 }
824
825 key_put(key);
826 _leave(" = 0");
827 return 0;
828
829rmdir_error:
830 key_put(key);
831error:
832 _leave(" = %d", ret);
833 return ret;
834}
835
836/*
837 * remove a file from an AFS filesystem
838 */
839static int afs_unlink(struct inode *dir, struct dentry *dentry)
840{
841 struct afs_vnode *dvnode, *vnode;
842 struct key *key;
843 int ret;
844
845 dvnode = AFS_FS_I(dir);
846
847 _enter("{%x:%d},{%s}",
848 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);
849
850 ret = -ENAMETOOLONG;
851 if (dentry->d_name.len > 255)
852 goto error;
853
854 key = afs_request_key(dvnode->volume->cell);
855 if (IS_ERR(key)) {
856 ret = PTR_ERR(key);
857 goto error;
858 }
859
860 if (dentry->d_inode) {
861 vnode = AFS_FS_I(dentry->d_inode);
862
863 /* make sure we have a callback promise on the victim */
864 ret = afs_validate(vnode, key);
865 if (ret < 0)
866 goto error;
867 }
868
869 ret = afs_vnode_remove(dvnode, key, dentry->d_name.name, false);
870 if (ret < 0)
871 goto remove_error;
872
873 if (dentry->d_inode) {
874 /* if the file wasn't deleted due to excess hard links, the
875 * fileserver will break the callback promise on the file - if
876 * it had one - before it returns to us, and if it was deleted,
877 * it won't
878 *
879 * however, if we didn't have a callback promise outstanding,
880 * or it was outstanding on a different server, then it won't
881 * break it either...
882 */
883 vnode = AFS_FS_I(dentry->d_inode);
884 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
885 _debug("AFS_VNODE_DELETED");
886 if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags))
887 _debug("AFS_VNODE_CB_BROKEN");
888 set_bit(AFS_VNODE_CB_BROKEN, &vnode->flags);
889 ret = afs_validate(vnode, key);
890 _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
891 }
892
893 key_put(key);
894 _leave(" = 0");
895 return 0;
896
897remove_error:
898 key_put(key);
899error:
900 _leave(" = %d", ret);
901 return ret;
902}
903
904/*
905 * create a regular file on an AFS filesystem
906 */
907static int afs_create(struct inode *dir, struct dentry *dentry, int mode,
908 struct nameidata *nd)
909{
910 struct afs_file_status status;
911 struct afs_callback cb;
912 struct afs_server *server;
913 struct afs_vnode *dvnode, *vnode;
914 struct afs_fid fid;
915 struct inode *inode;
916 struct key *key;
917 int ret;
918
919 dvnode = AFS_FS_I(dir);
920
921 _enter("{%x:%d},{%s},%o,",
922 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);
923
924 ret = -ENAMETOOLONG;
925 if (dentry->d_name.len > 255)
926 goto error;
927
928 key = afs_request_key(dvnode->volume->cell);
929 if (IS_ERR(key)) {
930 ret = PTR_ERR(key);
931 goto error;
932 }
933
934 mode |= S_IFREG;
935 ret = afs_vnode_create(dvnode, key, dentry->d_name.name,
936 mode, &fid, &status, &cb, &server);
937 if (ret < 0)
938 goto create_error;
939
940 inode = afs_iget(dir->i_sb, key, &fid, &status, &cb);
941 if (IS_ERR(inode)) {
942 /* ENOMEM at a really inconvenient time - just abandon the new
943 * directory on the server */
944 ret = PTR_ERR(inode);
945 goto iget_error;
946 }
947
948 /* apply the status report we've got for the new vnode */
949 vnode = AFS_FS_I(inode);
950 spin_lock(&vnode->lock);
951 vnode->update_cnt++;
952 spin_unlock(&vnode->lock);
953 afs_vnode_finalise_status_update(vnode, server);
954 afs_put_server(server);
955
956 d_instantiate(dentry, inode);
957 if (d_unhashed(dentry)) {
958 _debug("not hashed");
959 d_rehash(dentry);
960 }
961 key_put(key);
962 _leave(" = 0");
963 return 0;
964
965iget_error:
966 afs_put_server(server);
967create_error:
968 key_put(key);
969error:
970 d_drop(dentry);
971 _leave(" = %d", ret);
972 return ret;
973}
974
975/*
976 * create a hard link between files in an AFS filesystem
977 */
978static int afs_link(struct dentry *from, struct inode *dir,
979 struct dentry *dentry)
980{
981 struct afs_vnode *dvnode, *vnode;
982 struct key *key;
983 int ret;
984
985 vnode = AFS_FS_I(from->d_inode);
986 dvnode = AFS_FS_I(dir);
987
988 _enter("{%x:%d},{%x:%d},{%s}",
989 vnode->fid.vid, vnode->fid.vnode,
990 dvnode->fid.vid, dvnode->fid.vnode,
991 dentry->d_name.name);
992
993 ret = -ENAMETOOLONG;
994 if (dentry->d_name.len > 255)
995 goto error;
996
997 key = afs_request_key(dvnode->volume->cell);
998 if (IS_ERR(key)) {
999 ret = PTR_ERR(key);
1000 goto error;
1001 }
1002
1003 ret = afs_vnode_link(dvnode, vnode, key, dentry->d_name.name);
1004 if (ret < 0)
1005 goto link_error;
1006
1007 atomic_inc(&vnode->vfs_inode.i_count);
1008 d_instantiate(dentry, &vnode->vfs_inode);
1009 key_put(key);
1010 _leave(" = 0");
1011 return 0;
1012
1013link_error:
1014 key_put(key);
1015error:
1016 d_drop(dentry);
1017 _leave(" = %d", ret);
1018 return ret;
1019}
1020
1021/*
1022 * create a symlink in an AFS filesystem
1023 */
1024static int afs_symlink(struct inode *dir, struct dentry *dentry,
1025 const char *content)
1026{
1027 struct afs_file_status status;
1028 struct afs_server *server;
1029 struct afs_vnode *dvnode, *vnode;
1030 struct afs_fid fid;
1031 struct inode *inode;
1032 struct key *key;
1033 int ret;
1034
1035 dvnode = AFS_FS_I(dir);
1036
1037 _enter("{%x:%d},{%s},%s",
1038 dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
1039 content);
1040
1041 ret = -ENAMETOOLONG;
1042 if (dentry->d_name.len > 255)
1043 goto error;
1044
1045 ret = -EINVAL;
1046 if (strlen(content) > 1023)
1047 goto error;
1048
1049 key = afs_request_key(dvnode->volume->cell);
1050 if (IS_ERR(key)) {
1051 ret = PTR_ERR(key);
1052 goto error;
1053 }
1054
1055 ret = afs_vnode_symlink(dvnode, key, dentry->d_name.name, content,
1056 &fid, &status, &server);
1057 if (ret < 0)
1058 goto create_error;
1059
1060 inode = afs_iget(dir->i_sb, key, &fid, &status, NULL);
1061 if (IS_ERR(inode)) {
1062 /* ENOMEM at a really inconvenient time - just abandon the new
1063 * directory on the server */
1064 ret = PTR_ERR(inode);
1065 goto iget_error;
1066 }
1067
1068 /* apply the status report we've got for the new vnode */
1069 vnode = AFS_FS_I(inode);
1070 spin_lock(&vnode->lock);
1071 vnode->update_cnt++;
1072 spin_unlock(&vnode->lock);
1073 afs_vnode_finalise_status_update(vnode, server);
1074 afs_put_server(server);
1075
1076 d_instantiate(dentry, inode);
1077 if (d_unhashed(dentry)) {
1078 _debug("not hashed");
1079 d_rehash(dentry);
1080 }
1081 key_put(key);
1082 _leave(" = 0");
1083 return 0;
1084
1085iget_error:
1086 afs_put_server(server);
1087create_error:
1088 key_put(key);
1089error:
1090 d_drop(dentry);
1091 _leave(" = %d", ret);
1092 return ret;
1093}
1094
1095/*
1096 * rename a file in an AFS filesystem and/or move it between directories
1097 */
1098static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1099 struct inode *new_dir, struct dentry *new_dentry)
1100{
1101 struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1102 struct key *key;
1103 int ret;
1104
1105 vnode = AFS_FS_I(old_dentry->d_inode);
1106 orig_dvnode = AFS_FS_I(old_dir);
1107 new_dvnode = AFS_FS_I(new_dir);
1108
1109 _enter("{%x:%d},{%x:%d},{%x:%d},{%s}",
1110 orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1111 vnode->fid.vid, vnode->fid.vnode,
1112 new_dvnode->fid.vid, new_dvnode->fid.vnode,
1113 new_dentry->d_name.name);
1114
1115 ret = -ENAMETOOLONG;
1116 if (new_dentry->d_name.len > 255)
1117 goto error;
1118
1119 key = afs_request_key(orig_dvnode->volume->cell);
1120 if (IS_ERR(key)) {
1121 ret = PTR_ERR(key);
1122 goto error;
1123 }
1124
1125 ret = afs_vnode_rename(orig_dvnode, new_dvnode, key,
1126 old_dentry->d_name.name,
1127 new_dentry->d_name.name);
1128 if (ret < 0)
1129 goto rename_error;
1130 key_put(key);
1131 _leave(" = 0");
1132 return 0;
1133
1134rename_error:
1135 key_put(key);
1136error:
1137 d_drop(new_dentry);
1138 _leave(" = %d", ret);
1139 return ret;
1140}