diff options
Diffstat (limited to 'fs/coda/upcall.c')
-rw-r--r-- | fs/coda/upcall.c | 89 |
1 files changed, 55 insertions, 34 deletions
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index b8893ab6f9e6..c3563cab9758 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/errno.h> | 27 | #include <linux/errno.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
30 | #include <linux/mutex.h> | ||
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <linux/vmalloc.h> | 32 | #include <linux/vmalloc.h> |
32 | #include <linux/vfs.h> | 33 | #include <linux/vfs.h> |
@@ -606,7 +607,8 @@ static void coda_unblock_signals(sigset_t *old) | |||
606 | (r)->uc_opcode != CODA_RELEASE) || \ | 607 | (r)->uc_opcode != CODA_RELEASE) || \ |
607 | (r)->uc_flags & CODA_REQ_READ)) | 608 | (r)->uc_flags & CODA_REQ_READ)) |
608 | 609 | ||
609 | static inline void coda_waitfor_upcall(struct upc_req *req) | 610 | static inline void coda_waitfor_upcall(struct venus_comm *vcp, |
611 | struct upc_req *req) | ||
610 | { | 612 | { |
611 | DECLARE_WAITQUEUE(wait, current); | 613 | DECLARE_WAITQUEUE(wait, current); |
612 | unsigned long timeout = jiffies + coda_timeout * HZ; | 614 | unsigned long timeout = jiffies + coda_timeout * HZ; |
@@ -639,10 +641,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req) | |||
639 | break; | 641 | break; |
640 | } | 642 | } |
641 | 643 | ||
644 | mutex_unlock(&vcp->vc_mutex); | ||
642 | if (blocked) | 645 | if (blocked) |
643 | schedule_timeout(HZ); | 646 | schedule_timeout(HZ); |
644 | else | 647 | else |
645 | schedule(); | 648 | schedule(); |
649 | mutex_lock(&vcp->vc_mutex); | ||
646 | } | 650 | } |
647 | if (blocked) | 651 | if (blocked) |
648 | coda_unblock_signals(&old); | 652 | coda_unblock_signals(&old); |
@@ -667,18 +671,23 @@ static int coda_upcall(struct venus_comm *vcp, | |||
667 | { | 671 | { |
668 | union outputArgs *out; | 672 | union outputArgs *out; |
669 | union inputArgs *sig_inputArgs; | 673 | union inputArgs *sig_inputArgs; |
670 | struct upc_req *req, *sig_req; | 674 | struct upc_req *req = NULL, *sig_req; |
671 | int error = 0; | 675 | int error; |
676 | |||
677 | mutex_lock(&vcp->vc_mutex); | ||
672 | 678 | ||
673 | if (!vcp->vc_inuse) { | 679 | if (!vcp->vc_inuse) { |
674 | printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n"); | 680 | printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n"); |
675 | return -ENXIO; | 681 | error = -ENXIO; |
682 | goto exit; | ||
676 | } | 683 | } |
677 | 684 | ||
678 | /* Format the request message. */ | 685 | /* Format the request message. */ |
679 | req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); | 686 | req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); |
680 | if (!req) | 687 | if (!req) { |
681 | return -ENOMEM; | 688 | error = -ENOMEM; |
689 | goto exit; | ||
690 | } | ||
682 | 691 | ||
683 | req->uc_data = (void *)buffer; | 692 | req->uc_data = (void *)buffer; |
684 | req->uc_flags = 0; | 693 | req->uc_flags = 0; |
@@ -705,7 +714,7 @@ static int coda_upcall(struct venus_comm *vcp, | |||
705 | * ENODEV. */ | 714 | * ENODEV. */ |
706 | 715 | ||
707 | /* Go to sleep. Wake up on signals only after the timeout. */ | 716 | /* Go to sleep. Wake up on signals only after the timeout. */ |
708 | coda_waitfor_upcall(req); | 717 | coda_waitfor_upcall(vcp, req); |
709 | 718 | ||
710 | /* Op went through, interrupt or not... */ | 719 | /* Op went through, interrupt or not... */ |
711 | if (req->uc_flags & CODA_REQ_WRITE) { | 720 | if (req->uc_flags & CODA_REQ_WRITE) { |
@@ -759,6 +768,7 @@ static int coda_upcall(struct venus_comm *vcp, | |||
759 | 768 | ||
760 | exit: | 769 | exit: |
761 | kfree(req); | 770 | kfree(req); |
771 | mutex_unlock(&vcp->vc_mutex); | ||
762 | return error; | 772 | return error; |
763 | } | 773 | } |
764 | 774 | ||
@@ -796,21 +806,24 @@ exit: | |||
796 | * | 806 | * |
797 | * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ | 807 | * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ |
798 | 808 | ||
799 | int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) | 809 | int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out) |
800 | { | 810 | { |
801 | struct inode *inode = NULL; | 811 | struct inode *inode = NULL; |
802 | struct CodaFid *fid, *newfid; | 812 | struct CodaFid *fid = NULL, *newfid; |
813 | struct super_block *sb; | ||
803 | 814 | ||
804 | /* Handle invalidation requests. */ | 815 | /* Handle invalidation requests. */ |
805 | if ( !sb || !sb->s_root) | 816 | mutex_lock(&vcp->vc_mutex); |
806 | return 0; | 817 | sb = vcp->vc_sb; |
818 | if (!sb || !sb->s_root) | ||
819 | goto unlock_out; | ||
807 | 820 | ||
808 | switch (opcode) { | 821 | switch (opcode) { |
809 | case CODA_FLUSH: | 822 | case CODA_FLUSH: |
810 | coda_cache_clear_all(sb); | 823 | coda_cache_clear_all(sb); |
811 | shrink_dcache_sb(sb); | 824 | shrink_dcache_sb(sb); |
812 | if (sb->s_root->d_inode) | 825 | if (sb->s_root->d_inode) |
813 | coda_flag_inode(sb->s_root->d_inode, C_FLUSH); | 826 | coda_flag_inode(sb->s_root->d_inode, C_FLUSH); |
814 | break; | 827 | break; |
815 | 828 | ||
816 | case CODA_PURGEUSER: | 829 | case CODA_PURGEUSER: |
@@ -819,45 +832,53 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) | |||
819 | 832 | ||
820 | case CODA_ZAPDIR: | 833 | case CODA_ZAPDIR: |
821 | fid = &out->coda_zapdir.CodaFid; | 834 | fid = &out->coda_zapdir.CodaFid; |
822 | inode = coda_fid_to_inode(fid, sb); | ||
823 | if (inode) { | ||
824 | coda_flag_inode_children(inode, C_PURGE); | ||
825 | coda_flag_inode(inode, C_VATTR); | ||
826 | } | ||
827 | break; | 835 | break; |
828 | 836 | ||
829 | case CODA_ZAPFILE: | 837 | case CODA_ZAPFILE: |
830 | fid = &out->coda_zapfile.CodaFid; | 838 | fid = &out->coda_zapfile.CodaFid; |
831 | inode = coda_fid_to_inode(fid, sb); | ||
832 | if (inode) | ||
833 | coda_flag_inode(inode, C_VATTR); | ||
834 | break; | 839 | break; |
835 | 840 | ||
836 | case CODA_PURGEFID: | 841 | case CODA_PURGEFID: |
837 | fid = &out->coda_purgefid.CodaFid; | 842 | fid = &out->coda_purgefid.CodaFid; |
843 | break; | ||
844 | |||
845 | case CODA_REPLACE: | ||
846 | fid = &out->coda_replace.OldFid; | ||
847 | break; | ||
848 | } | ||
849 | if (fid) | ||
838 | inode = coda_fid_to_inode(fid, sb); | 850 | inode = coda_fid_to_inode(fid, sb); |
839 | if (inode) { | ||
840 | coda_flag_inode_children(inode, C_PURGE); | ||
841 | 851 | ||
842 | /* catch the dentries later if some are still busy */ | 852 | unlock_out: |
843 | coda_flag_inode(inode, C_PURGE); | 853 | mutex_unlock(&vcp->vc_mutex); |
844 | d_prune_aliases(inode); | ||
845 | 854 | ||
846 | } | 855 | if (!inode) |
856 | return 0; | ||
857 | |||
858 | switch (opcode) { | ||
859 | case CODA_ZAPDIR: | ||
860 | coda_flag_inode_children(inode, C_PURGE); | ||
861 | coda_flag_inode(inode, C_VATTR); | ||
862 | break; | ||
863 | |||
864 | case CODA_ZAPFILE: | ||
865 | coda_flag_inode(inode, C_VATTR); | ||
866 | break; | ||
867 | |||
868 | case CODA_PURGEFID: | ||
869 | coda_flag_inode_children(inode, C_PURGE); | ||
870 | |||
871 | /* catch the dentries later if some are still busy */ | ||
872 | coda_flag_inode(inode, C_PURGE); | ||
873 | d_prune_aliases(inode); | ||
847 | break; | 874 | break; |
848 | 875 | ||
849 | case CODA_REPLACE: | 876 | case CODA_REPLACE: |
850 | fid = &out->coda_replace.OldFid; | ||
851 | newfid = &out->coda_replace.NewFid; | 877 | newfid = &out->coda_replace.NewFid; |
852 | inode = coda_fid_to_inode(fid, sb); | 878 | coda_replace_fid(inode, fid, newfid); |
853 | if (inode) | ||
854 | coda_replace_fid(inode, fid, newfid); | ||
855 | break; | 879 | break; |
856 | } | 880 | } |
857 | 881 | iput(inode); | |
858 | if (inode) | ||
859 | iput(inode); | ||
860 | |||
861 | return 0; | 882 | return 0; |
862 | } | 883 | } |
863 | 884 | ||