diff options
Diffstat (limited to 'fs/coda/dir.c')
-rw-r--r-- | fs/coda/dir.c | 342 |
1 files changed, 175 insertions, 167 deletions
diff --git a/fs/coda/dir.c b/fs/coda/dir.c index 83f7bbcc5..0faf29663 100644 --- a/fs/coda/dir.c +++ b/fs/coda/dir.c @@ -48,11 +48,15 @@ static int coda_dentry_revalidate(struct dentry *de, int); static int coda_dentry_delete(struct dentry *); /* support routines */ +static void coda_prepare_fakefile(struct inode *coda_inode, + struct file *coda_file, + struct inode *open_inode, + struct file *open_file, + struct dentry *open_dentry); static int coda_venus_readdir(struct file *filp, void *dirent, filldir_t filldir); -int coda_fsync(struct file *, struct dentry *dentry); +int coda_fsync(struct file *, struct dentry *dentry, int); -int coda_crossvol_rename = 0; int coda_hasmknod = 0; struct dentry_operations coda_dentry_operations = @@ -90,38 +94,36 @@ struct file_operations coda_dir_operations = { /* acces routines: lookup, readlink, permission */ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) { - struct coda_inode_info *dircnp; struct inode *res_inode = NULL; - struct ViceFid resfid; + struct ViceFid resfid = {0,0,0}; int dropme = 0; /* to indicate entry should not be cached */ - int type; + int type = 0; int error = 0; const char *name = entry->d_name.name; size_t length = entry->d_name.len; ENTRY; - dircnp = ITOC(dir); - if ( length > CODA_MAXNAMLEN ) { printk("name too long: lookup, %s (%*s)\n", - coda_f2s(&dircnp->c_fid), (int)length, name); + coda_i2s(dir), (int)length, name); return ERR_PTR(-ENAMETOOLONG); } CDEBUG(D_INODE, "name %s, len %ld in ino %ld, fid %s\n", - name, (long)length, dir->i_ino, coda_f2s(&dircnp->c_fid)); + name, (long)length, dir->i_ino, coda_i2s(dir)); /* control object, create inode on the fly */ if (coda_isroot(dir) && coda_iscontrol(name, length)) { error = coda_cnode_makectl(&res_inode, dir->i_sb); CDEBUG(D_SPECIAL, "Lookup on CTL object; dir ino %ld, count %d\n", - dir->i_ino, dir->i_count); + dir->i_ino, atomic_read(&dir->i_count)); + dropme = 1; goto exit; } - error = venus_lookup(dir->i_sb, &(dircnp->c_fid), + error = venus_lookup(dir->i_sb, coda_i2f(dir), (const char *)name, length, &type, &resfid); res_inode = NULL; @@ -132,12 +134,17 @@ static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry) coda_f2s(&resfid)); dropme = 1; } + error = coda_cnode_make(&res_inode, &resfid, dir->i_sb); - if (error) - return ERR_PTR(error); + if (error) return ERR_PTR(error); + + /* make sure we drop unexpected weird fid's */ + if (coda_f2i(&resfid) != res_inode->i_ino && + !coda_fid_is_weird(&resfid)) + dropme = 1; } else if (error != -ENOENT) { CDEBUG(D_INODE, "error for %s(%*s)%d\n", - coda_f2s(&dircnp->c_fid), (int)length, name, error); + coda_i2s(dir), (int)length, name, error); return ERR_PTR(error); } CDEBUG(D_INODE, "lookup: %s is (%s), type %d result %d, dropme %d\n", @@ -149,7 +156,7 @@ exit: d_add(entry, res_inode); if ( dropme ) { d_drop(entry); - ITOC(res_inode)->c_flags |= C_VATTR; + coda_flag_inode(res_inode, C_VATTR); } EXIT; return NULL; @@ -158,16 +165,14 @@ exit: int coda_permission(struct inode *inode, int mask) { - struct coda_inode_info *cp = ITOC(inode); int error; ENTRY; coda_vfs_stat.permission++; coda_permission_stat.count++; - if ( mask == 0 ) { + if ( mask == 0 ) return 0; - } if ( coda_access_cache == 1 ) { if ( coda_cache_check(inode, mask) ) { @@ -176,28 +181,39 @@ int coda_permission(struct inode *inode, int mask) } } - cp = ITOC(inode); - CDEBUG(D_INODE, "mask is %o\n", mask); - error = venus_access(inode->i_sb, &(cp->c_fid), mask); + error = venus_access(inode->i_sb, coda_i2f(inode), mask); CDEBUG(D_INODE, "fid: %s, ino: %ld (mask: %o) error: %d\n", - coda_f2s(&(cp->c_fid)), inode->i_ino, mask, error); + coda_i2s(inode), inode->i_ino, mask, error); - if ( error == 0 ) { + if (!error) coda_cache_enter(inode, mask); - } return error; } -/* creation routines: create, mknod, mkdir, link, symlink */ +static inline void coda_dir_changed(struct inode *dir, int link) +{ +#ifdef REQUERY_VENUS_FOR_MTIME + /* invalidate the directory cnode's attributes so we refetch the + * attributes from venus next time the inode is referenced */ + coda_flag_inode(dir, C_VATTR); +#else + /* optimistically we can also act as if our nose bleeds. The + * granularity of the mtime is coarse anyways so we might actually be + * right most of the time. Note: we only do this for directories. */ + dir->i_mtime = CURRENT_TIME; +#endif + if (link) + dir->i_nlink += link; +} +/* creation routines: create, mknod, mkdir, link, symlink */ static int coda_create(struct inode *dir, struct dentry *de, int mode) { int error=0; - struct coda_inode_info *dircnp; const char *name=de->d_name.name; int length=de->d_name.len; struct inode *result = NULL; @@ -207,14 +223,12 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode) ENTRY; coda_vfs_stat.create++; - CDEBUG(D_INODE, "name: %s, length %d, mode %o\n",name, length, mode); + CDEBUG(D_INODE, "name: %s, length %d, mode %o\n", name, length, mode); if (coda_isroot(dir) && coda_iscontrol(name, length)) return -EPERM; - dircnp = ITOC(dir); - - error = venus_create(dir->i_sb, &(dircnp->c_fid), name, length, + error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 0, mode, 0, &newfid, &attrs); if ( error ) { @@ -232,15 +246,14 @@ static int coda_create(struct inode *dir, struct dentry *de, int mode) } /* invalidate the directory cnode's attributes */ - dircnp->c_flags |= C_VATTR; + coda_dir_changed(dir, 0); d_instantiate(de, result); return 0; -} +} static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) { int error=0; - struct coda_inode_info *dircnp; const char *name=de->d_name.name; int length=de->d_name.len; struct inode *result = NULL; @@ -258,9 +271,7 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) if (coda_isroot(dir) && coda_iscontrol(name, length)) return -EPERM; - dircnp = ITOC(dir); - - error = venus_create(dir->i_sb, &(dircnp->c_fid), name, length, + error = venus_create(dir->i_sb, coda_i2f(dir), name, length, 0, mode, rdev, &newfid, &attrs); if ( error ) { @@ -278,14 +289,13 @@ static int coda_mknod(struct inode *dir, struct dentry *de, int mode, int rdev) } /* invalidate the directory cnode's attributes */ - dircnp->c_flags |= C_VATTR; + coda_dir_changed(dir, 0); d_instantiate(de, result); return 0; } static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) { - struct coda_inode_info *dircnp; struct inode *inode; struct coda_vattr attr; const char *name = de->d_name.name; @@ -299,13 +309,11 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) if (coda_isroot(dir) && coda_iscontrol(name, len)) return -EPERM; - dircnp = ITOC(dir); - CDEBUG(D_INODE, "mkdir %s (len %d) in %s, mode %o.\n", - name, len, coda_f2s(&(dircnp->c_fid)), mode); + name, len, coda_i2s(dir), mode); attr.va_mode = mode; - error = venus_mkdir(dir->i_sb, &(dircnp->c_fid), + error = venus_mkdir(dir->i_sb, coda_i2f(dir), name, len, &newfid, &attr); if ( error ) { @@ -325,8 +333,7 @@ static int coda_mkdir(struct inode *dir, struct dentry *de, int mode) } /* invalidate the directory cnode's attributes */ - dircnp->c_flags |= C_VATTR; - dir->i_nlink++; + coda_dir_changed(dir, 1); d_instantiate(de, inode); return 0; } @@ -338,7 +345,6 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, struct inode *inode = source_de->d_inode; const char * name = de->d_name.name; int len = de->d_name.len; - struct coda_inode_info *dir_cnp, *cnp; int error; ENTRY; @@ -347,28 +353,26 @@ static int coda_link(struct dentry *source_de, struct inode *dir_inode, if (coda_isroot(dir_inode) && coda_iscontrol(name, len)) return -EPERM; - dir_cnp = ITOC(dir_inode); - cnp = ITOC(inode); - - CDEBUG(D_INODE, "old: fid: %s\n", coda_f2s(&(cnp->c_fid))); - CDEBUG(D_INODE, "directory: %s\n", coda_f2s(&(dir_cnp->c_fid))); + CDEBUG(D_INODE, "old: fid: %s\n", coda_i2s(inode)); + CDEBUG(D_INODE, "directory: %s\n", coda_i2s(dir_inode)); - error = venus_link(dir_inode->i_sb,&(cnp->c_fid), &(dir_cnp->c_fid), - (const char *)name, len); + error = venus_link(dir_inode->i_sb, coda_i2f(inode), + coda_i2f(dir_inode), (const char *)name, len); - if ( ! error ) { - dir_cnp->c_flags |= C_VATTR; - ++inode->i_count; - d_instantiate(de, inode); - inode->i_nlink++; - } else { + if (error) { d_drop(de); - return error; + goto out; } - CDEBUG(D_INODE, "link result %d\n",error); + coda_dir_changed(dir_inode, 0); + atomic_inc(&inode->i_count); + d_instantiate(de, inode); + inode->i_nlink++; + +out: + CDEBUG(D_INODE, "link result %d\n",error); EXIT; - return(error); + return(error); } @@ -377,7 +381,6 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, { const char *name = de->d_name.name; int len = de->d_name.len; - struct coda_inode_info *dir_cnp = ITOC(dir_inode); int symlen; int error=0; @@ -398,13 +401,12 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, * an inode for the entry we have to drop it. */ d_drop(de); - error = venus_symlink(dir_inode->i_sb, &(dir_cnp->c_fid), name, len, + error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len, symname, symlen); /* mtime is no good anymore */ - if ( !error ) { - dir_cnp->c_flags |= C_VATTR; - } + if ( !error ) + coda_dir_changed(dir_inode, 0); CDEBUG(D_INODE, "in symlink result %d\n",error); EXIT; @@ -414,7 +416,6 @@ static int coda_symlink(struct inode *dir_inode, struct dentry *de, /* destruction routines: unlink, rmdir */ int coda_unlink(struct inode *dir, struct dentry *de) { - struct coda_inode_info *dircnp = ITOC(dir); int error; const char *name = de->d_name.name; int len = de->d_name.len; @@ -423,16 +424,15 @@ int coda_unlink(struct inode *dir, struct dentry *de) coda_vfs_stat.unlink++; CDEBUG(D_INODE, " %s in %s, dirino %ld\n", name , - coda_f2s(&(dircnp->c_fid)), dir->i_ino); + coda_i2s(dir), dir->i_ino); - error = venus_remove(dir->i_sb, &(dircnp->c_fid), name, len); + error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); if ( error ) { CDEBUG(D_INODE, "upc returned error %d\n", error); return error; } - /* cache management: mtime has changed, ask Venus */ - dircnp->c_flags |= C_VATTR; + coda_dir_changed(dir, 0); de->d_inode->i_nlink--; return 0; @@ -440,7 +440,6 @@ int coda_unlink(struct inode *dir, struct dentry *de) int coda_rmdir(struct inode *dir, struct dentry *de) { - struct coda_inode_info *dircnp; const char *name = de->d_name.name; int len = de->d_name.len; int error; @@ -448,19 +447,18 @@ int coda_rmdir(struct inode *dir, struct dentry *de) ENTRY; coda_vfs_stat.rmdir++; - dircnp = ITOC(dir); - if (!d_unhashed(de)) return -EBUSY; - error = venus_rmdir(dir->i_sb, &(dircnp->c_fid), name, len); + error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); if ( error ) { CDEBUG(D_INODE, "upc returned error %d\n", error); return error; } - if (de->d_inode->i_nlink) - de->d_inode->i_nlink --; + coda_dir_changed(dir, -1); + de->d_inode->i_nlink--; + d_delete(de); return 0; } @@ -473,43 +471,38 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, const char *new_name = new_dentry->d_name.name; int old_length = old_dentry->d_name.len; int new_length = new_dentry->d_name.len; - struct inode *new_inode = new_dentry->d_inode; - struct coda_inode_info *new_cnp, *old_cnp; int error; ENTRY; coda_vfs_stat.rename++; - old_cnp = ITOC(old_dir); - new_cnp = ITOC(new_dir); - - CDEBUG(D_INODE, "old: %s, (%d length, %ld strlen), new: %s" - "(%d length, %ld strlen).old:d_count: %d, new:d_count: %d\n", - old_name, old_length, (long)strlen(old_name), new_name, new_length, - (long)strlen(new_name),old_dentry->d_count, new_dentry->d_count); - - /* the C library will do unlink/create etc */ - if ( coda_crossvol_rename == 0 && - old_cnp->c_fid.Volume != new_cnp->c_fid.Volume ) - return -EXDEV; + CDEBUG(D_INODE, "old: %s, (%d length), new: %s" + "(%d length). old:d_count: %d, new:d_count: %d\n", + old_name, old_length, new_name, new_length, + old_dentry->d_count, new_dentry->d_count); - error = venus_rename(old_dir->i_sb, &(old_cnp->c_fid), - &(new_cnp->c_fid), old_length, new_length, + error = venus_rename(old_dir->i_sb, coda_i2f(old_dir), + coda_i2f(new_dir), old_length, new_length, (const char *) old_name, (const char *)new_name); - if ( error ) { - CDEBUG(D_INODE, "returned error %d\n", error); - return error; - } + if ( !error ) { + if ( new_dentry->d_inode ) { + if ( S_ISDIR(new_dentry->d_inode->i_mode) ) { + old_dir->i_nlink--; + new_dir->i_nlink++; + } + coda_flag_inode(new_dentry->d_inode, C_VATTR); + } - coda_flag_inode(new_inode, C_VATTR); - coda_flag_inode(old_dir, C_VATTR); - coda_flag_inode(new_dir, C_VATTR); + /* coda_flag_inode(old_dir, C_VATTR); */ + /* coda_flag_inode(new_dir, C_VATTR); */ + old_dir->i_mtime = new_dir->i_mtime = CURRENT_TIME; + } CDEBUG(D_INODE, "result %d\n", error); EXIT; - return 0; + return error; } @@ -517,43 +510,70 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry, int coda_readdir(struct file *file, void *dirent, filldir_t filldir) { int result = 0; - struct coda_inode_info *cnp; struct file open_file; struct dentry open_dentry; - struct inode *inode=file->f_dentry->d_inode; + struct inode *inode=file->f_dentry->d_inode, *container; ENTRY; coda_vfs_stat.readdir++; - cnp = ITOC(inode); - if ( !cnp->c_ovp ) { - CDEBUG(D_FILE, "open inode pointer = NULL.\n"); + if ( inode->i_mapping == &inode->i_data ) { + CDEBUG(D_FILE, "no container inode.\n"); return -EIO; } - coda_prepare_openfile(inode, file, cnp->c_ovp, &open_file, - &open_dentry); - if ( S_ISREG(cnp->c_ovp->i_mode) ) { + container = (struct inode *)inode->i_mapping->host; + + coda_prepare_fakefile(inode, file, container, &open_file, &open_dentry); + + if ( S_ISREG(container->i_mode) ) { /* Venus: we must read Venus dirents from the file */ result = coda_venus_readdir(&open_file, dirent, filldir); } else { - /* potemkin case: we are handed a directory inode */ + /* potemkin case: we are handed a directory inode */ result = vfs_readdir(&open_file, filldir, dirent); } - coda_restore_codafile(inode, file, cnp->c_ovp, &open_file); + + /* we only have to restore the file position (and f_version?) */ + file->f_pos = open_file.f_pos; + file->f_version = open_file.f_version; + EXIT; return result; } +/* grab the ext2 inode of the container file */ +static int coda_inode_grab(dev_t dev, ino_t ino, struct inode **ind) +{ + struct super_block *sbptr; + + sbptr = get_super(dev); + + if ( !sbptr ) { + printk("coda_inode_grab: coda_find_super returns NULL.\n"); + return -ENXIO; + } + + *ind = NULL; + *ind = iget(sbptr, ino); + + if ( *ind == NULL ) { + printk("coda_inode_grab: iget(dev: %d, ino: %ld) " + "returns NULL.\n", dev, (long)ino); + return -ENOENT; + } + CDEBUG(D_FILE, "ino: %ld, ops at %p\n", (long)ino, (*ind)->i_op); + return 0; +} + /* ask venus to cache the file and return the inode of the container file, put this inode pointer in the cnode for future read/writes */ int coda_open(struct inode *i, struct file *f) { ino_t ino; dev_t dev; - struct coda_inode_info *cnp; int error = 0; - struct inode *cont_inode = NULL; + struct inode *cont_inode = NULL, *old_container; unsigned short flags = f->f_flags & (~O_EXCL); unsigned short coda_flags = coda_flags_to_cflags(flags); struct coda_cred *cred; @@ -564,10 +584,7 @@ int coda_open(struct inode *i, struct file *f) CDEBUG(D_SPECIAL, "OPEN inode number: %ld, count %d, flags %o.\n", f->f_dentry->d_inode->i_ino, f->f_dentry->d_count, flags); - cnp = ITOC(i); - - - error = venus_open(i->i_sb, &(cnp->c_fid), coda_flags, &ino, &dev); + error = venus_open(i->i_sb, coda_i2f(i), coda_flags, &ino, &dev); if (error) { CDEBUG(D_FILE, "venus: dev %d, inode %ld, out->result %d\n", dev, (long)ino, error); @@ -589,25 +606,25 @@ int coda_open(struct inode *i, struct file *f) coda_load_creds(cred); f->private_data = cred; - if ( cnp->c_ovp ) - iput(cnp->c_ovp); - - cnp->c_ovp = cont_inode; + if ( i->i_mapping != &i->i_data ) { + old_container = (struct inode *)i->i_mapping->host; + i->i_mapping = &i->i_data; + iput(old_container); + } i->i_mapping = cont_inode->i_mapping; - cnp->c_ocount++; - CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", - error, i->i_count, i->i_ino); - CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", - cnp->c_ovp->i_ino, cnp->c_ovp->i_count, - (cnp->c_ovp->i_op)); + CDEBUG(D_FILE, "result %d, coda i->i_count is %d for ino %ld\n", + error, atomic_read(&i->i_count), i->i_ino); + CDEBUG(D_FILE, "cache ino: %ld, count %d, ops %p\n", + cont_inode->i_ino, atomic_read(&cont_inode->i_count), + cont_inode->i_op); EXIT; return 0; } int coda_release(struct inode *i, struct file *f) { - struct coda_inode_info *cnp; + struct inode *container = NULL; int error = 0; unsigned short flags = (f->f_flags) & (~O_EXCL); unsigned short cflags = coda_flags_to_cflags(flags); @@ -618,29 +635,15 @@ int coda_release(struct inode *i, struct file *f) cred = (struct coda_cred *)f->private_data; - cnp =ITOC(i); - CHECK_CNODE(cnp); - CDEBUG(D_FILE, - "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n", - i->i_ino, i->i_count, (cnp->c_ovp ? cnp->c_ovp->i_ino : 0), - (cnp->c_ovp ? cnp->c_ovp->i_count : -99)); + if (i->i_mapping != &i->i_data) + container = (struct inode *)i->i_mapping->host; + CDEBUG(D_FILE, "RELEASE coda (ino %ld, ct %d) cache (ino %ld, ct %d)\n", + i->i_ino, atomic_read(&i->i_count), + (container ? container->i_ino : 0), + (container ? atomic_read(&container->i_count) : -99)); - /* even when c_ocount=0 we cannot put c_ovp to - * NULL since the file may be mmapped. - * See code in inode.c (coda_put_inode) for - * further handling of close. - */ - - --cnp->c_ocount; - - if ( flags & (O_WRONLY | O_RDWR) ) - --cnp->c_owrite; - - /* Venus closing a container file? don't bother making the upcall. */ - if ( current->pid != coda_upc_comm.vc_pid ) { - error = venus_release(i->i_sb, &(cnp->c_fid), cflags, cred); - } + error = venus_release(i->i_sb, coda_i2f(i), cflags, cred); f->private_data = NULL; if (cred) @@ -651,13 +654,29 @@ int coda_release(struct inode *i, struct file *f) } /* support routines */ + +/* instantiate a fake file and dentry to pass to coda_venus_readdir */ +static void coda_prepare_fakefile(struct inode *i, struct file *coda_file, + struct inode *cont_inode, + struct file *cont_file, + struct dentry *cont_dentry) +{ + cont_file->f_dentry = cont_dentry; + cont_file->f_dentry->d_inode = cont_inode; + cont_file->f_pos = coda_file->f_pos; + cont_file->f_version = coda_file->f_version; + cont_file->f_op = cont_inode->i_fop; + return ; +} + /* * this structure is manipulated by filldir in vfs layer. * the count holds the remaining amount of space in the getdents buffer, * beyond the current_dir pointer. + * + * What structure is this comment referring to?? -JH */ - /* should be big enough to hold any single directory entry */ #define DIR_BUFSIZE 2048 @@ -767,13 +786,12 @@ static int coda_dentry_revalidate(struct dentry *de, int flags) if (!inode) return 1; - - cii = ITOC(de->d_inode); if (coda_isroot(inode)) return 1; if (is_bad_inode(inode)) return 0; + cii = ITOC(de->d_inode); if (! (cii->c_flags & (C_PURGE | C_FLUSH)) ) return valid; @@ -807,7 +825,7 @@ static int coda_dentry_delete(struct dentry * dentry) if (!dentry->d_inode) return 0; - flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE; + flags = (ITOC(dentry->d_inode)->c_flags) & C_PURGE; if (is_bad_inode(dentry->d_inode) || flags) { CDEBUG(D_DOWNCALL, "bad inode, unhashing %s/%s, %ld\n", dentry->d_parent->d_name.name, dentry->d_name.name, @@ -825,14 +843,13 @@ static int coda_dentry_delete(struct dentry * dentry) * cache manager Venus issues a downcall to the kernel when this * happens */ - int coda_revalidate_inode(struct dentry *dentry) { struct coda_vattr attr; int error = 0; int old_mode; ino_t old_ino; - struct inode *inode = dentry->d_inode; + struct inode *inode = dentry->d_inode, *container; struct coda_inode_info *cii = ITOC(inode); ENTRY; @@ -843,14 +860,6 @@ int coda_revalidate_inode(struct dentry *dentry) if ( cii->c_flags == 0 ) return 0; - /* Venus accessing a container file, don't try to revalidate */ - if ( current->pid == coda_upc_comm.vc_pid ) - return 0; - - /* Venus closed the device .... */ - if ( cii->c_flags & C_DYING ) - goto return_bad_inode; - if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); if ( error ) @@ -865,7 +874,6 @@ int coda_revalidate_inode(struct dentry *dentry) old_ino = inode->i_ino; coda_vattr_to_iattr(inode, &attr); - if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) { printk("Coda: inode %ld, fid %s changed type!\n", inode->i_ino, coda_f2s(&(cii->c_fid))); @@ -885,10 +893,10 @@ int coda_revalidate_inode(struct dentry *dentry) return 0; return_bad_inode: - if ( cii->c_ovp ) { - iput(cii->c_ovp); + if ( inode->i_mapping != &inode->i_data ) { + container = (struct inode *)inode->i_mapping->host; inode->i_mapping = &inode->i_data; - cii->c_ovp = NULL; + iput(container); } make_bad_inode(inode); return -EIO; |