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_psdev.h> 1131a203dfSAl Viro #include "coda_linux.h" 121da177e4SLinus Torvalds 131da177e4SLinus Torvalds static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) 141da177e4SLinus Torvalds { 151da177e4SLinus Torvalds return memcmp(fid1, fid2, sizeof(*fid1)) == 0; 161da177e4SLinus Torvalds } 171da177e4SLinus Torvalds 18754661f1SArjan van de Ven static const struct inode_operations coda_symlink_inode_operations = { 191da177e4SLinus Torvalds .readlink = generic_readlink, 201da177e4SLinus Torvalds .follow_link = page_follow_link_light, 211da177e4SLinus Torvalds .put_link = page_put_link, 221da177e4SLinus Torvalds .setattr = coda_setattr, 231da177e4SLinus Torvalds }; 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds /* cnode.c */ 261da177e4SLinus Torvalds static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr) 271da177e4SLinus Torvalds { 281da177e4SLinus Torvalds coda_vattr_to_iattr(inode, attr); 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds if (S_ISREG(inode->i_mode)) { 311da177e4SLinus Torvalds inode->i_op = &coda_file_inode_operations; 321da177e4SLinus Torvalds inode->i_fop = &coda_file_operations; 331da177e4SLinus Torvalds } else if (S_ISDIR(inode->i_mode)) { 341da177e4SLinus Torvalds inode->i_op = &coda_dir_inode_operations; 351da177e4SLinus Torvalds inode->i_fop = &coda_dir_operations; 361da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) { 371da177e4SLinus Torvalds inode->i_op = &coda_symlink_inode_operations; 381da177e4SLinus Torvalds inode->i_data.a_ops = &coda_symlink_aops; 391da177e4SLinus Torvalds inode->i_mapping = &inode->i_data; 401da177e4SLinus Torvalds } else 411da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev)); 421da177e4SLinus Torvalds } 431da177e4SLinus Torvalds 441da177e4SLinus Torvalds static int coda_test_inode(struct inode *inode, void *data) 451da177e4SLinus Torvalds { 461da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 47b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 48b5ce1d83SYoshihisa Abe return coda_fideq(&cii->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; 54b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 55b5ce1d83SYoshihisa Abe cii->c_fid = *fid; 561da177e4SLinus Torvalds return 0; 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 591da177e4SLinus Torvalds struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid, 601da177e4SLinus Torvalds struct coda_vattr * attr) 611da177e4SLinus Torvalds { 621da177e4SLinus Torvalds struct inode *inode; 631da177e4SLinus Torvalds struct coda_inode_info *cii; 641da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 651da177e4SLinus Torvalds 661da177e4SLinus Torvalds inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds if (!inode) 691da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds if (inode->i_state & I_NEW) { 721da177e4SLinus Torvalds cii = ITOC(inode); 731da177e4SLinus Torvalds /* we still need to set i_ino for things like stat(2) */ 741da177e4SLinus Torvalds inode->i_ino = hash; 75b5ce1d83SYoshihisa Abe /* inode is locked and unique, no need to grab cii->c_lock */ 761da177e4SLinus Torvalds cii->c_mapcount = 0; 771da177e4SLinus Torvalds unlock_new_inode(inode); 781da177e4SLinus Torvalds } 791da177e4SLinus Torvalds 801da177e4SLinus Torvalds /* always replace the attributes, type might have changed */ 811da177e4SLinus Torvalds coda_fill_inode(inode, attr); 821da177e4SLinus Torvalds return inode; 831da177e4SLinus Torvalds } 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds /* this is effectively coda_iget: 861da177e4SLinus Torvalds - get attributes (might be cached) 871da177e4SLinus Torvalds - get the inode for the fid using vfs iget 881da177e4SLinus Torvalds - link the two up if this is needed 891da177e4SLinus Torvalds - fill in the attributes 901da177e4SLinus Torvalds */ 911da177e4SLinus Torvalds int coda_cnode_make(struct inode **inode, struct CodaFid *fid, struct super_block *sb) 921da177e4SLinus Torvalds { 931da177e4SLinus Torvalds struct coda_vattr attr; 941da177e4SLinus Torvalds int error; 951da177e4SLinus Torvalds 961da177e4SLinus Torvalds /* We get inode numbers from Venus -- see venus source */ 971da177e4SLinus Torvalds error = venus_getattr(sb, fid, &attr); 981da177e4SLinus Torvalds if ( error ) { 991da177e4SLinus Torvalds *inode = NULL; 1001da177e4SLinus Torvalds return error; 1011da177e4SLinus Torvalds } 1021da177e4SLinus Torvalds 1031da177e4SLinus Torvalds *inode = coda_iget(sb, fid, &attr); 1041da177e4SLinus Torvalds if ( IS_ERR(*inode) ) { 1051da177e4SLinus Torvalds printk("coda_cnode_make: coda_iget failed\n"); 1061da177e4SLinus Torvalds return PTR_ERR(*inode); 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds return 0; 1091da177e4SLinus Torvalds } 1101da177e4SLinus Torvalds 1111da177e4SLinus Torvalds 112b5ce1d83SYoshihisa Abe /* Although we treat Coda file identifiers as immutable, there is one 113b5ce1d83SYoshihisa Abe * special case for files created during a disconnection where they may 114b5ce1d83SYoshihisa Abe * not be globally unique. When an identifier collision is detected we 115b5ce1d83SYoshihisa Abe * first try to flush the cached inode from the kernel and finally 116b5ce1d83SYoshihisa Abe * resort to renaming/rehashing in-place. Userspace remembers both old 117b5ce1d83SYoshihisa Abe * and new values of the identifier to handle any in-flight upcalls. 118b5ce1d83SYoshihisa Abe * The real solution is to use globally unique UUIDs as identifiers, but 119b5ce1d83SYoshihisa Abe * retrofitting the existing userspace code for this is non-trivial. */ 1201da177e4SLinus Torvalds void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 1211da177e4SLinus Torvalds struct CodaFid *newfid) 1221da177e4SLinus Torvalds { 123b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 1241da177e4SLinus Torvalds unsigned long hash = coda_f2i(newfid); 1251da177e4SLinus Torvalds 126c5d3237cSEric Sesterhenn BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); 1271da177e4SLinus Torvalds 1281da177e4SLinus Torvalds /* replace fid and rehash inode */ 1291da177e4SLinus Torvalds /* XXX we probably need to hold some lock here! */ 1301da177e4SLinus Torvalds remove_inode_hash(inode); 1311da177e4SLinus Torvalds cii->c_fid = *newfid; 1321da177e4SLinus Torvalds inode->i_ino = hash; 1331da177e4SLinus Torvalds __insert_inode_hash(inode, hash); 1341da177e4SLinus Torvalds } 1351da177e4SLinus Torvalds 1361da177e4SLinus Torvalds /* convert a fid to an inode. */ 1371da177e4SLinus Torvalds struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 1381da177e4SLinus Torvalds { 1391da177e4SLinus Torvalds struct inode *inode; 1401da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 1411da177e4SLinus Torvalds 1421da177e4SLinus Torvalds if ( !sb ) { 1431da177e4SLinus Torvalds printk("coda_fid_to_inode: no sb!\n"); 1441da177e4SLinus Torvalds return NULL; 1451da177e4SLinus Torvalds } 1461da177e4SLinus Torvalds 147ed31a7ddSJan Harkes inode = ilookup5(sb, hash, coda_test_inode, fid); 1481da177e4SLinus Torvalds if ( !inode ) 1491da177e4SLinus Torvalds return NULL; 1501da177e4SLinus Torvalds 1511da177e4SLinus Torvalds /* we should never see newly created inodes because we intentionally 1521da177e4SLinus Torvalds * fail in the initialization callback */ 1531da177e4SLinus Torvalds BUG_ON(inode->i_state & I_NEW); 1541da177e4SLinus Torvalds 1551da177e4SLinus Torvalds return inode; 1561da177e4SLinus Torvalds } 1571da177e4SLinus Torvalds 1581da177e4SLinus Torvalds /* the CONTROL inode is made without asking attributes from Venus */ 1590b2c4e39SAl Viro struct inode *coda_cnode_makectl(struct super_block *sb) 1601da177e4SLinus Torvalds { 1610b2c4e39SAl Viro struct inode *inode = new_inode(sb); 1620b2c4e39SAl Viro if (inode) { 1630b2c4e39SAl Viro inode->i_ino = CTL_INO; 1640b2c4e39SAl Viro inode->i_op = &coda_ioctl_inode_operations; 1650b2c4e39SAl Viro inode->i_fop = &coda_ioctl_operations; 1660b2c4e39SAl Viro inode->i_mode = 0444; 1670b2c4e39SAl Viro return inode; 1681da177e4SLinus Torvalds } 1690b2c4e39SAl Viro return ERR_PTR(-ENOMEM); 1701da177e4SLinus Torvalds } 1711da177e4SLinus Torvalds 172