|
@@ -97,58 +97,45 @@ const struct file_operations coda_dir_operations = {
|
|
|
/* access routines: lookup, readlink, permission */
|
|
|
static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
|
|
|
{
|
|
|
- struct inode *res_inode = NULL;
|
|
|
+ struct inode *inode = NULL;
|
|
|
struct CodaFid resfid = { { 0, } };
|
|
|
- int dropme = 0; /* to indicate entry should not be cached */
|
|
|
int type = 0;
|
|
|
int error = 0;
|
|
|
const char *name = entry->d_name.name;
|
|
|
size_t length = entry->d_name.len;
|
|
|
-
|
|
|
- if ( length > CODA_MAXNAMLEN ) {
|
|
|
- printk("name too long: lookup, %s (%*s)\n",
|
|
|
+
|
|
|
+ if (length > CODA_MAXNAMLEN) {
|
|
|
+ printk(KERN_ERR "name too long: lookup, %s (%*s)\n",
|
|
|
coda_i2s(dir), (int)length, name);
|
|
|
return ERR_PTR(-ENAMETOOLONG);
|
|
|
}
|
|
|
|
|
|
+ /* control object, create inode on the fly */
|
|
|
+ if (coda_isroot(dir) && coda_iscontrol(name, length)) {
|
|
|
+ error = coda_cnode_makectl(&inode, dir->i_sb);
|
|
|
+ type = CODA_NOCACHE;
|
|
|
+ goto exit;
|
|
|
+ }
|
|
|
+
|
|
|
lock_kernel();
|
|
|
- /* control object, create inode on the fly */
|
|
|
- if (coda_isroot(dir) && coda_iscontrol(name, length)) {
|
|
|
- error = coda_cnode_makectl(&res_inode, dir->i_sb);
|
|
|
- dropme = 1;
|
|
|
- goto exit;
|
|
|
- }
|
|
|
|
|
|
- error = venus_lookup(dir->i_sb, coda_i2f(dir),
|
|
|
- (const char *)name, length, &type, &resfid);
|
|
|
+ error = venus_lookup(dir->i_sb, coda_i2f(dir), name, length,
|
|
|
+ &type, &resfid);
|
|
|
+ if (!error)
|
|
|
+ error = coda_cnode_make(&inode, &resfid, dir->i_sb);
|
|
|
|
|
|
- res_inode = NULL;
|
|
|
- if (!error) {
|
|
|
- if (type & CODA_NOCACHE) {
|
|
|
- type &= (~CODA_NOCACHE);
|
|
|
- dropme = 1;
|
|
|
- }
|
|
|
+ unlock_kernel();
|
|
|
|
|
|
- error = coda_cnode_make(&res_inode, &resfid, dir->i_sb);
|
|
|
- if (error) {
|
|
|
- unlock_kernel();
|
|
|
- return ERR_PTR(error);
|
|
|
- }
|
|
|
- } else if (error != -ENOENT) {
|
|
|
- unlock_kernel();
|
|
|
+ if (error && error != -ENOENT)
|
|
|
return ERR_PTR(error);
|
|
|
- }
|
|
|
|
|
|
exit:
|
|
|
- entry->d_time = 0;
|
|
|
entry->d_op = &coda_dentry_operations;
|
|
|
- d_add(entry, res_inode);
|
|
|
- if ( dropme ) {
|
|
|
- d_drop(entry);
|
|
|
- coda_flag_inode(res_inode, C_VATTR);
|
|
|
- }
|
|
|
- unlock_kernel();
|
|
|
- return NULL;
|
|
|
+
|
|
|
+ if (inode && (type & CODA_NOCACHE))
|
|
|
+ coda_flag_inode(inode, C_VATTR | C_PURGE);
|
|
|
+
|
|
|
+ return d_splice_alias(inode, entry);
|
|
|
}
|
|
|
|
|
|
|