aboutsummaryrefslogtreecommitdiffstats
path: root/fs/coda
diff options
context:
space:
mode:
Diffstat (limited to 'fs/coda')
-rw-r--r--fs/coda/Makefile2
-rw-r--r--fs/coda/cache.c26
-rw-r--r--fs/coda/cnode.c22
-rw-r--r--fs/coda/coda_cache.h22
-rw-r--r--fs/coda/coda_fs_i.h58
-rw-r--r--fs/coda/coda_linux.c3
-rw-r--r--fs/coda/coda_linux.h101
-rw-r--r--fs/coda/dir.c184
-rw-r--r--fs/coda/file.c34
-rw-r--r--fs/coda/inode.c82
-rw-r--r--fs/coda/pioctl.c29
-rw-r--r--fs/coda/psdev.c46
-rw-r--r--fs/coda/symlink.c7
-rw-r--r--fs/coda/sysctl.c17
-rw-r--r--fs/coda/upcall.c94
15 files changed, 441 insertions, 286 deletions
diff --git a/fs/coda/Makefile b/fs/coda/Makefile
index 6c22e61da397..1bab69a0d347 100644
--- a/fs/coda/Makefile
+++ b/fs/coda/Makefile
@@ -9,4 +9,4 @@ coda-objs := psdev.o cache.o cnode.o inode.o dir.o file.o upcall.o \
9 9
10# If you want debugging output, please uncomment the following line. 10# If you want debugging output, please uncomment the following line.
11 11
12# EXTRA_CFLAGS += -DDEBUG -DDEBUG_SMB_MALLOC=1 12# ccflags-y := -DDEBUG -DDEBUG_SMB_MALLOC=1
diff --git a/fs/coda/cache.c b/fs/coda/cache.c
index a5bf5771a22a..690157876184 100644
--- a/fs/coda/cache.c
+++ b/fs/coda/cache.c
@@ -17,12 +17,12 @@
17#include <linux/string.h> 17#include <linux/string.h>
18#include <linux/list.h> 18#include <linux/list.h>
19#include <linux/sched.h> 19#include <linux/sched.h>
20#include <linux/spinlock.h>
20 21
21#include <linux/coda.h> 22#include <linux/coda.h>
22#include <linux/coda_linux.h>
23#include <linux/coda_psdev.h> 23#include <linux/coda_psdev.h>
24#include <linux/coda_fs_i.h> 24#include "coda_linux.h"
25#include <linux/coda_cache.h> 25#include "coda_cache.h"
26 26
27static atomic_t permission_epoch = ATOMIC_INIT(0); 27static atomic_t permission_epoch = ATOMIC_INIT(0);
28 28
@@ -31,19 +31,23 @@ void coda_cache_enter(struct inode *inode, int mask)
31{ 31{
32 struct coda_inode_info *cii = ITOC(inode); 32 struct coda_inode_info *cii = ITOC(inode);
33 33
34 spin_lock(&cii->c_lock);
34 cii->c_cached_epoch = atomic_read(&permission_epoch); 35 cii->c_cached_epoch = atomic_read(&permission_epoch);
35 if (cii->c_uid != current_fsuid()) { 36 if (cii->c_uid != current_fsuid()) {
36 cii->c_uid = current_fsuid(); 37 cii->c_uid = current_fsuid();
37 cii->c_cached_perm = mask; 38 cii->c_cached_perm = mask;
38 } else 39 } else
39 cii->c_cached_perm |= mask; 40 cii->c_cached_perm |= mask;
41 spin_unlock(&cii->c_lock);
40} 42}
41 43
42/* remove cached acl from an inode */ 44/* remove cached acl from an inode */
43void coda_cache_clear_inode(struct inode *inode) 45void coda_cache_clear_inode(struct inode *inode)
44{ 46{
45 struct coda_inode_info *cii = ITOC(inode); 47 struct coda_inode_info *cii = ITOC(inode);
48 spin_lock(&cii->c_lock);
46 cii->c_cached_epoch = atomic_read(&permission_epoch) - 1; 49 cii->c_cached_epoch = atomic_read(&permission_epoch) - 1;
50 spin_unlock(&cii->c_lock);
47} 51}
48 52
49/* remove all acl caches */ 53/* remove all acl caches */
@@ -57,13 +61,15 @@ void coda_cache_clear_all(struct super_block *sb)
57int coda_cache_check(struct inode *inode, int mask) 61int coda_cache_check(struct inode *inode, int mask)
58{ 62{
59 struct coda_inode_info *cii = ITOC(inode); 63 struct coda_inode_info *cii = ITOC(inode);
60 int hit; 64 int hit;
61 65
62 hit = (mask & cii->c_cached_perm) == mask && 66 spin_lock(&cii->c_lock);
63 cii->c_uid == current_fsuid() && 67 hit = (mask & cii->c_cached_perm) == mask &&
64 cii->c_cached_epoch == atomic_read(&permission_epoch); 68 cii->c_uid == current_fsuid() &&
69 cii->c_cached_epoch == atomic_read(&permission_epoch);
70 spin_unlock(&cii->c_lock);
65 71
66 return hit; 72 return hit;
67} 73}
68 74
69 75
@@ -86,7 +92,7 @@ static void coda_flag_children(struct dentry *parent, int flag)
86 struct list_head *child; 92 struct list_head *child;
87 struct dentry *de; 93 struct dentry *de;
88 94
89 spin_lock(&dcache_lock); 95 spin_lock(&parent->d_lock);
90 list_for_each(child, &parent->d_subdirs) 96 list_for_each(child, &parent->d_subdirs)
91 { 97 {
92 de = list_entry(child, struct dentry, d_u.d_child); 98 de = list_entry(child, struct dentry, d_u.d_child);
@@ -95,7 +101,7 @@ static void coda_flag_children(struct dentry *parent, int flag)
95 continue; 101 continue;
96 coda_flag_inode(de->d_inode, flag); 102 coda_flag_inode(de->d_inode, flag);
97 } 103 }
98 spin_unlock(&dcache_lock); 104 spin_unlock(&parent->d_lock);
99 return; 105 return;
100} 106}
101 107
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c
index a7a780929eec..6475877b0763 100644
--- a/fs/coda/cnode.c
+++ b/fs/coda/cnode.c
@@ -7,9 +7,8 @@
7#include <linux/time.h> 7#include <linux/time.h>
8 8
9#include <linux/coda.h> 9#include <linux/coda.h>
10#include <linux/coda_linux.h>
11#include <linux/coda_fs_i.h>
12#include <linux/coda_psdev.h> 10#include <linux/coda_psdev.h>
11#include "coda_linux.h"
13 12
14static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) 13static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
15{ 14{
@@ -45,13 +44,15 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
45static int coda_test_inode(struct inode *inode, void *data) 44static int coda_test_inode(struct inode *inode, void *data)
46{ 45{
47 struct CodaFid *fid = (struct CodaFid *)data; 46 struct CodaFid *fid = (struct CodaFid *)data;
48 return coda_fideq(&(ITOC(inode)->c_fid), fid); 47 struct coda_inode_info *cii = ITOC(inode);
48 return coda_fideq(&cii->c_fid, fid);
49} 49}
50 50
51static int coda_set_inode(struct inode *inode, void *data) 51static int coda_set_inode(struct inode *inode, void *data)
52{ 52{
53 struct CodaFid *fid = (struct CodaFid *)data; 53 struct CodaFid *fid = (struct CodaFid *)data;
54 ITOC(inode)->c_fid = *fid; 54 struct coda_inode_info *cii = ITOC(inode);
55 cii->c_fid = *fid;
55 return 0; 56 return 0;
56} 57}
57 58
@@ -71,6 +72,7 @@ struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
71 cii = ITOC(inode); 72 cii = ITOC(inode);
72 /* we still need to set i_ino for things like stat(2) */ 73 /* we still need to set i_ino for things like stat(2) */
73 inode->i_ino = hash; 74 inode->i_ino = hash;
75 /* inode is locked and unique, no need to grab cii->c_lock */
74 cii->c_mapcount = 0; 76 cii->c_mapcount = 0;
75 unlock_new_inode(inode); 77 unlock_new_inode(inode);
76 } 78 }
@@ -107,14 +109,20 @@ int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_bloc
107} 109}
108 110
109 111
112/* Although we treat Coda file identifiers as immutable, there is one
113 * special case for files created during a disconnection where they may
114 * not be globally unique. When an identifier collision is detected we
115 * first try to flush the cached inode from the kernel and finally
116 * resort to renaming/rehashing in-place. Userspace remembers both old
117 * and new values of the identifier to handle any in-flight upcalls.
118 * The real solution is to use globally unique UUIDs as identifiers, but
119 * retrofitting the existing userspace code for this is non-trivial. */
110void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 120void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid,
111 struct CodaFid *newfid) 121 struct CodaFid *newfid)
112{ 122{
113 struct coda_inode_info *cii; 123 struct coda_inode_info *cii = ITOC(inode);
114 unsigned long hash = coda_f2i(newfid); 124 unsigned long hash = coda_f2i(newfid);
115 125
116 cii = ITOC(inode);
117
118 BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); 126 BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
119 127
120 /* replace fid and rehash inode */ 128 /* replace fid and rehash inode */
diff --git a/fs/coda/coda_cache.h b/fs/coda/coda_cache.h
new file mode 100644
index 000000000000..c910b5eb1ceb
--- /dev/null
+++ b/fs/coda/coda_cache.h
@@ -0,0 +1,22 @@
1/* Coda filesystem -- Linux Minicache
2 *
3 * Copyright (C) 1989 - 1997 Carnegie Mellon University
4 *
5 * Carnegie Mellon University encourages users of this software to
6 * contribute improvements to the Coda project. Contact Peter Braam
7 * <coda@cs.cmu.edu>
8 */
9
10#ifndef _CFSNC_HEADER_
11#define _CFSNC_HEADER_
12
13/* credential cache */
14void coda_cache_enter(struct inode *inode, int mask);
15void coda_cache_clear_inode(struct inode *);
16void coda_cache_clear_all(struct super_block *sb);
17int coda_cache_check(struct inode *inode, int mask);
18
19/* for downcalls and attributes and lookups */
20void coda_flag_inode_children(struct inode *inode, int flag);
21
22#endif /* _CFSNC_HEADER_ */
diff --git a/fs/coda/coda_fs_i.h b/fs/coda/coda_fs_i.h
new file mode 100644
index 000000000000..e35071b1de0e
--- /dev/null
+++ b/fs/coda/coda_fs_i.h
@@ -0,0 +1,58 @@
1/*
2 * coda_fs_i.h
3 *
4 * Copyright (C) 1998 Carnegie Mellon University
5 *
6 */
7
8#ifndef _LINUX_CODA_FS_I
9#define _LINUX_CODA_FS_I
10
11#include <linux/types.h>
12#include <linux/list.h>
13#include <linux/spinlock.h>
14#include <linux/coda.h>
15
16/*
17 * coda fs inode data
18 * c_lock protects accesses to c_flags, c_mapcount, c_cached_epoch, c_uid and
19 * c_cached_perm.
20 * vfs_inode is set only when the inode is created and never changes.
21 * c_fid is set when the inode is created and should be considered immutable.
22 */
23struct coda_inode_info {
24 struct CodaFid c_fid; /* Coda identifier */
25 u_short c_flags; /* flags (see below) */
26 unsigned int c_mapcount; /* nr of times this inode is mapped */
27 unsigned int c_cached_epoch; /* epoch for cached permissions */
28 vuid_t c_uid; /* fsuid for cached permissions */
29 unsigned int c_cached_perm; /* cached access permissions */
30 spinlock_t c_lock;
31 struct inode vfs_inode;
32};
33
34/*
35 * coda fs file private data
36 */
37#define CODA_MAGIC 0xC0DAC0DA
38struct coda_file_info {
39 int cfi_magic; /* magic number */
40 struct file *cfi_container; /* container file for this cnode */
41 unsigned int cfi_mapcount; /* nr of times this file is mapped */
42};
43
44#define CODA_FTOC(file) ((struct coda_file_info *)((file)->private_data))
45
46/* flags */
47#define C_VATTR 0x1 /* Validity of vattr in inode */
48#define C_FLUSH 0x2 /* used after a flush */
49#define C_DYING 0x4 /* from venus (which died) */
50#define C_PURGE 0x8
51
52int coda_cnode_make(struct inode **, struct CodaFid *, struct super_block *);
53struct inode *coda_iget(struct super_block *sb, struct CodaFid *fid, struct coda_vattr *attr);
54int coda_cnode_makectl(struct inode **inode, struct super_block *sb);
55struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb);
56void coda_replace_fid(struct inode *, struct CodaFid *, struct CodaFid *);
57
58#endif
diff --git a/fs/coda/coda_linux.c b/fs/coda/coda_linux.c
index bf4a3fd3c8e3..2bdbcc11b373 100644
--- a/fs/coda/coda_linux.c
+++ b/fs/coda/coda_linux.c
@@ -17,9 +17,8 @@
17#include <linux/string.h> 17#include <linux/string.h>
18 18
19#include <linux/coda.h> 19#include <linux/coda.h>
20#include <linux/coda_linux.h>
21#include <linux/coda_psdev.h> 20#include <linux/coda_psdev.h>
22#include <linux/coda_fs_i.h> 21#include "coda_linux.h"
23 22
24/* initialize the debugging variables */ 23/* initialize the debugging variables */
25int coda_fake_statfs; 24int coda_fake_statfs;
diff --git a/fs/coda/coda_linux.h b/fs/coda/coda_linux.h
new file mode 100644
index 000000000000..9b0c5323890b
--- /dev/null
+++ b/fs/coda/coda_linux.h
@@ -0,0 +1,101 @@
1/*
2 * Coda File System, Linux Kernel module
3 *
4 * Original version, adapted from cfs_mach.c, (C) Carnegie Mellon University
5 * Linux modifications (C) 1996, Peter J. Braam
6 * Rewritten for Linux 2.1 (C) 1997 Carnegie Mellon University
7 *
8 * Carnegie Mellon University encourages users of this software to
9 * contribute improvements to the Coda project.
10 */
11
12#ifndef _LINUX_CODA_FS
13#define _LINUX_CODA_FS
14
15#include <linux/kernel.h>
16#include <linux/param.h>
17#include <linux/mm.h>
18#include <linux/vmalloc.h>
19#include <linux/slab.h>
20#include <linux/wait.h>
21#include <linux/types.h>
22#include <linux/fs.h>
23#include "coda_fs_i.h"
24
25/* operations */
26extern const struct inode_operations coda_dir_inode_operations;
27extern const struct inode_operations coda_file_inode_operations;
28extern const struct inode_operations coda_ioctl_inode_operations;
29
30extern const struct dentry_operations coda_dentry_operations;
31
32extern const struct address_space_operations coda_file_aops;
33extern const struct address_space_operations coda_symlink_aops;
34
35extern const struct file_operations coda_dir_operations;
36extern const struct file_operations coda_file_operations;
37extern const struct file_operations coda_ioctl_operations;
38
39/* operations shared over more than one file */
40int coda_open(struct inode *i, struct file *f);
41int coda_release(struct inode *i, struct file *f);
42int coda_permission(struct inode *inode, int mask, unsigned int flags);
43int coda_revalidate_inode(struct dentry *);
44int coda_getattr(struct vfsmount *, struct dentry *, struct kstat *);
45int coda_setattr(struct dentry *, struct iattr *);
46
47/* this file: heloers */
48char *coda_f2s(struct CodaFid *f);
49int coda_isroot(struct inode *i);
50int coda_iscontrol(const char *name, size_t length);
51
52void coda_vattr_to_iattr(struct inode *, struct coda_vattr *);
53void coda_iattr_to_vattr(struct iattr *, struct coda_vattr *);
54unsigned short coda_flags_to_cflags(unsigned short);
55
56/* sysctl.h */
57void coda_sysctl_init(void);
58void coda_sysctl_clean(void);
59
60#define CODA_ALLOC(ptr, cast, size) do { \
61 if (size < PAGE_SIZE) \
62 ptr = kmalloc((unsigned long) size, GFP_KERNEL); \
63 else \
64 ptr = (cast)vmalloc((unsigned long) size); \
65 if (!ptr) \
66 printk("kernel malloc returns 0 at %s:%d\n", __FILE__, __LINE__); \
67 else memset( ptr, 0, size ); \
68} while (0)
69
70
71#define CODA_FREE(ptr,size) \
72 do { if (size < PAGE_SIZE) kfree((ptr)); else vfree((ptr)); } while (0)
73
74/* inode to cnode access functions */
75
76static inline struct coda_inode_info *ITOC(struct inode *inode)
77{
78 return list_entry(inode, struct coda_inode_info, vfs_inode);
79}
80
81static __inline__ struct CodaFid *coda_i2f(struct inode *inode)
82{
83 return &(ITOC(inode)->c_fid);
84}
85
86static __inline__ char *coda_i2s(struct inode *inode)
87{
88 return coda_f2s(&(ITOC(inode)->c_fid));
89}
90
91/* this will not zap the inode away */
92static __inline__ void coda_flag_inode(struct inode *inode, int flag)
93{
94 struct coda_inode_info *cii = ITOC(inode);
95
96 spin_lock(&cii->c_lock);
97 cii->c_flags |= flag;
98 spin_unlock(&cii->c_lock);
99}
100
101#endif
diff --git a/fs/coda/dir.c b/fs/coda/dir.c
index ccd98b0f2b0b..2b8dae4d121e 100644
--- a/fs/coda/dir.c
+++ b/fs/coda/dir.c
@@ -17,15 +17,15 @@
17#include <linux/stat.h> 17#include <linux/stat.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/smp_lock.h> 20#include <linux/spinlock.h>
21#include <linux/namei.h>
21 22
22#include <asm/uaccess.h> 23#include <asm/uaccess.h>
23 24
24#include <linux/coda.h> 25#include <linux/coda.h>
25#include <linux/coda_linux.h>
26#include <linux/coda_psdev.h> 26#include <linux/coda_psdev.h>
27#include <linux/coda_fs_i.h> 27#include "coda_linux.h"
28#include <linux/coda_cache.h> 28#include "coda_cache.h"
29 29
30#include "coda_int.h" 30#include "coda_int.h"
31 31
@@ -47,7 +47,7 @@ static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
47 47
48/* dentry ops */ 48/* dentry ops */
49static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd); 49static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
50static int coda_dentry_delete(struct dentry *); 50static int coda_dentry_delete(const struct dentry *);
51 51
52/* support routines */ 52/* support routines */
53static int coda_venus_readdir(struct file *coda_file, void *buf, 53static int coda_venus_readdir(struct file *coda_file, void *buf,
@@ -60,7 +60,7 @@ static int coda_return_EIO(void)
60} 60}
61#define CODA_EIO_ERROR ((void *) (coda_return_EIO)) 61#define CODA_EIO_ERROR ((void *) (coda_return_EIO))
62 62
63static const struct dentry_operations coda_dentry_operations = 63const struct dentry_operations coda_dentry_operations =
64{ 64{
65 .d_revalidate = coda_dentry_revalidate, 65 .d_revalidate = coda_dentry_revalidate,
66 .d_delete = coda_dentry_delete, 66 .d_delete = coda_dentry_delete,
@@ -116,21 +116,15 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struc
116 goto exit; 116 goto exit;
117 } 117 }
118 118
119 lock_kernel();
120
121 error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, 119 error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
122 &type, &resfid); 120 &type, &resfid);
123 if (!error) 121 if (!error)
124 error = coda_cnode_make(&inode, &resfid, dir->i_sb); 122 error = coda_cnode_make(&inode, &resfid, dir->i_sb);
125 123
126 unlock_kernel();
127
128 if (error && error != -ENOENT) 124 if (error && error != -ENOENT)
129 return ERR_PTR(error); 125 return ERR_PTR(error);
130 126
131exit: 127exit:
132 entry->d_op = &coda_dentry_operations;
133
134 if (inode && (type & CODA_NOCACHE)) 128 if (inode && (type & CODA_NOCACHE))
135 coda_flag_inode(inode, C_VATTR | C_PURGE); 129 coda_flag_inode(inode, C_VATTR | C_PURGE);
136 130
@@ -138,30 +132,29 @@ exit:
138} 132}
139 133
140 134
141int coda_permission(struct inode *inode, int mask) 135int coda_permission(struct inode *inode, int mask, unsigned int flags)
142{ 136{
143 int error = 0; 137 int error;
138
139 if (flags & IPERM_FLAG_RCU)
140 return -ECHILD;
144 141
145 mask &= MAY_READ | MAY_WRITE | MAY_EXEC; 142 mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
146 143
147 if (!mask) 144 if (!mask)
148 return 0; 145 return 0;
149 146
150 if ((mask & MAY_EXEC) && !execute_ok(inode)) 147 if ((mask & MAY_EXEC) && !execute_ok(inode))
151 return -EACCES; 148 return -EACCES;
152 149
153 lock_kernel();
154
155 if (coda_cache_check(inode, mask)) 150 if (coda_cache_check(inode, mask))
156 goto out; 151 return 0;
157 152
158 error = venus_access(inode->i_sb, coda_i2f(inode), mask); 153 error = venus_access(inode->i_sb, coda_i2f(inode), mask);
159 154
160 if (!error) 155 if (!error)
161 coda_cache_enter(inode, mask); 156 coda_cache_enter(inode, mask);
162 157
163 out:
164 unlock_kernel();
165 return error; 158 return error;
166} 159}
167 160
@@ -200,41 +193,34 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
200/* creation routines: create, mknod, mkdir, link, symlink */ 193/* creation routines: create, mknod, mkdir, link, symlink */
201static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd) 194static int coda_create(struct inode *dir, struct dentry *de, int mode, struct nameidata *nd)
202{ 195{
203 int error=0; 196 int error;
204 const char *name=de->d_name.name; 197 const char *name=de->d_name.name;
205 int length=de->d_name.len; 198 int length=de->d_name.len;
206 struct inode *inode; 199 struct inode *inode;
207 struct CodaFid newfid; 200 struct CodaFid newfid;
208 struct coda_vattr attrs; 201 struct coda_vattr attrs;
209 202
210 lock_kernel(); 203 if (coda_isroot(dir) && coda_iscontrol(name, length))
211
212 if (coda_isroot(dir) && coda_iscontrol(name, length)) {
213 unlock_kernel();
214 return -EPERM; 204 return -EPERM;
215 }
216 205
217 error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 206 error = venus_create(dir->i_sb, coda_i2f(dir), name, length,
218 0, mode, &newfid, &attrs); 207 0, mode, &newfid, &attrs);
219 208 if (error)
220 if ( error ) { 209 goto err_out;
221 unlock_kernel();
222 d_drop(de);
223 return error;
224 }
225 210
226 inode = coda_iget(dir->i_sb, &newfid, &attrs); 211 inode = coda_iget(dir->i_sb, &newfid, &attrs);
227 if ( IS_ERR(inode) ) { 212 if (IS_ERR(inode)) {
228 unlock_kernel(); 213 error = PTR_ERR(inode);
229 d_drop(de); 214 goto err_out;
230 return PTR_ERR(inode);
231 } 215 }
232 216
233 /* invalidate the directory cnode's attributes */ 217 /* invalidate the directory cnode's attributes */
234 coda_dir_update_mtime(dir); 218 coda_dir_update_mtime(dir);
235 unlock_kernel();
236 d_instantiate(de, inode); 219 d_instantiate(de, inode);
237 return 0; 220 return 0;
221err_out:
222 d_drop(de);
223 return error;
238} 224}
239 225
240static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) 226static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
@@ -246,36 +232,29 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode)
246 int error; 232 int error;
247 struct CodaFid newfid; 233 struct CodaFid newfid;
248 234
249 lock_kernel(); 235 if (coda_isroot(dir) && coda_iscontrol(name, len))
250
251 if (coda_isroot(dir) && coda_iscontrol(name, len)) {
252 unlock_kernel();
253 return -EPERM; 236 return -EPERM;
254 }
255 237
256 attrs.va_mode = mode; 238 attrs.va_mode = mode;
257 error = venus_mkdir(dir->i_sb, coda_i2f(dir), 239 error = venus_mkdir(dir->i_sb, coda_i2f(dir),
258 name, len, &newfid, &attrs); 240 name, len, &newfid, &attrs);
259 241 if (error)
260 if ( error ) { 242 goto err_out;
261 unlock_kernel();
262 d_drop(de);
263 return error;
264 }
265 243
266 inode = coda_iget(dir->i_sb, &newfid, &attrs); 244 inode = coda_iget(dir->i_sb, &newfid, &attrs);
267 if ( IS_ERR(inode) ) { 245 if (IS_ERR(inode)) {
268 unlock_kernel(); 246 error = PTR_ERR(inode);
269 d_drop(de); 247 goto err_out;
270 return PTR_ERR(inode);
271 } 248 }
272 249
273 /* invalidate the directory cnode's attributes */ 250 /* invalidate the directory cnode's attributes */
274 coda_dir_inc_nlink(dir); 251 coda_dir_inc_nlink(dir);
275 coda_dir_update_mtime(dir); 252 coda_dir_update_mtime(dir);
276 unlock_kernel();
277 d_instantiate(de, inode); 253 d_instantiate(de, inode);
278 return 0; 254 return 0;
255err_out:
256 d_drop(de);
257 return error;
279} 258}
280 259
281/* try to make de an entry in dir_inodde linked to source_de */ 260/* try to make de an entry in dir_inodde linked to source_de */
@@ -287,52 +266,38 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode,
287 int len = de->d_name.len; 266 int len = de->d_name.len;
288 int error; 267 int error;
289 268
290 lock_kernel(); 269 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
291
292 if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) {
293 unlock_kernel();
294 return -EPERM; 270 return -EPERM;
295 }
296 271
297 error = venus_link(dir_inode->i_sb, coda_i2f(inode), 272 error = venus_link(dir_inode->i_sb, coda_i2f(inode),
298 coda_i2f(dir_inode), (const char *)name, len); 273 coda_i2f(dir_inode), (const char *)name, len);
299
300 if (error) { 274 if (error) {
301 d_drop(de); 275 d_drop(de);
302 goto out; 276 return error;
303 } 277 }
304 278
305 coda_dir_update_mtime(dir_inode); 279 coda_dir_update_mtime(dir_inode);
306 atomic_inc(&inode->i_count); 280 ihold(inode);
307 d_instantiate(de, inode); 281 d_instantiate(de, inode);
308 inc_nlink(inode); 282 inc_nlink(inode);
309 283 return 0;
310out:
311 unlock_kernel();
312 return(error);
313} 284}
314 285
315 286
316static int coda_symlink(struct inode *dir_inode, struct dentry *de, 287static int coda_symlink(struct inode *dir_inode, struct dentry *de,
317 const char *symname) 288 const char *symname)
318{ 289{
319 const char *name = de->d_name.name; 290 const char *name = de->d_name.name;
320 int len = de->d_name.len; 291 int len = de->d_name.len;
321 int symlen; 292 int symlen;
322 int error = 0; 293 int error;
323
324 lock_kernel();
325 294
326 if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) { 295 if (coda_isroot(dir_inode) && coda_iscontrol(name, len))
327 unlock_kernel();
328 return -EPERM; 296 return -EPERM;
329 }
330 297
331 symlen = strlen(symname); 298 symlen = strlen(symname);
332 if ( symlen > CODA_MAXPATHLEN ) { 299 if (symlen > CODA_MAXPATHLEN)
333 unlock_kernel();
334 return -ENAMETOOLONG; 300 return -ENAMETOOLONG;
335 }
336 301
337 /* 302 /*
338 * This entry is now negative. Since we do not create 303 * This entry is now negative. Since we do not create
@@ -343,10 +308,9 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de,
343 symname, symlen); 308 symname, symlen);
344 309
345 /* mtime is no good anymore */ 310 /* mtime is no good anymore */
346 if ( !error ) 311 if (!error)
347 coda_dir_update_mtime(dir_inode); 312 coda_dir_update_mtime(dir_inode);
348 313
349 unlock_kernel();
350 return error; 314 return error;
351} 315}
352 316
@@ -357,17 +321,12 @@ static int coda_unlink(struct inode *dir, struct dentry *de)
357 const char *name = de->d_name.name; 321 const char *name = de->d_name.name;
358 int len = de->d_name.len; 322 int len = de->d_name.len;
359 323
360 lock_kernel();
361
362 error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); 324 error = venus_remove(dir->i_sb, coda_i2f(dir), name, len);
363 if ( error ) { 325 if (error)
364 unlock_kernel();
365 return error; 326 return error;
366 }
367 327
368 coda_dir_update_mtime(dir); 328 coda_dir_update_mtime(dir);
369 drop_nlink(de->d_inode); 329 drop_nlink(de->d_inode);
370 unlock_kernel();
371 return 0; 330 return 0;
372} 331}
373 332
@@ -377,8 +336,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
377 int len = de->d_name.len; 336 int len = de->d_name.len;
378 int error; 337 int error;
379 338
380 lock_kernel();
381
382 error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); 339 error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len);
383 if (!error) { 340 if (!error) {
384 /* VFS may delete the child */ 341 /* VFS may delete the child */
@@ -389,7 +346,6 @@ static int coda_rmdir(struct inode *dir, struct dentry *de)
389 coda_dir_drop_nlink(dir); 346 coda_dir_drop_nlink(dir);
390 coda_dir_update_mtime(dir); 347 coda_dir_update_mtime(dir);
391 } 348 }
392 unlock_kernel();
393 return error; 349 return error;
394} 350}
395 351
@@ -403,15 +359,12 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
403 int new_length = new_dentry->d_name.len; 359 int new_length = new_dentry->d_name.len;
404 int error; 360 int error;
405 361
406 lock_kernel();
407
408 error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), 362 error = venus_rename(old_dir->i_sb, coda_i2f(old_dir),
409 coda_i2f(new_dir), old_length, new_length, 363 coda_i2f(new_dir), old_length, new_length,
410 (const char *) old_name, (const char *)new_name); 364 (const char *) old_name, (const char *)new_name);
411 365 if (!error) {
412 if ( !error ) { 366 if (new_dentry->d_inode) {
413 if ( new_dentry->d_inode ) { 367 if (S_ISDIR(new_dentry->d_inode->i_mode)) {
414 if ( S_ISDIR(new_dentry->d_inode->i_mode) ) {
415 coda_dir_drop_nlink(old_dir); 368 coda_dir_drop_nlink(old_dir);
416 coda_dir_inc_nlink(new_dir); 369 coda_dir_inc_nlink(new_dir);
417 } 370 }
@@ -423,8 +376,6 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
423 coda_flag_inode(new_dir, C_VATTR); 376 coda_flag_inode(new_dir, C_VATTR);
424 } 377 }
425 } 378 }
426 unlock_kernel();
427
428 return error; 379 return error;
429} 380}
430 381
@@ -591,13 +542,14 @@ out:
591/* called when a cache lookup succeeds */ 542/* called when a cache lookup succeeds */
592static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) 543static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
593{ 544{
594 struct inode *inode = de->d_inode; 545 struct inode *inode;
595 struct coda_inode_info *cii; 546 struct coda_inode_info *cii;
596 547
597 if (!inode) 548 if (nd->flags & LOOKUP_RCU)
598 return 1; 549 return -ECHILD;
599 lock_kernel(); 550
600 if (coda_isroot(inode)) 551 inode = de->d_inode;
552 if (!inode || coda_isroot(inode))
601 goto out; 553 goto out;
602 if (is_bad_inode(inode)) 554 if (is_bad_inode(inode))
603 goto bad; 555 goto bad;
@@ -612,18 +564,17 @@ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
612 if (cii->c_flags & C_FLUSH) 564 if (cii->c_flags & C_FLUSH)
613 coda_flag_inode_children(inode, C_FLUSH); 565 coda_flag_inode_children(inode, C_FLUSH);
614 566
615 if (atomic_read(&de->d_count) > 1) 567 if (de->d_count > 1)
616 /* pretend it's valid, but don't change the flags */ 568 /* pretend it's valid, but don't change the flags */
617 goto out; 569 goto out;
618 570
619 /* clear the flags. */ 571 /* clear the flags. */
572 spin_lock(&cii->c_lock);
620 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); 573 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
621 574 spin_unlock(&cii->c_lock);
622bad: 575bad:
623 unlock_kernel();
624 return 0; 576 return 0;
625out: 577out:
626 unlock_kernel();
627 return 1; 578 return 1;
628} 579}
629 580
@@ -631,7 +582,7 @@ out:
631 * This is the callback from dput() when d_count is going to 0. 582 * This is the callback from dput() when d_count is going to 0.
632 * We use this to unhash dentries with bad inodes. 583 * We use this to unhash dentries with bad inodes.
633 */ 584 */
634static int coda_dentry_delete(struct dentry * dentry) 585static int coda_dentry_delete(const struct dentry * dentry)
635{ 586{
636 int flags; 587 int flags;
637 588
@@ -656,20 +607,19 @@ static int coda_dentry_delete(struct dentry * dentry)
656int coda_revalidate_inode(struct dentry *dentry) 607int coda_revalidate_inode(struct dentry *dentry)
657{ 608{
658 struct coda_vattr attr; 609 struct coda_vattr attr;
659 int error = 0; 610 int error;
660 int old_mode; 611 int old_mode;
661 ino_t old_ino; 612 ino_t old_ino;
662 struct inode *inode = dentry->d_inode; 613 struct inode *inode = dentry->d_inode;
663 struct coda_inode_info *cii = ITOC(inode); 614 struct coda_inode_info *cii = ITOC(inode);
664 615
665 lock_kernel(); 616 if (!cii->c_flags)
666 if ( !cii->c_flags ) 617 return 0;
667 goto ok;
668 618
669 if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { 619 if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) {
670 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); 620 error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr);
671 if ( error ) 621 if (error)
672 goto return_bad; 622 return -EIO;
673 623
674 /* this inode may be lost if: 624 /* this inode may be lost if:
675 - it's ino changed 625 - it's ino changed
@@ -688,17 +638,13 @@ int coda_revalidate_inode(struct dentry *dentry)
688 /* the following can happen when a local fid is replaced 638 /* the following can happen when a local fid is replaced
689 with a global one, here we lose and declare the inode bad */ 639 with a global one, here we lose and declare the inode bad */
690 if (inode->i_ino != old_ino) 640 if (inode->i_ino != old_ino)
691 goto return_bad; 641 return -EIO;
692 642
693 coda_flag_inode_children(inode, C_FLUSH); 643 coda_flag_inode_children(inode, C_FLUSH);
644
645 spin_lock(&cii->c_lock);
694 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); 646 cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH);
647 spin_unlock(&cii->c_lock);
695 } 648 }
696
697ok:
698 unlock_kernel();
699 return 0; 649 return 0;
700
701return_bad:
702 unlock_kernel();
703 return -EIO;
704} 650}
diff --git a/fs/coda/file.c b/fs/coda/file.c
index ad3cd2abeeb4..0433057be330 100644
--- a/fs/coda/file.c
+++ b/fs/coda/file.c
@@ -15,16 +15,15 @@
15#include <linux/stat.h> 15#include <linux/stat.h>
16#include <linux/cred.h> 16#include <linux/cred.h>
17#include <linux/errno.h> 17#include <linux/errno.h>
18#include <linux/smp_lock.h> 18#include <linux/spinlock.h>
19#include <linux/string.h> 19#include <linux/string.h>
20#include <linux/slab.h> 20#include <linux/slab.h>
21#include <asm/uaccess.h> 21#include <asm/uaccess.h>
22 22
23#include <linux/coda.h> 23#include <linux/coda.h>
24#include <linux/coda_linux.h>
25#include <linux/coda_fs_i.h>
26#include <linux/coda_psdev.h> 24#include <linux/coda_psdev.h>
27 25
26#include "coda_linux.h"
28#include "coda_int.h" 27#include "coda_int.h"
29 28
30static ssize_t 29static ssize_t
@@ -109,19 +108,24 @@ coda_file_mmap(struct file *coda_file, struct vm_area_struct *vma)
109 108
110 coda_inode = coda_file->f_path.dentry->d_inode; 109 coda_inode = coda_file->f_path.dentry->d_inode;
111 host_inode = host_file->f_path.dentry->d_inode; 110 host_inode = host_file->f_path.dentry->d_inode;
111
112 cii = ITOC(coda_inode);
113 spin_lock(&cii->c_lock);
112 coda_file->f_mapping = host_file->f_mapping; 114 coda_file->f_mapping = host_file->f_mapping;
113 if (coda_inode->i_mapping == &coda_inode->i_data) 115 if (coda_inode->i_mapping == &coda_inode->i_data)
114 coda_inode->i_mapping = host_inode->i_mapping; 116 coda_inode->i_mapping = host_inode->i_mapping;
115 117
116 /* only allow additional mmaps as long as userspace isn't changing 118 /* only allow additional mmaps as long as userspace isn't changing
117 * the container file on us! */ 119 * the container file on us! */
118 else if (coda_inode->i_mapping != host_inode->i_mapping) 120 else if (coda_inode->i_mapping != host_inode->i_mapping) {
121 spin_unlock(&cii->c_lock);
119 return -EBUSY; 122 return -EBUSY;
123 }
120 124
121 /* keep track of how often the coda_inode/host_file has been mmapped */ 125 /* keep track of how often the coda_inode/host_file has been mmapped */
122 cii = ITOC(coda_inode);
123 cii->c_mapcount++; 126 cii->c_mapcount++;
124 cfi->cfi_mapcount++; 127 cfi->cfi_mapcount++;
128 spin_unlock(&cii->c_lock);
125 129
126 return host_file->f_op->mmap(host_file, vma); 130 return host_file->f_op->mmap(host_file, vma);
127} 131}
@@ -138,8 +142,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
138 if (!cfi) 142 if (!cfi)
139 return -ENOMEM; 143 return -ENOMEM;
140 144
141 lock_kernel();
142
143 error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags, 145 error = venus_open(coda_inode->i_sb, coda_i2f(coda_inode), coda_flags,
144 &host_file); 146 &host_file);
145 if (!host_file) 147 if (!host_file)
@@ -147,7 +149,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
147 149
148 if (error) { 150 if (error) {
149 kfree(cfi); 151 kfree(cfi);
150 unlock_kernel();
151 return error; 152 return error;
152 } 153 }
153 154
@@ -159,8 +160,6 @@ int coda_open(struct inode *coda_inode, struct file *coda_file)
159 160
160 BUG_ON(coda_file->private_data != NULL); 161 BUG_ON(coda_file->private_data != NULL);
161 coda_file->private_data = cfi; 162 coda_file->private_data = cfi;
162
163 unlock_kernel();
164 return 0; 163 return 0;
165} 164}
166 165
@@ -171,9 +170,7 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
171 struct coda_file_info *cfi; 170 struct coda_file_info *cfi;
172 struct coda_inode_info *cii; 171 struct coda_inode_info *cii;
173 struct inode *host_inode; 172 struct inode *host_inode;
174 int err = 0; 173 int err;
175
176 lock_kernel();
177 174
178 cfi = CODA_FTOC(coda_file); 175 cfi = CODA_FTOC(coda_file);
179 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC); 176 BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
@@ -185,18 +182,18 @@ int coda_release(struct inode *coda_inode, struct file *coda_file)
185 cii = ITOC(coda_inode); 182 cii = ITOC(coda_inode);
186 183
187 /* did we mmap this file? */ 184 /* did we mmap this file? */
185 spin_lock(&cii->c_lock);
188 if (coda_inode->i_mapping == &host_inode->i_data) { 186 if (coda_inode->i_mapping == &host_inode->i_data) {
189 cii->c_mapcount -= cfi->cfi_mapcount; 187 cii->c_mapcount -= cfi->cfi_mapcount;
190 if (!cii->c_mapcount) 188 if (!cii->c_mapcount)
191 coda_inode->i_mapping = &coda_inode->i_data; 189 coda_inode->i_mapping = &coda_inode->i_data;
192 } 190 }
191 spin_unlock(&cii->c_lock);
193 192
194 fput(cfi->cfi_container); 193 fput(cfi->cfi_container);
195 kfree(coda_file->private_data); 194 kfree(coda_file->private_data);
196 coda_file->private_data = NULL; 195 coda_file->private_data = NULL;
197 196
198 unlock_kernel();
199
200 /* VFS fput ignores the return value from file_operations->release, so 197 /* VFS fput ignores the return value from file_operations->release, so
201 * there is no use returning an error here */ 198 * there is no use returning an error here */
202 return 0; 199 return 0;
@@ -207,7 +204,7 @@ int coda_fsync(struct file *coda_file, int datasync)
207 struct file *host_file; 204 struct file *host_file;
208 struct inode *coda_inode = coda_file->f_path.dentry->d_inode; 205 struct inode *coda_inode = coda_file->f_path.dentry->d_inode;
209 struct coda_file_info *cfi; 206 struct coda_file_info *cfi;
210 int err = 0; 207 int err;
211 208
212 if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) || 209 if (!(S_ISREG(coda_inode->i_mode) || S_ISDIR(coda_inode->i_mode) ||
213 S_ISLNK(coda_inode->i_mode))) 210 S_ISLNK(coda_inode->i_mode)))
@@ -218,11 +215,8 @@ int coda_fsync(struct file *coda_file, int datasync)
218 host_file = cfi->cfi_container; 215 host_file = cfi->cfi_container;
219 216
220 err = vfs_fsync(host_file, datasync); 217 err = vfs_fsync(host_file, datasync);
221 if ( !err && !datasync ) { 218 if (!err && !datasync)
222 lock_kernel();
223 err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode)); 219 err = venus_fsync(coda_inode->i_sb, coda_i2f(coda_inode));
224 unlock_kernel();
225 }
226 220
227 return err; 221 return err;
228} 222}
diff --git a/fs/coda/inode.c b/fs/coda/inode.c
index 6526e6f21ecf..871b27715465 100644
--- a/fs/coda/inode.c
+++ b/fs/coda/inode.c
@@ -15,7 +15,8 @@
15#include <linux/stat.h> 15#include <linux/stat.h>
16#include <linux/errno.h> 16#include <linux/errno.h>
17#include <linux/unistd.h> 17#include <linux/unistd.h>
18#include <linux/smp_lock.h> 18#include <linux/mutex.h>
19#include <linux/spinlock.h>
19#include <linux/file.h> 20#include <linux/file.h>
20#include <linux/vfs.h> 21#include <linux/vfs.h>
21#include <linux/slab.h> 22#include <linux/slab.h>
@@ -27,10 +28,9 @@
27#include <linux/vmalloc.h> 28#include <linux/vmalloc.h>
28 29
29#include <linux/coda.h> 30#include <linux/coda.h>
30#include <linux/coda_linux.h>
31#include <linux/coda_psdev.h> 31#include <linux/coda_psdev.h>
32#include <linux/coda_fs_i.h> 32#include "coda_linux.h"
33#include <linux/coda_cache.h> 33#include "coda_cache.h"
34 34
35#include "coda_int.h" 35#include "coda_int.h"
36 36
@@ -44,21 +44,29 @@ static struct kmem_cache * coda_inode_cachep;
44static struct inode *coda_alloc_inode(struct super_block *sb) 44static struct inode *coda_alloc_inode(struct super_block *sb)
45{ 45{
46 struct coda_inode_info *ei; 46 struct coda_inode_info *ei;
47 ei = (struct coda_inode_info *)kmem_cache_alloc(coda_inode_cachep, GFP_KERNEL); 47 ei = kmem_cache_alloc(coda_inode_cachep, GFP_KERNEL);
48 if (!ei) 48 if (!ei)
49 return NULL; 49 return NULL;
50 memset(&ei->c_fid, 0, sizeof(struct CodaFid)); 50 memset(&ei->c_fid, 0, sizeof(struct CodaFid));
51 ei->c_flags = 0; 51 ei->c_flags = 0;
52 ei->c_uid = 0; 52 ei->c_uid = 0;
53 ei->c_cached_perm = 0; 53 ei->c_cached_perm = 0;
54 spin_lock_init(&ei->c_lock);
54 return &ei->vfs_inode; 55 return &ei->vfs_inode;
55} 56}
56 57
57static void coda_destroy_inode(struct inode *inode) 58static void coda_i_callback(struct rcu_head *head)
58{ 59{
60 struct inode *inode = container_of(head, struct inode, i_rcu);
61 INIT_LIST_HEAD(&inode->i_dentry);
59 kmem_cache_free(coda_inode_cachep, ITOC(inode)); 62 kmem_cache_free(coda_inode_cachep, ITOC(inode));
60} 63}
61 64
65static void coda_destroy_inode(struct inode *inode)
66{
67 call_rcu(&inode->i_rcu, coda_i_callback);
68}
69
62static void init_once(void *foo) 70static void init_once(void *foo)
63{ 71{
64 struct coda_inode_info *ei = (struct coda_inode_info *) foo; 72 struct coda_inode_info *ei = (struct coda_inode_info *) foo;
@@ -143,7 +151,7 @@ static int get_device_index(struct coda_mount_data *data)
143static int coda_fill_super(struct super_block *sb, void *data, int silent) 151static int coda_fill_super(struct super_block *sb, void *data, int silent)
144{ 152{
145 struct inode *root = NULL; 153 struct inode *root = NULL;
146 struct venus_comm *vc = NULL; 154 struct venus_comm *vc;
147 struct CodaFid fid; 155 struct CodaFid fid;
148 int error; 156 int error;
149 int idx; 157 int idx;
@@ -157,21 +165,26 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
157 printk(KERN_INFO "coda_read_super: device index: %i\n", idx); 165 printk(KERN_INFO "coda_read_super: device index: %i\n", idx);
158 166
159 vc = &coda_comms[idx]; 167 vc = &coda_comms[idx];
168 mutex_lock(&vc->vc_mutex);
169
160 if (!vc->vc_inuse) { 170 if (!vc->vc_inuse) {
161 printk("coda_read_super: No pseudo device\n"); 171 printk("coda_read_super: No pseudo device\n");
162 return -EINVAL; 172 error = -EINVAL;
173 goto unlock_out;
163 } 174 }
164 175
165 if ( vc->vc_sb ) { 176 if (vc->vc_sb) {
166 printk("coda_read_super: Device already mounted\n"); 177 printk("coda_read_super: Device already mounted\n");
167 return -EBUSY; 178 error = -EBUSY;
179 goto unlock_out;
168 } 180 }
169 181
170 error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY); 182 error = bdi_setup_and_register(&vc->bdi, "coda", BDI_CAP_MAP_COPY);
171 if (error) 183 if (error)
172 goto bdi_err; 184 goto unlock_out;
173 185
174 vc->vc_sb = sb; 186 vc->vc_sb = sb;
187 mutex_unlock(&vc->vc_mutex);
175 188
176 sb->s_fs_info = vc; 189 sb->s_fs_info = vc;
177 sb->s_flags |= MS_NOATIME; 190 sb->s_flags |= MS_NOATIME;
@@ -179,6 +192,7 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
179 sb->s_blocksize_bits = 12; 192 sb->s_blocksize_bits = 12;
180 sb->s_magic = CODA_SUPER_MAGIC; 193 sb->s_magic = CODA_SUPER_MAGIC;
181 sb->s_op = &coda_super_operations; 194 sb->s_op = &coda_super_operations;
195 sb->s_d_op = &coda_dentry_operations;
182 sb->s_bdi = &vc->bdi; 196 sb->s_bdi = &vc->bdi;
183 197
184 /* get root fid from Venus: this needs the root inode */ 198 /* get root fid from Venus: this needs the root inode */
@@ -200,26 +214,33 @@ static int coda_fill_super(struct super_block *sb, void *data, int silent)
200 printk("coda_read_super: rootinode is %ld dev %s\n", 214 printk("coda_read_super: rootinode is %ld dev %s\n",
201 root->i_ino, root->i_sb->s_id); 215 root->i_ino, root->i_sb->s_id);
202 sb->s_root = d_alloc_root(root); 216 sb->s_root = d_alloc_root(root);
203 if (!sb->s_root) 217 if (!sb->s_root) {
218 error = -EINVAL;
204 goto error; 219 goto error;
205 return 0; 220 }
221 return 0;
206 222
207 error: 223error:
208 bdi_destroy(&vc->bdi);
209 bdi_err:
210 if (root) 224 if (root)
211 iput(root); 225 iput(root);
212 if (vc)
213 vc->vc_sb = NULL;
214 226
215 return -EINVAL; 227 mutex_lock(&vc->vc_mutex);
228 bdi_destroy(&vc->bdi);
229 vc->vc_sb = NULL;
230 sb->s_fs_info = NULL;
231unlock_out:
232 mutex_unlock(&vc->vc_mutex);
233 return error;
216} 234}
217 235
218static void coda_put_super(struct super_block *sb) 236static void coda_put_super(struct super_block *sb)
219{ 237{
220 bdi_destroy(&coda_vcp(sb)->bdi); 238 struct venus_comm *vcp = coda_vcp(sb);
221 coda_vcp(sb)->vc_sb = NULL; 239 mutex_lock(&vcp->vc_mutex);
240 bdi_destroy(&vcp->bdi);
241 vcp->vc_sb = NULL;
222 sb->s_fs_info = NULL; 242 sb->s_fs_info = NULL;
243 mutex_unlock(&vcp->vc_mutex);
223 244
224 printk("Coda: Bye bye.\n"); 245 printk("Coda: Bye bye.\n");
225} 246}
@@ -245,8 +266,6 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
245 struct coda_vattr vattr; 266 struct coda_vattr vattr;
246 int error; 267 int error;
247 268
248 lock_kernel();
249
250 memset(&vattr, 0, sizeof(vattr)); 269 memset(&vattr, 0, sizeof(vattr));
251 270
252 inode->i_ctime = CURRENT_TIME_SEC; 271 inode->i_ctime = CURRENT_TIME_SEC;
@@ -256,13 +275,10 @@ int coda_setattr(struct dentry *de, struct iattr *iattr)
256 /* Venus is responsible for truncating the container-file!!! */ 275 /* Venus is responsible for truncating the container-file!!! */
257 error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr); 276 error = venus_setattr(inode->i_sb, coda_i2f(inode), &vattr);
258 277
259 if ( !error ) { 278 if (!error) {
260 coda_vattr_to_iattr(inode, &vattr); 279 coda_vattr_to_iattr(inode, &vattr);
261 coda_cache_clear_inode(inode); 280 coda_cache_clear_inode(inode);
262 } 281 }
263
264 unlock_kernel();
265
266 return error; 282 return error;
267} 283}
268 284
@@ -276,12 +292,8 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
276{ 292{
277 int error; 293 int error;
278 294
279 lock_kernel();
280
281 error = venus_statfs(dentry, buf); 295 error = venus_statfs(dentry, buf);
282 296
283 unlock_kernel();
284
285 if (error) { 297 if (error) {
286 /* fake something like AFS does */ 298 /* fake something like AFS does */
287 buf->f_blocks = 9000000; 299 buf->f_blocks = 9000000;
@@ -301,16 +313,16 @@ static int coda_statfs(struct dentry *dentry, struct kstatfs *buf)
301 313
302/* init_coda: used by filesystems.c to register coda */ 314/* init_coda: used by filesystems.c to register coda */
303 315
304static int coda_get_sb(struct file_system_type *fs_type, 316static struct dentry *coda_mount(struct file_system_type *fs_type,
305 int flags, const char *dev_name, void *data, struct vfsmount *mnt) 317 int flags, const char *dev_name, void *data)
306{ 318{
307 return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt); 319 return mount_nodev(fs_type, flags, data, coda_fill_super);
308} 320}
309 321
310struct file_system_type coda_fs_type = { 322struct file_system_type coda_fs_type = {
311 .owner = THIS_MODULE, 323 .owner = THIS_MODULE,
312 .name = "coda", 324 .name = "coda",
313 .get_sb = coda_get_sb, 325 .mount = coda_mount,
314 .kill_sb = kill_anon_super, 326 .kill_sb = kill_anon_super,
315 .fs_flags = FS_BINARY_MOUNTDATA, 327 .fs_flags = FS_BINARY_MOUNTDATA,
316}; 328};
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c
index ca25d96d45c9..cb140ef293e4 100644
--- a/fs/coda/pioctl.c
+++ b/fs/coda/pioctl.c
@@ -19,14 +19,12 @@
19#include <asm/uaccess.h> 19#include <asm/uaccess.h>
20 20
21#include <linux/coda.h> 21#include <linux/coda.h>
22#include <linux/coda_linux.h>
23#include <linux/coda_fs_i.h>
24#include <linux/coda_psdev.h> 22#include <linux/coda_psdev.h>
25 23
26#include <linux/smp_lock.h> 24#include "coda_linux.h"
27 25
28/* pioctl ops */ 26/* pioctl ops */
29static int coda_ioctl_permission(struct inode *inode, int mask); 27static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags);
30static long coda_pioctl(struct file *filp, unsigned int cmd, 28static long coda_pioctl(struct file *filp, unsigned int cmd,
31 unsigned long user_data); 29 unsigned long user_data);
32 30
@@ -39,10 +37,11 @@ const struct inode_operations coda_ioctl_inode_operations = {
39const struct file_operations coda_ioctl_operations = { 37const struct file_operations coda_ioctl_operations = {
40 .owner = THIS_MODULE, 38 .owner = THIS_MODULE,
41 .unlocked_ioctl = coda_pioctl, 39 .unlocked_ioctl = coda_pioctl,
40 .llseek = noop_llseek,
42}; 41};
43 42
44/* the coda pioctl inode ops */ 43/* the coda pioctl inode ops */
45static int coda_ioctl_permission(struct inode *inode, int mask) 44static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags)
46{ 45{
47 return (mask & MAY_EXEC) ? -EACCES : 0; 46 return (mask & MAY_EXEC) ? -EACCES : 0;
48} 47}
@@ -57,13 +56,9 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
57 struct inode *target_inode = NULL; 56 struct inode *target_inode = NULL;
58 struct coda_inode_info *cnp; 57 struct coda_inode_info *cnp;
59 58
60 lock_kernel();
61
62 /* get the Pioctl data arguments from user space */ 59 /* get the Pioctl data arguments from user space */
63 if (copy_from_user(&data, (void __user *)user_data, sizeof(data))) { 60 if (copy_from_user(&data, (void __user *)user_data, sizeof(data)))
64 error = -EINVAL; 61 return -EINVAL;
65 goto out;
66 }
67 62
68 /* 63 /*
69 * Look up the pathname. Note that the pathname is in 64 * Look up the pathname. Note that the pathname is in
@@ -75,13 +70,12 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
75 error = user_lpath(data.path, &path); 70 error = user_lpath(data.path, &path);
76 71
77 if (error) 72 if (error)
78 goto out; 73 return error;
79 else 74
80 target_inode = path.dentry->d_inode; 75 target_inode = path.dentry->d_inode;
81 76
82 /* return if it is not a Coda inode */ 77 /* return if it is not a Coda inode */
83 if (target_inode->i_sb != inode->i_sb) { 78 if (target_inode->i_sb != inode->i_sb) {
84 path_put(&path);
85 error = -EINVAL; 79 error = -EINVAL;
86 goto out; 80 goto out;
87 } 81 }
@@ -90,10 +84,7 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
90 cnp = ITOC(target_inode); 84 cnp = ITOC(target_inode);
91 85
92 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data); 86 error = venus_pioctl(inode->i_sb, &(cnp->c_fid), cmd, &data);
93
94 path_put(&path);
95
96out: 87out:
97 unlock_kernel(); 88 path_put(&path);
98 return error; 89 return error;
99} 90}
diff --git a/fs/coda/psdev.c b/fs/coda/psdev.c
index 116af7546cf0..8f616e0e252c 100644
--- a/fs/coda/psdev.c
+++ b/fs/coda/psdev.c
@@ -35,7 +35,7 @@
35#include <linux/poll.h> 35#include <linux/poll.h>
36#include <linux/init.h> 36#include <linux/init.h>
37#include <linux/list.h> 37#include <linux/list.h>
38#include <linux/smp_lock.h> 38#include <linux/mutex.h>
39#include <linux/device.h> 39#include <linux/device.h>
40#include <asm/io.h> 40#include <asm/io.h>
41#include <asm/system.h> 41#include <asm/system.h>
@@ -43,10 +43,10 @@
43#include <asm/uaccess.h> 43#include <asm/uaccess.h>
44 44
45#include <linux/coda.h> 45#include <linux/coda.h>
46#include <linux/coda_linux.h>
47#include <linux/coda_fs_i.h>
48#include <linux/coda_psdev.h> 46#include <linux/coda_psdev.h>
49 47
48#include "coda_linux.h"
49
50#include "coda_int.h" 50#include "coda_int.h"
51 51
52/* statistics */ 52/* statistics */
@@ -67,8 +67,10 @@ static unsigned int coda_psdev_poll(struct file *file, poll_table * wait)
67 unsigned int mask = POLLOUT | POLLWRNORM; 67 unsigned int mask = POLLOUT | POLLWRNORM;
68 68
69 poll_wait(file, &vcp->vc_waitq, wait); 69 poll_wait(file, &vcp->vc_waitq, wait);
70 mutex_lock(&vcp->vc_mutex);
70 if (!list_empty(&vcp->vc_pending)) 71 if (!list_empty(&vcp->vc_pending))
71 mask |= POLLIN | POLLRDNORM; 72 mask |= POLLIN | POLLRDNORM;
73 mutex_unlock(&vcp->vc_mutex);
72 74
73 return mask; 75 return mask;
74} 76}
@@ -108,16 +110,9 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
108 return -EFAULT; 110 return -EFAULT;
109 111
110 if (DOWNCALL(hdr.opcode)) { 112 if (DOWNCALL(hdr.opcode)) {
111 struct super_block *sb = NULL; 113 union outputArgs *dcbuf;
112 union outputArgs *dcbuf;
113 int size = sizeof(*dcbuf); 114 int size = sizeof(*dcbuf);
114 115
115 sb = vcp->vc_sb;
116 if ( !sb ) {
117 count = nbytes;
118 goto out;
119 }
120
121 if ( nbytes < sizeof(struct coda_out_hdr) ) { 116 if ( nbytes < sizeof(struct coda_out_hdr) ) {
122 printk("coda_downcall opc %d uniq %d, not enough!\n", 117 printk("coda_downcall opc %d uniq %d, not enough!\n",
123 hdr.opcode, hdr.unique); 118 hdr.opcode, hdr.unique);
@@ -137,9 +132,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
137 } 132 }
138 133
139 /* what downcall errors does Venus handle ? */ 134 /* what downcall errors does Venus handle ? */
140 lock_kernel(); 135 error = coda_downcall(vcp, hdr.opcode, dcbuf);
141 error = coda_downcall(hdr.opcode, dcbuf, sb);
142 unlock_kernel();
143 136
144 CODA_FREE(dcbuf, nbytes); 137 CODA_FREE(dcbuf, nbytes);
145 if (error) { 138 if (error) {
@@ -152,7 +145,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
152 } 145 }
153 146
154 /* Look for the message on the processing queue. */ 147 /* Look for the message on the processing queue. */
155 lock_kernel(); 148 mutex_lock(&vcp->vc_mutex);
156 list_for_each(lh, &vcp->vc_processing) { 149 list_for_each(lh, &vcp->vc_processing) {
157 tmp = list_entry(lh, struct upc_req , uc_chain); 150 tmp = list_entry(lh, struct upc_req , uc_chain);
158 if (tmp->uc_unique == hdr.unique) { 151 if (tmp->uc_unique == hdr.unique) {
@@ -161,7 +154,7 @@ static ssize_t coda_psdev_write(struct file *file, const char __user *buf,
161 break; 154 break;
162 } 155 }
163 } 156 }
164 unlock_kernel(); 157 mutex_unlock(&vcp->vc_mutex);
165 158
166 if (!req) { 159 if (!req) {
167 printk("psdev_write: msg (%d, %d) not found\n", 160 printk("psdev_write: msg (%d, %d) not found\n",
@@ -216,7 +209,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
216 if (nbytes == 0) 209 if (nbytes == 0)
217 return 0; 210 return 0;
218 211
219 lock_kernel(); 212 mutex_lock(&vcp->vc_mutex);
220 213
221 add_wait_queue(&vcp->vc_waitq, &wait); 214 add_wait_queue(&vcp->vc_waitq, &wait);
222 set_current_state(TASK_INTERRUPTIBLE); 215 set_current_state(TASK_INTERRUPTIBLE);
@@ -230,7 +223,9 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
230 retval = -ERESTARTSYS; 223 retval = -ERESTARTSYS;
231 break; 224 break;
232 } 225 }
226 mutex_unlock(&vcp->vc_mutex);
233 schedule(); 227 schedule();
228 mutex_lock(&vcp->vc_mutex);
234 } 229 }
235 230
236 set_current_state(TASK_RUNNING); 231 set_current_state(TASK_RUNNING);
@@ -263,7 +258,7 @@ static ssize_t coda_psdev_read(struct file * file, char __user * buf,
263 CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr)); 258 CODA_FREE(req->uc_data, sizeof(struct coda_in_hdr));
264 kfree(req); 259 kfree(req);
265out: 260out:
266 unlock_kernel(); 261 mutex_unlock(&vcp->vc_mutex);
267 return (count ? count : retval); 262 return (count ? count : retval);
268} 263}
269 264
@@ -276,10 +271,10 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
276 if (idx < 0 || idx >= MAX_CODADEVS) 271 if (idx < 0 || idx >= MAX_CODADEVS)
277 return -ENODEV; 272 return -ENODEV;
278 273
279 lock_kernel();
280
281 err = -EBUSY; 274 err = -EBUSY;
282 vcp = &coda_comms[idx]; 275 vcp = &coda_comms[idx];
276 mutex_lock(&vcp->vc_mutex);
277
283 if (!vcp->vc_inuse) { 278 if (!vcp->vc_inuse) {
284 vcp->vc_inuse++; 279 vcp->vc_inuse++;
285 280
@@ -293,7 +288,7 @@ static int coda_psdev_open(struct inode * inode, struct file * file)
293 err = 0; 288 err = 0;
294 } 289 }
295 290
296 unlock_kernel(); 291 mutex_unlock(&vcp->vc_mutex);
297 return err; 292 return err;
298} 293}
299 294
@@ -308,7 +303,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
308 return -1; 303 return -1;
309 } 304 }
310 305
311 lock_kernel(); 306 mutex_lock(&vcp->vc_mutex);
312 307
313 /* Wakeup clients so they can return. */ 308 /* Wakeup clients so they can return. */
314 list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) { 309 list_for_each_entry_safe(req, tmp, &vcp->vc_pending, uc_chain) {
@@ -333,7 +328,7 @@ static int coda_psdev_release(struct inode * inode, struct file * file)
333 328
334 file->private_data = NULL; 329 file->private_data = NULL;
335 vcp->vc_inuse--; 330 vcp->vc_inuse--;
336 unlock_kernel(); 331 mutex_unlock(&vcp->vc_mutex);
337 return 0; 332 return 0;
338} 333}
339 334
@@ -346,6 +341,7 @@ static const struct file_operations coda_psdev_fops = {
346 .unlocked_ioctl = coda_psdev_ioctl, 341 .unlocked_ioctl = coda_psdev_ioctl,
347 .open = coda_psdev_open, 342 .open = coda_psdev_open,
348 .release = coda_psdev_release, 343 .release = coda_psdev_release,
344 .llseek = noop_llseek,
349}; 345};
350 346
351static int init_coda_psdev(void) 347static int init_coda_psdev(void)
@@ -361,9 +357,11 @@ static int init_coda_psdev(void)
361 err = PTR_ERR(coda_psdev_class); 357 err = PTR_ERR(coda_psdev_class);
362 goto out_chrdev; 358 goto out_chrdev;
363 } 359 }
364 for (i = 0; i < MAX_CODADEVS; i++) 360 for (i = 0; i < MAX_CODADEVS; i++) {
361 mutex_init(&(&coda_comms[i])->vc_mutex);
365 device_create(coda_psdev_class, NULL, 362 device_create(coda_psdev_class, NULL,
366 MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i); 363 MKDEV(CODA_PSDEV_MAJOR, i), NULL, "cfs%d", i);
364 }
367 coda_sysctl_init(); 365 coda_sysctl_init();
368 goto out; 366 goto out;
369 367
diff --git a/fs/coda/symlink.c b/fs/coda/symlink.c
index 4513b7258458..ab94ef63caef 100644
--- a/fs/coda/symlink.c
+++ b/fs/coda/symlink.c
@@ -14,12 +14,11 @@
14#include <linux/stat.h> 14#include <linux/stat.h>
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/pagemap.h> 16#include <linux/pagemap.h>
17#include <linux/smp_lock.h>
18 17
19#include <linux/coda.h> 18#include <linux/coda.h>
20#include <linux/coda_linux.h>
21#include <linux/coda_psdev.h> 19#include <linux/coda_psdev.h>
22#include <linux/coda_fs_i.h> 20
21#include "coda_linux.h"
23 22
24static int coda_symlink_filler(struct file *file, struct page *page) 23static int coda_symlink_filler(struct file *file, struct page *page)
25{ 24{
@@ -29,11 +28,9 @@ static int coda_symlink_filler(struct file *file, struct page *page)
29 unsigned int len = PAGE_SIZE; 28 unsigned int len = PAGE_SIZE;
30 char *p = kmap(page); 29 char *p = kmap(page);
31 30
32 lock_kernel();
33 cii = ITOC(inode); 31 cii = ITOC(inode);
34 32
35 error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len); 33 error = venus_readlink(inode->i_sb, &cii->c_fid, p, &len);
36 unlock_kernel();
37 if (error) 34 if (error)
38 goto fail; 35 goto fail;
39 SetPageUptodate(page); 36 SetPageUptodate(page);
diff --git a/fs/coda/sysctl.c b/fs/coda/sysctl.c
index c6405ce3c50e..af56ad56a89a 100644
--- a/fs/coda/sysctl.c
+++ b/fs/coda/sysctl.c
@@ -13,7 +13,6 @@
13 13
14#ifdef CONFIG_SYSCTL 14#ifdef CONFIG_SYSCTL
15static struct ctl_table_header *fs_table_header; 15static struct ctl_table_header *fs_table_header;
16#endif
17 16
18static ctl_table coda_table[] = { 17static ctl_table coda_table[] = {
19 { 18 {
@@ -40,7 +39,6 @@ static ctl_table coda_table[] = {
40 {} 39 {}
41}; 40};
42 41
43#ifdef CONFIG_SYSCTL
44static ctl_table fs_table[] = { 42static ctl_table fs_table[] = {
45 { 43 {
46 .procname = "coda", 44 .procname = "coda",
@@ -49,22 +47,27 @@ static ctl_table fs_table[] = {
49 }, 47 },
50 {} 48 {}
51}; 49};
52#endif
53 50
54void coda_sysctl_init(void) 51void coda_sysctl_init(void)
55{ 52{
56#ifdef CONFIG_SYSCTL
57 if ( !fs_table_header ) 53 if ( !fs_table_header )
58 fs_table_header = register_sysctl_table(fs_table); 54 fs_table_header = register_sysctl_table(fs_table);
59#endif
60} 55}
61 56
62void coda_sysctl_clean(void) 57void coda_sysctl_clean(void)
63{ 58{
64#ifdef CONFIG_SYSCTL
65 if ( fs_table_header ) { 59 if ( fs_table_header ) {
66 unregister_sysctl_table(fs_table_header); 60 unregister_sysctl_table(fs_table_header);
67 fs_table_header = NULL; 61 fs_table_header = NULL;
68 } 62 }
69#endif
70} 63}
64
65#else
66void coda_sysctl_init(void)
67{
68}
69
70void coda_sysctl_clean(void)
71{
72}
73#endif
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c
index b8893ab6f9e6..9727e0c52579 100644
--- a/fs/coda/upcall.c
+++ b/fs/coda/upcall.c
@@ -27,15 +27,15 @@
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>
33 34
34#include <linux/coda.h> 35#include <linux/coda.h>
35#include <linux/coda_linux.h>
36#include <linux/coda_psdev.h> 36#include <linux/coda_psdev.h>
37#include <linux/coda_fs_i.h> 37#include "coda_linux.h"
38#include <linux/coda_cache.h> 38#include "coda_cache.h"
39 39
40#include "coda_int.h" 40#include "coda_int.h"
41 41
@@ -606,7 +606,8 @@ static void coda_unblock_signals(sigset_t *old)
606 (r)->uc_opcode != CODA_RELEASE) || \ 606 (r)->uc_opcode != CODA_RELEASE) || \
607 (r)->uc_flags & CODA_REQ_READ)) 607 (r)->uc_flags & CODA_REQ_READ))
608 608
609static inline void coda_waitfor_upcall(struct upc_req *req) 609static inline void coda_waitfor_upcall(struct venus_comm *vcp,
610 struct upc_req *req)
610{ 611{
611 DECLARE_WAITQUEUE(wait, current); 612 DECLARE_WAITQUEUE(wait, current);
612 unsigned long timeout = jiffies + coda_timeout * HZ; 613 unsigned long timeout = jiffies + coda_timeout * HZ;
@@ -639,10 +640,12 @@ static inline void coda_waitfor_upcall(struct upc_req *req)
639 break; 640 break;
640 } 641 }
641 642
643 mutex_unlock(&vcp->vc_mutex);
642 if (blocked) 644 if (blocked)
643 schedule_timeout(HZ); 645 schedule_timeout(HZ);
644 else 646 else
645 schedule(); 647 schedule();
648 mutex_lock(&vcp->vc_mutex);
646 } 649 }
647 if (blocked) 650 if (blocked)
648 coda_unblock_signals(&old); 651 coda_unblock_signals(&old);
@@ -667,18 +670,23 @@ static int coda_upcall(struct venus_comm *vcp,
667{ 670{
668 union outputArgs *out; 671 union outputArgs *out;
669 union inputArgs *sig_inputArgs; 672 union inputArgs *sig_inputArgs;
670 struct upc_req *req, *sig_req; 673 struct upc_req *req = NULL, *sig_req;
671 int error = 0; 674 int error;
675
676 mutex_lock(&vcp->vc_mutex);
672 677
673 if (!vcp->vc_inuse) { 678 if (!vcp->vc_inuse) {
674 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n"); 679 printk(KERN_NOTICE "coda: Venus dead, not sending upcall\n");
675 return -ENXIO; 680 error = -ENXIO;
681 goto exit;
676 } 682 }
677 683
678 /* Format the request message. */ 684 /* Format the request message. */
679 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL); 685 req = kmalloc(sizeof(struct upc_req), GFP_KERNEL);
680 if (!req) 686 if (!req) {
681 return -ENOMEM; 687 error = -ENOMEM;
688 goto exit;
689 }
682 690
683 req->uc_data = (void *)buffer; 691 req->uc_data = (void *)buffer;
684 req->uc_flags = 0; 692 req->uc_flags = 0;
@@ -705,7 +713,7 @@ static int coda_upcall(struct venus_comm *vcp,
705 * ENODEV. */ 713 * ENODEV. */
706 714
707 /* Go to sleep. Wake up on signals only after the timeout. */ 715 /* Go to sleep. Wake up on signals only after the timeout. */
708 coda_waitfor_upcall(req); 716 coda_waitfor_upcall(vcp, req);
709 717
710 /* Op went through, interrupt or not... */ 718 /* Op went through, interrupt or not... */
711 if (req->uc_flags & CODA_REQ_WRITE) { 719 if (req->uc_flags & CODA_REQ_WRITE) {
@@ -759,6 +767,7 @@ static int coda_upcall(struct venus_comm *vcp,
759 767
760exit: 768exit:
761 kfree(req); 769 kfree(req);
770 mutex_unlock(&vcp->vc_mutex);
762 return error; 771 return error;
763} 772}
764 773
@@ -796,21 +805,24 @@ exit:
796 * 805 *
797 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */ 806 * CODA_REPLACE -- replace one CodaFid with another throughout the name cache */
798 807
799int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb) 808int coda_downcall(struct venus_comm *vcp, int opcode, union outputArgs *out)
800{ 809{
801 struct inode *inode = NULL; 810 struct inode *inode = NULL;
802 struct CodaFid *fid, *newfid; 811 struct CodaFid *fid = NULL, *newfid;
812 struct super_block *sb;
803 813
804 /* Handle invalidation requests. */ 814 /* Handle invalidation requests. */
805 if ( !sb || !sb->s_root) 815 mutex_lock(&vcp->vc_mutex);
806 return 0; 816 sb = vcp->vc_sb;
817 if (!sb || !sb->s_root)
818 goto unlock_out;
807 819
808 switch (opcode) { 820 switch (opcode) {
809 case CODA_FLUSH: 821 case CODA_FLUSH:
810 coda_cache_clear_all(sb); 822 coda_cache_clear_all(sb);
811 shrink_dcache_sb(sb); 823 shrink_dcache_sb(sb);
812 if (sb->s_root->d_inode) 824 if (sb->s_root->d_inode)
813 coda_flag_inode(sb->s_root->d_inode, C_FLUSH); 825 coda_flag_inode(sb->s_root->d_inode, C_FLUSH);
814 break; 826 break;
815 827
816 case CODA_PURGEUSER: 828 case CODA_PURGEUSER:
@@ -819,45 +831,53 @@ int coda_downcall(int opcode, union outputArgs * out, struct super_block *sb)
819 831
820 case CODA_ZAPDIR: 832 case CODA_ZAPDIR:
821 fid = &out->coda_zapdir.CodaFid; 833 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; 834 break;
828 835
829 case CODA_ZAPFILE: 836 case CODA_ZAPFILE:
830 fid = &out->coda_zapfile.CodaFid; 837 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; 838 break;
835 839
836 case CODA_PURGEFID: 840 case CODA_PURGEFID:
837 fid = &out->coda_purgefid.CodaFid; 841 fid = &out->coda_purgefid.CodaFid;
842 break;
843
844 case CODA_REPLACE:
845 fid = &out->coda_replace.OldFid;
846 break;
847 }
848 if (fid)
838 inode = coda_fid_to_inode(fid, sb); 849 inode = coda_fid_to_inode(fid, sb);
839 if (inode) {
840 coda_flag_inode_children(inode, C_PURGE);
841 850
842 /* catch the dentries later if some are still busy */ 851unlock_out:
843 coda_flag_inode(inode, C_PURGE); 852 mutex_unlock(&vcp->vc_mutex);
844 d_prune_aliases(inode);
845 853
846 } 854 if (!inode)
855 return 0;
856
857 switch (opcode) {
858 case CODA_ZAPDIR:
859 coda_flag_inode_children(inode, C_PURGE);
860 coda_flag_inode(inode, C_VATTR);
861 break;
862
863 case CODA_ZAPFILE:
864 coda_flag_inode(inode, C_VATTR);
865 break;
866
867 case CODA_PURGEFID:
868 coda_flag_inode_children(inode, C_PURGE);
869
870 /* catch the dentries later if some are still busy */
871 coda_flag_inode(inode, C_PURGE);
872 d_prune_aliases(inode);
847 break; 873 break;
848 874
849 case CODA_REPLACE: 875 case CODA_REPLACE:
850 fid = &out->coda_replace.OldFid;
851 newfid = &out->coda_replace.NewFid; 876 newfid = &out->coda_replace.NewFid;
852 inode = coda_fid_to_inode(fid, sb); 877 coda_replace_fid(inode, fid, newfid);
853 if (inode)
854 coda_replace_fid(inode, fid, newfid);
855 break; 878 break;
856 } 879 }
857 880 iput(inode);
858 if (inode)
859 iput(inode);
860
861 return 0; 881 return 0;
862} 882}
863 883