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> 1121fc61c7SAl Viro #include <linux/pagemap.h> 1231a203dfSAl Viro #include "coda_linux.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; 3921fc61c7SAl Viro inode_nohighmem(inode); 401da177e4SLinus Torvalds inode->i_data.a_ops = &coda_symlink_aops; 411da177e4SLinus Torvalds inode->i_mapping = &inode->i_data; 421da177e4SLinus Torvalds } else 431da177e4SLinus Torvalds init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev)); 441da177e4SLinus Torvalds } 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds static int coda_test_inode(struct inode *inode, void *data) 471da177e4SLinus Torvalds { 481da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 49b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 50b5ce1d83SYoshihisa Abe return coda_fideq(&cii->c_fid, fid); 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 531da177e4SLinus Torvalds static int coda_set_inode(struct inode *inode, void *data) 541da177e4SLinus Torvalds { 551da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 56b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 57b5ce1d83SYoshihisa Abe cii->c_fid = *fid; 581da177e4SLinus Torvalds return 0; 591da177e4SLinus Torvalds } 601da177e4SLinus Torvalds 611da177e4SLinus Torvalds struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid, 621da177e4SLinus Torvalds struct coda_vattr * attr) 631da177e4SLinus Torvalds { 641da177e4SLinus Torvalds struct inode *inode; 651da177e4SLinus Torvalds struct coda_inode_info *cii; 661da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 671da177e4SLinus Torvalds 681da177e4SLinus Torvalds inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); 691da177e4SLinus Torvalds 701da177e4SLinus Torvalds if (!inode) 711da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds if (inode->i_state & I_NEW) { 741da177e4SLinus Torvalds cii = ITOC(inode); 751da177e4SLinus Torvalds /* we still need to set i_ino for things like stat(2) */ 761da177e4SLinus Torvalds inode->i_ino = hash; 77b5ce1d83SYoshihisa Abe /* inode is locked and unique, no need to grab cii->c_lock */ 781da177e4SLinus Torvalds cii->c_mapcount = 0; 791da177e4SLinus Torvalds unlock_new_inode(inode); 801da177e4SLinus Torvalds } 811da177e4SLinus Torvalds 821da177e4SLinus Torvalds /* always replace the attributes, type might have changed */ 831da177e4SLinus Torvalds coda_fill_inode(inode, attr); 841da177e4SLinus Torvalds return inode; 851da177e4SLinus Torvalds } 861da177e4SLinus Torvalds 871da177e4SLinus Torvalds /* this is effectively coda_iget: 881da177e4SLinus Torvalds - get attributes (might be cached) 891da177e4SLinus Torvalds - get the inode for the fid using vfs iget 901da177e4SLinus Torvalds - link the two up if this is needed 911da177e4SLinus Torvalds - fill in the attributes 921da177e4SLinus Torvalds */ 93f4947fbcSAl Viro struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb) 941da177e4SLinus Torvalds { 951da177e4SLinus Torvalds struct coda_vattr attr; 96f4947fbcSAl Viro struct inode *inode; 971da177e4SLinus Torvalds int error; 981da177e4SLinus Torvalds 991da177e4SLinus Torvalds /* We get inode numbers from Venus -- see venus source */ 1001da177e4SLinus Torvalds error = venus_getattr(sb, fid, &attr); 101f4947fbcSAl Viro if (error) 102f4947fbcSAl Viro return ERR_PTR(error); 1031da177e4SLinus Torvalds 104f4947fbcSAl Viro inode = coda_iget(sb, fid, &attr); 105f4947fbcSAl Viro if (IS_ERR(inode)) 1066d6bd94fSFabian Frederick pr_warn("%s: coda_iget failed\n", __func__); 107f4947fbcSAl Viro return inode; 1081da177e4SLinus Torvalds } 1091da177e4SLinus Torvalds 1101da177e4SLinus Torvalds 111b5ce1d83SYoshihisa Abe /* Although we treat Coda file identifiers as immutable, there is one 112b5ce1d83SYoshihisa Abe * special case for files created during a disconnection where they may 113b5ce1d83SYoshihisa Abe * not be globally unique. When an identifier collision is detected we 114b5ce1d83SYoshihisa Abe * first try to flush the cached inode from the kernel and finally 115b5ce1d83SYoshihisa Abe * resort to renaming/rehashing in-place. Userspace remembers both old 116b5ce1d83SYoshihisa Abe * and new values of the identifier to handle any in-flight upcalls. 117b5ce1d83SYoshihisa Abe * The real solution is to use globally unique UUIDs as identifiers, but 118b5ce1d83SYoshihisa Abe * retrofitting the existing userspace code for this is non-trivial. */ 1191da177e4SLinus Torvalds void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 1201da177e4SLinus Torvalds struct CodaFid *newfid) 1211da177e4SLinus Torvalds { 122b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 1231da177e4SLinus Torvalds unsigned long hash = coda_f2i(newfid); 1241da177e4SLinus Torvalds 125c5d3237cSEric Sesterhenn BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); 1261da177e4SLinus Torvalds 1271da177e4SLinus Torvalds /* replace fid and rehash inode */ 1281da177e4SLinus Torvalds /* XXX we probably need to hold some lock here! */ 1291da177e4SLinus Torvalds remove_inode_hash(inode); 1301da177e4SLinus Torvalds cii->c_fid = *newfid; 1311da177e4SLinus Torvalds inode->i_ino = hash; 1321da177e4SLinus Torvalds __insert_inode_hash(inode, hash); 1331da177e4SLinus Torvalds } 1341da177e4SLinus Torvalds 1351da177e4SLinus Torvalds /* convert a fid to an inode. */ 1361da177e4SLinus Torvalds struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 1371da177e4SLinus Torvalds { 1381da177e4SLinus Torvalds struct inode *inode; 1391da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 1401da177e4SLinus Torvalds 1411da177e4SLinus Torvalds if ( !sb ) { 1426d6bd94fSFabian Frederick pr_warn("%s: no sb!\n", __func__); 1431da177e4SLinus Torvalds return NULL; 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds 146ed31a7ddSJan Harkes inode = ilookup5(sb, hash, coda_test_inode, fid); 1471da177e4SLinus Torvalds if ( !inode ) 1481da177e4SLinus Torvalds return NULL; 1491da177e4SLinus Torvalds 1501da177e4SLinus Torvalds /* we should never see newly created inodes because we intentionally 1511da177e4SLinus Torvalds * fail in the initialization callback */ 1521da177e4SLinus Torvalds BUG_ON(inode->i_state & I_NEW); 1531da177e4SLinus Torvalds 1541da177e4SLinus Torvalds return inode; 1551da177e4SLinus Torvalds } 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* the CONTROL inode is made without asking attributes from Venus */ 1580b2c4e39SAl Viro struct inode *coda_cnode_makectl(struct super_block *sb) 1591da177e4SLinus Torvalds { 1600b2c4e39SAl Viro struct inode *inode = new_inode(sb); 1610b2c4e39SAl Viro if (inode) { 1620b2c4e39SAl Viro inode->i_ino = CTL_INO; 1630b2c4e39SAl Viro inode->i_op = &coda_ioctl_inode_operations; 1640b2c4e39SAl Viro inode->i_fop = &coda_ioctl_operations; 1650b2c4e39SAl Viro inode->i_mode = 0444; 1660b2c4e39SAl Viro return inode; 1671da177e4SLinus Torvalds } 1680b2c4e39SAl Viro return ERR_PTR(-ENOMEM); 1691da177e4SLinus Torvalds } 1701da177e4SLinus Torvalds 171