11da177e4SLinus Torvalds /* cnode related routines for the coda kernel code 21da177e4SLinus Torvalds (C) 1996 Peter Braam 31da177e4SLinus Torvalds */ 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds #include <linux/types.h> 61da177e4SLinus Torvalds #include <linux/string.h> 71da177e4SLinus Torvalds #include <linux/time.h> 81da177e4SLinus Torvalds 91da177e4SLinus Torvalds #include <linux/coda.h> 101da177e4SLinus Torvalds #include <linux/coda_linux.h> 111da177e4SLinus Torvalds #include <linux/coda_fs_i.h> 121da177e4SLinus Torvalds #include <linux/coda_psdev.h> 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) 151da177e4SLinus Torvalds { 161da177e4SLinus Torvalds return memcmp(fid1, fid2, sizeof(*fid1)) == 0; 171da177e4SLinus Torvalds } 181da177e4SLinus Torvalds 19754661f1SArjan van de Ven static const struct inode_operations coda_symlink_inode_operations = { 201da177e4SLinus Torvalds .readlink = generic_readlink, 211da177e4SLinus Torvalds .follow_link = page_follow_link_light, 221da177e4SLinus Torvalds .put_link = page_put_link, 231da177e4SLinus Torvalds .setattr = coda_setattr, 241da177e4SLinus Torvalds }; 251da177e4SLinus Torvalds 261da177e4SLinus Torvalds /* cnode.c */ 271da177e4SLinus Torvalds static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) 281da177e4SLinus Torvalds { 291da177e4SLinus Torvalds coda_vattr_to_iattr(inode, attr); 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 321da177e4SLinus Torvalds inode->i_op = &coda_file_inode_operations; 331da177e4SLinus Torvalds inode->i_fop = &coda_file_operations; 341da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 351da177e4SLinus Torvalds inode->i_op = &coda_dir_inode_operations; 361da177e4SLinus Torvalds inode->i_fop = &coda_dir_operations; 371da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 381da177e4SLinus Torvalds inode->i_op = &coda_symlink_inode_operations; 391da177e4SLinus Torvalds inode->i_data.a_ops = &coda_symlink_aops; 401da177e4SLinus Torvalds inode->i_mapping = &inode->i_data; 411da177e4SLinus Torvalds } else 421da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev)); 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds static int coda_test_inode(struct inode *inode, void *data) 461da177e4SLinus Torvalds { 471da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 481da177e4SLinus Torvalds return coda_fideq(&(ITOC(inode)->c_fid), fid); 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds static int coda_set_inode(struct inode *inode, void *data) 521da177e4SLinus Torvalds { 531da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 541da177e4SLinus Torvalds ITOC(inode)->c_fid = *fid; 551da177e4SLinus Torvalds return 0; 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid, 591da177e4SLinus Torvalds struct coda_vattr * attr) 601da177e4SLinus Torvalds { 611da177e4SLinus Torvalds struct inode *inode; 621da177e4SLinus Torvalds struct coda_inode_info *cii; 631da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds if (!inode) 681da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds if (inode->i_state & I_NEW) { 711da177e4SLinus Torvalds cii = ITOC(inode); 721da177e4SLinus Torvalds /* we still need to set i_ino for things like stat(2) */ 731da177e4SLinus Torvalds inode->i_ino = hash; 741da177e4SLinus Torvalds cii->c_mapcount = 0; 751da177e4SLinus Torvalds unlock_new_inode(inode); 761da177e4SLinus Torvalds } 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds /* always replace the attributes, type might have changed */ 791da177e4SLinus Torvalds coda_fill_inode(inode, attr); 801da177e4SLinus Torvalds return inode; 811da177e4SLinus Torvalds } 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds /* this is effectively coda_iget: 841da177e4SLinus Torvalds - get attributes (might be cached) 851da177e4SLinus Torvalds - get the inode for the fid using vfs iget 861da177e4SLinus Torvalds - link the two up if this is needed 871da177e4SLinus Torvalds - fill in the attributes 881da177e4SLinus Torvalds */ 891da177e4SLinus Torvalds int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_block *sb) 901da177e4SLinus Torvalds { 911da177e4SLinus Torvalds struct coda_vattr attr; 921da177e4SLinus Torvalds int error; 931da177e4SLinus Torvalds 941da177e4SLinus Torvalds /* We get inode numbers from Venus -- see venus source */ 951da177e4SLinus Torvalds error = venus_getattr(sb, fid, &attr); 961da177e4SLinus Torvalds if ( error ) { 971da177e4SLinus Torvalds *inode = NULL; 981da177e4SLinus Torvalds return error; 991da177e4SLinus Torvalds } 1001da177e4SLinus Torvalds 1011da177e4SLinus Torvalds *inode = coda_iget(sb, fid, &attr); 1021da177e4SLinus Torvalds if ( IS_ERR(*inode) ) { 1031da177e4SLinus Torvalds printk("coda_cnode_make: coda_iget failed\n"); 1041da177e4SLinus Torvalds return PTR_ERR(*inode); 1051da177e4SLinus Torvalds } 1061da177e4SLinus Torvalds return 0; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 1111da177e4SLinus Torvalds struct CodaFid *newfid) 1121da177e4SLinus Torvalds { 1131da177e4SLinus Torvalds struct coda_inode_info *cii; 1141da177e4SLinus Torvalds unsigned long hash = coda_f2i(newfid); 1151da177e4SLinus Torvalds 1161da177e4SLinus Torvalds cii = ITOC(inode); 1171da177e4SLinus Torvalds 118c5d3237cSEric Sesterhenn BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds /* replace fid and rehash inode */ 1211da177e4SLinus Torvalds /* XXX we probably need to hold some lock here! */ 1221da177e4SLinus Torvalds remove_inode_hash(inode); 1231da177e4SLinus Torvalds cii->c_fid = *newfid; 1241da177e4SLinus Torvalds inode->i_ino = hash; 1251da177e4SLinus Torvalds __insert_inode_hash(inode, hash); 1261da177e4SLinus Torvalds } 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds /* convert a fid to an inode. */ 1291da177e4SLinus Torvalds struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 1301da177e4SLinus Torvalds { 1311da177e4SLinus Torvalds struct inode *inode; 1321da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds if ( !sb ) { 1351da177e4SLinus Torvalds printk("coda_fid_to_inode: no sb!\n"); 1361da177e4SLinus Torvalds return NULL; 1371da177e4SLinus Torvalds } 1381da177e4SLinus Torvalds 139ed31a7ddSJan Harkes inode = ilookup5(sb, hash, coda_test_inode, fid); 1401da177e4SLinus Torvalds if ( !inode ) 1411da177e4SLinus Torvalds return NULL; 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds /* we should never see newly created inodes because we intentionally 1441da177e4SLinus Torvalds * fail in the initialization callback */ 1451da177e4SLinus Torvalds BUG_ON(inode->i_state & I_NEW); 1461da177e4SLinus Torvalds 1471da177e4SLinus Torvalds return inode; 1481da177e4SLinus Torvalds } 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* the CONTROL inode is made without asking attributes from Venus */ 1511da177e4SLinus Torvalds int coda_cnode_makectl(struct inode **inode, struct super_block *sb) 1521da177e4SLinus Torvalds { 1531da177e4SLinus Torvalds int error = -ENOMEM; 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds *inode = new_inode(sb); 1561da177e4SLinus Torvalds if (*inode) { 1571da177e4SLinus Torvalds (*inode)->i_ino = CTL_INO; 1581da177e4SLinus Torvalds (*inode)->i_op = &coda_ioctl_inode_operations; 1591da177e4SLinus Torvalds (*inode)->i_fop = &coda_ioctl_operations; 1601da177e4SLinus Torvalds (*inode)->i_mode = 0444; 1611da177e4SLinus Torvalds error = 0; 1621da177e4SLinus Torvalds } 1631da177e4SLinus Torvalds 1641da177e4SLinus Torvalds return error; 1651da177e4SLinus Torvalds } 1661da177e4SLinus Torvalds 167