cnode.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:5k
- /* cnode related routines for the coda kernel code
- (C) 1996 Peter Braam
- */
- #include <linux/types.h>
- #include <linux/string.h>
- #include <linux/time.h>
- #include <linux/coda.h>
- #include <linux/coda_linux.h>
- #include <linux/coda_fs_i.h>
- #include <linux/coda_psdev.h>
- extern int coda_debug;
- extern int coda_print_entry;
- inline int coda_fideq(ViceFid *fid1, ViceFid *fid2)
- {
- if (fid1->Vnode != fid2->Vnode) return 0;
- if (fid1->Volume != fid2->Volume) return 0;
- if (fid1->Unique != fid2->Unique) return 0;
- return 1;
- }
- inline int coda_isnullfid(ViceFid *fid)
- {
- if (fid->Vnode || fid->Volume || fid->Unique) return 0;
- return 1;
- }
- static int coda_inocmp(struct inode *inode, unsigned long ino, void *opaque)
- {
- return (coda_fideq((ViceFid *)opaque, &(ITOC(inode)->c_fid)));
- }
- static struct inode_operations coda_symlink_inode_operations = {
- readlink: page_readlink,
- follow_link: page_follow_link,
- setattr: coda_notify_change,
- };
- /* cnode.c */
- static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
- {
- CDEBUG(D_SUPER, "ino: %ldn", inode->i_ino);
- if (coda_debug & D_SUPER )
- print_vattr(attr);
- coda_vattr_to_iattr(inode, attr);
- if (S_ISREG(inode->i_mode)) {
- inode->i_op = &coda_file_inode_operations;
- inode->i_fop = &coda_file_operations;
- } else if (S_ISDIR(inode->i_mode)) {
- inode->i_op = &coda_dir_inode_operations;
- inode->i_fop = &coda_dir_operations;
- } else if (S_ISLNK(inode->i_mode)) {
- inode->i_op = &coda_symlink_inode_operations;
- inode->i_data.a_ops = &coda_symlink_aops;
- inode->i_mapping = &inode->i_data;
- } else
- init_special_inode(inode, inode->i_mode, attr->va_rdev);
- }
- struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
- struct coda_vattr * attr)
- {
- struct inode *inode;
- struct coda_inode_info *cii;
- ino_t ino = coda_f2i(fid);
- inode = iget4(sb, ino, coda_inocmp, fid);
- if ( !inode ) {
- CDEBUG(D_CNODE, "coda_iget: no inoden");
- return ERR_PTR(-ENOMEM);
- }
- /* check if the inode is already initialized */
- cii = ITOC(inode);
- if (coda_isnullfid(&cii->c_fid))
- /* new, empty inode found... initializing */
- cii->c_fid = *fid;
- /* we shouldnt see inode collisions anymore */
- if (!coda_fideq(fid, &cii->c_fid)) BUG();
- /* always replace the attributes, type might have changed */
- coda_fill_inode(inode, attr);
- return inode;
- }
- /* this is effectively coda_iget:
- - get attributes (might be cached)
- - get the inode for the fid using vfs iget
- - link the two up if this is needed
- - fill in the attributes
- */
- int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb)
- {
- struct coda_vattr attr;
- int error;
-
- /* We get inode numbers from Venus -- see venus source */
- error = venus_getattr(sb, fid, &attr);
- if ( error ) {
- CDEBUG(D_CNODE,
- "coda_cnode_make: coda_getvattr returned %d for %s.n",
- error, coda_f2s(fid));
- *inode = NULL;
- return error;
- }
- *inode = coda_iget(sb, fid, &attr);
- if ( IS_ERR(*inode) ) {
- printk("coda_cnode_make: coda_iget failedn");
- return PTR_ERR(*inode);
- }
- CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %sn",
- (*inode)->i_ino, atomic_read(&(*inode)->i_count),
- coda_f2s(&ITOC(*inode)->c_fid));
- return 0;
- }
- void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid,
- struct ViceFid *newfid)
- {
- struct coda_inode_info *cii;
-
- cii = ITOC(inode);
- if (!coda_fideq(&cii->c_fid, oldfid))
- BUG();
- /* replace fid and rehash inode */
- /* XXX we probably need to hold some lock here! */
- remove_inode_hash(inode);
- cii->c_fid = *newfid;
- inode->i_ino = coda_f2i(newfid);
- insert_inode_hash(inode);
- }
- /* convert a fid to an inode. */
- struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb)
- {
- ino_t nr;
- struct inode *inode;
- struct coda_inode_info *cii;
- if ( !sb ) {
- printk("coda_fid_to_inode: no sb!n");
- return NULL;
- }
- CDEBUG(D_INODE, "%sn", coda_f2s(fid));
- nr = coda_f2i(fid);
- inode = iget4(sb, nr, coda_inocmp, fid);
- if ( !inode ) {
- printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.n",
- sb, (long)nr);
- return NULL;
- }
- cii = ITOC(inode);
- /* The inode could already be purged due to memory pressure */
- if (coda_isnullfid(&cii->c_fid)) {
- inode->i_nlink = 0;
- iput(inode);
- return NULL;
- }
- /* we shouldn't see inode collisions anymore */
- if ( !coda_fideq(fid, &cii->c_fid) ) BUG();
- CDEBUG(D_INODE, "found %ldn", inode->i_ino);
- return inode;
- }
- /* the CONTROL inode is made without asking attributes from Venus */
- int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
- {
- int error = 0;
- *inode = iget(sb, CTL_INO);
- if ( *inode ) {
- (*inode)->i_op = &coda_ioctl_inode_operations;
- (*inode)->i_fop = &coda_ioctl_operations;
- (*inode)->i_mode = 0444;
- error = 0;
- } else {
- error = -ENOMEM;
- }
-
- return error;
- }