/* called when a cache lookup succeeds */ static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) { struct inode *inode = de->d_inode; struct coda_inode_info *cii; if (!inode || coda_isroot(inode)) goto out; if (is_bad_inode(inode)) goto bad; cii = ITOC(de->d_inode); if (!(cii->c_flags & (C_PURGE | C_FLUSH))) goto out; shrink_dcache_parent(de); /* propagate for a flush */ if (cii->c_flags & C_FLUSH) coda_flag_inode_children(inode, C_FLUSH); if (atomic_read(&de->d_count) > 1) /* pretend it's valid, but don't change the flags */ goto out; /* clear the flags. */ spin_lock(&cii->c_lock); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); spin_unlock(&cii->c_lock); bad: return 0; out: return 1; }
/* * This is called when we want to check if the inode has * changed on the server. Coda makes this easy since the * 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 coda_inode_info *cii = ITOC(inode); CDEBUG(D_INODE, "revalidating: %*s/%*s\n", dentry->d_name.len, dentry->d_name.name, dentry->d_parent->d_name.len, dentry->d_parent->d_name.name); lock_kernel(); if ( !cii->c_flags ) goto ok; if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); if ( error ) goto return_bad_inode; /* this inode may be lost if: - it's ino changed - type changes must be permitted for repair and missing mount points. */ old_mode = inode->i_mode; 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))); } /* the following can happen when a local fid is replaced with a global one, here we lose and declare the inode bad */ if (inode->i_ino != old_ino) goto return_bad_inode; coda_flag_inode_children(inode, C_FLUSH); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); } ok: unlock_kernel(); return 0; return_bad_inode: unlock_kernel(); return -EIO; }
/* * This is called when we want to check if the inode has * changed on the server. Coda makes this easy since the * cache manager Venus issues a downcall to the kernel when this * happens */ int coda_revalidate_inode(struct inode *inode) { struct coda_vattr attr; int error; int old_mode; ino_t old_ino; struct coda_inode_info *cii = ITOC(inode); if (!cii->c_flags) return 0; if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); if (error) return -EIO; /* this inode may be lost if: - it's ino changed - type changes must be permitted for repair and missing mount points. */ old_mode = inode->i_mode; old_ino = inode->i_ino; coda_vattr_to_iattr(inode, &attr); if ((old_mode & S_IFMT) != (inode->i_mode & S_IFMT)) { pr_warn("inode %ld, fid %s changed type!\n", inode->i_ino, coda_f2s(&(cii->c_fid))); } /* the following can happen when a local fid is replaced with a global one, here we lose and declare the inode bad */ if (inode->i_ino != old_ino) return -EIO; coda_flag_inode_children(inode, C_FLUSH); spin_lock(&cii->c_lock); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); spin_unlock(&cii->c_lock); } return 0; }
/* called when a cache lookup succeeds */ static int coda_dentry_revalidate(struct dentry *de, int flags) { struct inode *inode = de->d_inode; struct coda_inode_info *cii; if (!inode) return 1; lock_kernel(); if (coda_isroot(inode)) goto out; if (is_bad_inode(inode)) goto bad; cii = ITOC(de->d_inode); if (!(cii->c_flags & (C_PURGE | C_FLUSH))) goto out; shrink_dcache_parent(de); /* propagate for a flush */ if (cii->c_flags & C_FLUSH) coda_flag_inode_children(inode, C_FLUSH); if (atomic_read(&de->d_count) > 1) { /* pretend it's valid, but don't change the flags */ CDEBUG(D_DOWNCALL, "BOOM for: ino %ld, %s\n", de->d_inode->i_ino, coda_f2s(&cii->c_fid)); goto out; } /* clear the flags. */ cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); bad: unlock_kernel(); return 0; out: unlock_kernel(); return 1; }
/* called when a cache lookup succeeds */ static int coda_dentry_revalidate(struct dentry *de, unsigned int flags) { struct inode *inode; struct coda_inode_info *cii; if (flags & LOOKUP_RCU) return -ECHILD; inode = de->d_inode; if (!inode || is_root_inode(inode)) goto out; if (is_bad_inode(inode)) goto bad; cii = ITOC(de->d_inode); if (!(cii->c_flags & (C_PURGE | C_FLUSH))) goto out; shrink_dcache_parent(de); /* propagate for a flush */ if (cii->c_flags & C_FLUSH) coda_flag_inode_children(inode, C_FLUSH); if (d_count(de) > 1) /* pretend it's valid, but don't change the flags */ goto out; /* clear the flags. */ spin_lock(&cii->c_lock); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); spin_unlock(&cii->c_lock); bad: return 0; out: return 1; }
int coda_revalidate_inode(struct dentry *dentry) { struct coda_vattr attr; int error; int old_mode; ino_t old_ino; struct inode *inode = dentry->d_inode; struct coda_inode_info *cii = ITOC(inode); if (!cii->c_flags) return 0; if (cii->c_flags & (C_VATTR | C_PURGE | C_FLUSH)) { error = venus_getattr(inode->i_sb, &(cii->c_fid), &attr); if (error) return -EIO; old_mode = inode->i_mode; 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))); } if (inode->i_ino != old_ino) return -EIO; coda_flag_inode_children(inode, C_FLUSH); spin_lock(&cii->c_lock); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); spin_unlock(&cii->c_lock); } return 0; }
static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd) { struct inode *inode; struct coda_inode_info *cii; if (nd->flags & LOOKUP_RCU) return -ECHILD; inode = de->d_inode; if (!inode || coda_isroot(inode)) goto out; if (is_bad_inode(inode)) goto bad; cii = ITOC(de->d_inode); if (!(cii->c_flags & (C_PURGE | C_FLUSH))) goto out; shrink_dcache_parent(de); if (cii->c_flags & C_FLUSH) coda_flag_inode_children(inode, C_FLUSH); if (de->d_count > 1) goto out; spin_lock(&cii->c_lock); cii->c_flags &= ~(C_VATTR | C_PURGE | C_FLUSH); spin_unlock(&cii->c_lock); bad: return 0; out: return 1; }