/* * Directory operations for Coda filesystem * Original version: (C) 1996 P. Braam and M. Callahan * Rewritten for Linux 2.1. (C) 1997 Carnegie Mellon University * * Carnegie Mellon encourages users to contribute improvements to * the Coda project. Contact Peter Braam (coda@cs.cmu.edu).
*/
staticinlinevoid coda_dir_update_mtime(struct inode *dir)
{ #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. */
inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); #endif
}
/* we have to wrap inc_nlink/drop_nlink because sometimes userspace uses a * trick to fool GNU find's optimizations. If we can't be sure of the link * (because of volume mount points) we set i_nlink to 1 which forces find * to consider every child as a possible directory. We should also never
* see an increment or decrement for deleted directories where i_nlink == 0 */ staticinlinevoid coda_dir_inc_nlink(struct inode *dir)
{ if (dir->i_nlink >= 2)
inc_nlink(dir);
}
/* try to make de an entry in dir_inodde linked to source_de */ staticint coda_link(struct dentry *source_de, struct inode *dir_inode, struct dentry *de)
{ struct inode *inode = d_inode(source_de); constchar * name = de->d_name.name; int len = de->d_name.len; int error;
if (is_root_inode(dir_inode) && coda_iscontrol(name, len)) return -EPERM;
staticint coda_symlink(struct mnt_idmap *idmap, struct inode *dir_inode, struct dentry *de, constchar *symname)
{ constchar *name = de->d_name.name; int len = de->d_name.len; int symlen; int error;
if (is_root_inode(dir_inode) && coda_iscontrol(name, len)) return -EPERM;
symlen = strlen(symname); if (symlen > CODA_MAXPATHLEN) return -ENAMETOOLONG;
/* * This entry is now negative. Since we do not create * an inode for the entry we have to drop it.
*/
d_drop(de);
error = venus_symlink(dir_inode->i_sb, coda_i2f(dir_inode), name, len,
symname, symlen);
/* mtime is no good anymore */ if (!error)
coda_dir_update_mtime(dir_inode);
return error;
}
/* destruction routines: unlink, rmdir */ staticint coda_unlink(struct inode *dir, struct dentry *de)
{ int error; constchar *name = de->d_name.name; int len = de->d_name.len;
error = venus_remove(dir->i_sb, coda_i2f(dir), name, len); if (error) return error;
staticint coda_rmdir(struct inode *dir, struct dentry *de)
{ constchar *name = de->d_name.name; int len = de->d_name.len; int error;
error = venus_rmdir(dir->i_sb, coda_i2f(dir), name, len); if (!error) { /* VFS may delete the child */ if (d_really_is_positive(de))
clear_nlink(d_inode(de));
/* fix the link count of the parent */
coda_dir_drop_nlink(dir);
coda_dir_update_mtime(dir);
} return error;
}
ret = iterate_dir(host_file, ctx); if (ret != -ENOTDIR) return ret; /* Venus: we must read Venus dirents from a file */ return coda_venus_readdir(coda_file, ctx);
}
/* called when a cache lookup succeeds */ staticint coda_dentry_revalidate(struct inode *dir, conststruct qstr *name, struct dentry *de, unsignedint flags)
{ struct inode *inode; struct coda_inode_info *cii;
if (flags & LOOKUP_RCU) return -ECHILD;
inode = d_inode(de); if (!inode || is_root_inode(inode)) goto out; if (is_bad_inode(inode)) goto bad;
/* * This is the callback from dput() when d_count is going to 0. * We use this to unhash dentries with bad inodes.
*/ staticint coda_dentry_delete(conststruct dentry * dentry)
{ struct inode *inode; struct coda_inode_info *cii;
if (d_really_is_negative(dentry)) return 0;
inode = d_inode(dentry); if (!inode || is_bad_inode(inode)) return 1;
cii = ITOC(inode); if (cii->c_flags & C_PURGE) return 1;
return 0;
}
/* * 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);
/* 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;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.