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 *granularityofthemtimeiscoarseanywayssowemightactuallybe
* 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 *tricktofoolGNUfind'soptimizations.Ifwecan'tbesureofthelink *(becauseofvolumemountpoints)weseti_nlinkto1whichforcesfind *toconsidereverychildasapossibledirectory.Weshouldalsonever
* 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_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;
}
/* Make sure we skip '.' and '..', we already got those */ if (name.name[0] == '.' && (name.len == 1 ||
(name.name[1] == '.' && name.len == 2)))
vdir->d_fileno = name.len = 0;
/* skip null entries */ if (vdir->d_fileno && name.len) {
ino = vdir->d_fileno;
type = CDT2DT(vdir->d_type); if (!dir_emit(ctx, name.name, name.len, ino, type)) break;
} /* we'll always have progress because d_reclen is unsigned and
* we've already established it is non-zero. */
ctx->pos += vdir->d_reclen;
}
out:
kfree(vdir); return0;
}
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;
inode = d_inode(dentry); if (!inode || is_bad_inode(inode)) return1;
cii = ITOC(inode); if (cii->c_flags & C_PURGE) return1;
return0;
}
/* *Thisiscalledwhenwewanttocheckiftheinodehas *changedontheserver.Codamakesthiseasysincethe *cachemanagerVenusissuesadowncalltothekernelwhenthis *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) return0;
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'sinochanged -typechangesmustbepermittedforrepairand missingmountpoints.
*/
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.