diff options
Diffstat (limited to 'fs/coda/cnode.c')
-rw-r--r-- | fs/coda/cnode.c | 100 |
1 files changed, 52 insertions, 48 deletions
diff --git a/fs/coda/cnode.c b/fs/coda/cnode.c index 47f853c14..7c5544612 100644 --- a/fs/coda/cnode.c +++ b/fs/coda/cnode.c @@ -50,6 +50,7 @@ static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) } 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); } @@ -65,13 +66,25 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, inode = iget(sb, ino); if ( !inode ) { CDEBUG(D_CNODE, "coda_iget: no inode\n"); - return NULL; + return ERR_PTR(-ENOMEM); } /* check if the inode is already initialized */ cii = ITOC(inode); - if (cii->c_magic == CODA_CNODE_MAGIC) + if (cii->c_magic == CODA_CNODE_MAGIC) { + /* see if it is the right one (might have an inode collision) */ + if ( !coda_fideq(fid, &cii->c_fid) ) { + printk("coda_iget: initialized inode old %s new %s!\n", + coda_f2s(&cii->c_fid), coda_f2s2(fid)); + iput(inode); + return ERR_PTR(-ENOENT); + } + /* replace the attributes, type might have changed */ + coda_fill_inode(inode, attr); goto out; + } + + /* new, empty inode found... initializing */ /* Initialize the Coda inode info structure */ memset(cii, 0, (int) sizeof(struct coda_inode_info)); @@ -90,15 +103,17 @@ struct inode * coda_iget(struct super_block * sb, ViceFid * fid, if ( coda_f2i(fid) == ino ) goto out; - /* check if we expect this weird fid */ - if ( !coda_fid_is_weird(fid) ) + /* check if we expected this weird fid */ + if ( !coda_fid_is_weird(fid) ) { printk("Coda: unknown weird fid: ino %ld, fid %s." "Tell Peter.\n", (long)ino, coda_f2s(&cii->c_fid)); + goto out; + } /* add the inode to a global list so we can find it back later */ list_add(&cii->c_volrootlist, &sbi->sbi_volroothead); CDEBUG(D_CNODE, "Added %ld, %s to volroothead\n", - (long)ino, coda_f2s(&cii->c_fid)); + (long)ino, coda_f2s(&cii->c_fid)); out: return inode; } @@ -111,7 +126,6 @@ out: */ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) { - struct coda_inode_info *cnp; struct coda_vattr attr; int error; @@ -125,32 +139,22 @@ int coda_cnode_make(struct inode **inode, ViceFid *fid, struct super_block *sb) "coda_cnode_make: coda_getvattr returned %d for %s.\n", error, coda_f2s(fid)); *inode = NULL; + EXIT; return error; } *inode = coda_iget(sb, fid, &attr); - if ( !(*inode) ) { + if ( IS_ERR(*inode) ) { printk("coda_cnode_make: coda_iget failed\n"); - return -ENOMEM; - } - - cnp = ITOC(*inode); - /* see if it is the right one (we might have an inode collision) */ - if ( coda_fideq(fid, &cnp->c_fid) ) { - CDEBUG(D_DOWNCALL, - "Done making inode: ino %ld, count %d with %s\n", - (*inode)->i_ino, (*inode)->i_count, - coda_f2s(&cnp->c_fid)); EXIT; - return 0; - } + return PTR_ERR(*inode); + } - /* collision */ - printk("coda_cnode_make on initialized inode %ld, old %s new %s!\n", - (*inode)->i_ino, coda_f2s(&cnp->c_fid), coda_f2s2(fid)); - iput(*inode); + CDEBUG(D_DOWNCALL, "Done making inode: ino %ld, count %d with %s\n", + (*inode)->i_ino, atomic_read(&(*inode)->i_count), + coda_f2s(&(*inode)->u.coda_i.c_fid)); EXIT; - return -ENOENT; + return 0; } @@ -168,7 +172,8 @@ void coda_replace_fid(struct inode *inode, struct ViceFid *oldfid, cnp->c_fid = *newfid; list_del(&cnp->c_volrootlist); - if ( !coda_fid_is_weird(newfid) ) + INIT_LIST_HEAD(&cnp->c_volrootlist); + if ( coda_fid_is_weird(newfid) ) list_add(&cnp->c_volrootlist, &sbi->sbi_volroothead); return; @@ -184,10 +189,9 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) { ino_t nr; struct inode *inode; - struct coda_inode_info *cnp; + struct coda_inode_info *cii; ENTRY; - if ( !sb ) { printk("coda_fid_to_inode: no sb!\n"); return NULL; @@ -201,7 +205,6 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) if ( coda_fid_is_weird(fid) ) { - struct coda_inode_info *cii; struct list_head *lh, *le; struct coda_sb_info *sbi = coda_sbp(sb); le = lh = &sbi->sbi_volroothead; @@ -209,19 +212,19 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) while ( (le = le->next) != lh ) { cii = list_entry(le, struct coda_inode_info, c_volrootlist); - CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n", + /* paranoia check, should never trigger */ + if ( cii->c_magic != CODA_CNODE_MAGIC ) + printk("coda_fid_to_inode: Bad magic in inode %x.\n", cii->c_magic); + + CDEBUG(D_DOWNCALL, "iterating, now doing %s, ino %ld\n", coda_f2s(&cii->c_fid), cii->c_vnode->i_ino); + if ( coda_fideq(&cii->c_fid, fid) ) { inode = cii->c_vnode; CDEBUG(D_INODE, "volume root, found %ld\n", inode->i_ino); - if ( cii->c_magic != CODA_CNODE_MAGIC ) - printk("%s: Bad magic in inode, tell Peter.\n", - __FUNCTION__); - iget(sb, inode->i_ino); return inode; } - } return NULL; } @@ -236,27 +239,27 @@ struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) } /* check if this inode is linked to a cnode */ - cnp = ITOC(inode); - if ( cnp->c_magic != CODA_CNODE_MAGIC ) { + cii = ITOC(inode); + if ( cii->c_magic != CODA_CNODE_MAGIC ) { CDEBUG(D_INODE, "uninitialized inode. Return.\n"); - iput(inode); - return NULL; + goto bad_inode; } - /* make sure fid is the one we want; - unfortunately Venus will shamelessly send us mount-symlinks. - These have the same inode as the root of the volume they - mount, but the fid will be wrong. - */ - if ( !coda_fideq(fid, &(cnp->c_fid)) ) { - /* printk("coda_fid2inode: bad cnode (ino %ld, fid %s)" - "Tell Peter.\n", nr, coda_f2s(fid)); */ - iput(inode); - return NULL; + /* make sure fid is the one we want */ + if ( !coda_fideq(fid, &(cii->c_fid)) ) { +#if 0 + printk("coda_fid2inode: bad cnode (ino %ld, fid %s)", nr, + coda_f2s(fid)); +#endif + goto bad_inode; } CDEBUG(D_INODE, "found %ld\n", inode->i_ino); return inode; + +bad_inode: + iput(inode); + return NULL; } /* the CONTROL inode is made without asking attributes from Venus */ @@ -276,3 +279,4 @@ int coda_cnode_makectl(struct inode **inode, struct super_block *sb) return error; } + |