diff options
Diffstat (limited to 'fs/coda')
-rw-r--r-- | fs/coda/dir.c | 57 |
1 files changed, 22 insertions, 35 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 47ac9e21a590..0c6c48ca7496 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c | |||
@@ -97,58 +97,45 @@ const struct file_operations coda_dir_operations = { | |||
97 | /* access routines: lookup, readlink, permission */ | 97 | /* access routines: lookup, readlink, permission */ |
98 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) | 98 | static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) |
99 | { | 99 | { |
100 | struct inode *res_inode = NULL; | 100 | struct inode *inode = NULL; |
101 | struct CodaFid resfid = { { 0, } }; | 101 | struct CodaFid resfid = { { 0, } }; |
102 | int dropme = 0; /* to indicate entry should not be cached */ | ||
103 | int type = 0; | 102 | int type = 0; |
104 | int error = 0; | 103 | int error = 0; |
105 | const char *name = entry->d_name.name; | 104 | const char *name = entry->d_name.name; |
106 | size_t length = entry->d_name.len; | 105 | size_t length = entry->d_name.len; |
107 | 106 | ||
108 | if ( length > CODA_MAXNAMLEN ) { | 107 | if (length > CODA_MAXNAMLEN) { |
109 | printk("name too long: lookup, %s (%*s)\n", | 108 | printk(KERN_ERR "name too long: lookup, %s (%*s)\n", |
110 | coda_i2s(dir), (int)length, name); | 109 | coda_i2s(dir), (int)length, name); |
111 | return ERR_PTR(-ENAMETOOLONG); | 110 | return ERR_PTR(-ENAMETOOLONG); |
112 | } | 111 | } |
113 | 112 | ||
113 | /* control object, create inode on the fly */ | ||
114 | if (coda_isroot(dir) && coda_iscontrol(name, length)) { | ||
115 | error = coda_cnode_makectl(&inode, dir->i_sb); | ||
116 | type = CODA_NOCACHE; | ||
117 | goto exit; | ||
118 | } | ||
119 | |||
114 | lock_kernel(); | 120 | lock_kernel(); |
115 | /* control object, create inode on the fly */ | ||
116 | if (coda_isroot(dir) && coda_iscontrol(name, length)) { | ||
117 | error = coda_cnode_makectl(&res_inode, dir->i_sb); | ||
118 | dropme = 1; | ||
119 | goto exit; | ||
120 | } | ||
121 | 121 | ||
122 | error = venus_lookup(dir->i_sb, coda_i2f(dir), | 122 | error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length, |
123 | (const char *)name, length, &type, &resfid); | 123 | &type, &resfid); |
124 | if (!error) | ||
125 | error = coda_cnode_make(&inode, &resfid, dir->i_sb); | ||
124 | 126 | ||
125 | res_inode = NULL; | 127 | unlock_kernel(); |
126 | if (!error) { | ||
127 | if (type & CODA_NOCACHE) { | ||
128 | type &= (~CODA_NOCACHE); | ||
129 | dropme = 1; | ||
130 | } | ||
131 | 128 | ||
132 | error = coda_cnode_make(&res_inode, &resfid, dir->i_sb); | 129 | if (error && error != -ENOENT) |
133 | if (error) { | ||
134 | unlock_kernel(); | ||
135 | return ERR_PTR(error); | ||
136 | } | ||
137 | } else if (error != -ENOENT) { | ||
138 | unlock_kernel(); | ||
139 | return ERR_PTR(error); | 130 | return ERR_PTR(error); |
140 | } | ||
141 | 131 | ||
142 | exit: | 132 | exit: |
143 | entry->d_time = 0; | ||
144 | entry->d_op = &coda_dentry_operations; | 133 | entry->d_op = &coda_dentry_operations; |
145 | d_add(entry, res_inode); | 134 | |
146 | if ( dropme ) { | 135 | if (inode && (type & CODA_NOCACHE)) |
147 | d_drop(entry); | 136 | coda_flag_inode(inode, C_VATTR | C_PURGE); |
148 | coda_flag_inode(res_inode, C_VATTR); | 137 | |
149 | } | 138 | return d_splice_alias(inode, entry); |
150 | unlock_kernel(); | ||
151 | return NULL; | ||
152 | } | 139 | } |
153 | 140 | ||
154 | 141 | ||