1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 21da177e4SLinus Torvalds /* cnode related routines for the coda kernel code 31da177e4SLinus Torvalds (C) 1996 Peter Braam 41da177e4SLinus Torvalds */ 51da177e4SLinus Torvalds 61da177e4SLinus Torvalds #include <linux/types.h> 71da177e4SLinus Torvalds #include <linux/string.h> 81da177e4SLinus Torvalds #include <linux/time.h> 91da177e4SLinus Torvalds 101da177e4SLinus Torvalds #include <linux/coda.h> 111da177e4SLinus Torvalds #include <linux/coda_psdev.h> 1221fc61c7SAl Viro #include <linux/pagemap.h> 1331a203dfSAl Viro #include "coda_linux.h" 141da177e4SLinus Torvalds 151da177e4SLinus Torvalds static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2) 161da177e4SLinus Torvalds { 171da177e4SLinus Torvalds return memcmp(fid1, fid2, sizeof(*fid1)) == 0; 181da177e4SLinus Torvalds } 191da177e4SLinus Torvalds 20754661f1SArjan van de Ven static const struct inode_operations coda_symlink_inode_operations = { 216b255391SAl Viro .get_link = page_get_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; 3821fc61c7SAl Viro inode_nohighmem(inode); 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; 48b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 49b5ce1d83SYoshihisa Abe return coda_fideq(&cii->c_fid, fid); 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds static int coda_set_inode(struct inode *inode, void *data) 531da177e4SLinus Torvalds { 541da177e4SLinus Torvalds struct CodaFid *fid = (struct CodaFid *)data; 55b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 56b5ce1d83SYoshihisa Abe cii->c_fid = *fid; 571da177e4SLinus Torvalds return 0; 581da177e4SLinus Torvalds } 591da177e4SLinus Torvalds 601da177e4SLinus Torvalds struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid, 611da177e4SLinus Torvalds struct coda_vattr * attr) 621da177e4SLinus Torvalds { 631da177e4SLinus Torvalds struct inode *inode; 641da177e4SLinus Torvalds struct coda_inode_info *cii; 651da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid); 681da177e4SLinus Torvalds 691da177e4SLinus Torvalds if (!inode) 701da177e4SLinus Torvalds return ERR_PTR(-ENOMEM); 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds if (inode->i_state & I_NEW) { 731da177e4SLinus Torvalds cii = ITOC(inode); 741da177e4SLinus Torvalds /* we still need to set i_ino for things like stat(2) */ 751da177e4SLinus Torvalds inode->i_ino = hash; 76b5ce1d83SYoshihisa Abe /* inode is locked and unique, no need to grab cii->c_lock */ 771da177e4SLinus Torvalds cii->c_mapcount = 0; 781da177e4SLinus Torvalds unlock_new_inode(inode); 791da177e4SLinus Torvalds } 801da177e4SLinus Torvalds 811da177e4SLinus Torvalds /* always replace the attributes, type might have changed */ 821da177e4SLinus Torvalds coda_fill_inode(inode, attr); 831da177e4SLinus Torvalds return inode; 841da177e4SLinus Torvalds } 851da177e4SLinus Torvalds 861da177e4SLinus Torvalds /* this is effectively coda_iget: 871da177e4SLinus Torvalds - get attributes (might be cached) 881da177e4SLinus Torvalds - get the inode for the fid using vfs iget 891da177e4SLinus Torvalds - link the two up if this is needed 901da177e4SLinus Torvalds - fill in the attributes 911da177e4SLinus Torvalds */ 92f4947fbcSAl Viro struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb) 931da177e4SLinus Torvalds { 941da177e4SLinus Torvalds struct coda_vattr attr; 95f4947fbcSAl Viro struct inode *inode; 961da177e4SLinus Torvalds int error; 971da177e4SLinus Torvalds 981da177e4SLinus Torvalds /* We get inode numbers from Venus -- see venus source */ 991da177e4SLinus Torvalds error = venus_getattr(sb, fid, &attr); 100f4947fbcSAl Viro if (error) 101f4947fbcSAl Viro return ERR_PTR(error); 1021da177e4SLinus Torvalds 103f4947fbcSAl Viro inode = coda_iget(sb, fid, &attr); 104f4947fbcSAl Viro if (IS_ERR(inode)) 1056d6bd94fSFabian Frederick pr_warn("%s: coda_iget failed\n", __func__); 106f4947fbcSAl Viro return inode; 1071da177e4SLinus Torvalds } 1081da177e4SLinus Torvalds 1091da177e4SLinus Torvalds 110b5ce1d83SYoshihisa Abe /* Although we treat Coda file identifiers as immutable, there is one 111b5ce1d83SYoshihisa Abe * special case for files created during a disconnection where they may 112b5ce1d83SYoshihisa Abe * not be globally unique. When an identifier collision is detected we 113b5ce1d83SYoshihisa Abe * first try to flush the cached inode from the kernel and finally 114b5ce1d83SYoshihisa Abe * resort to renaming/rehashing in-place. Userspace remembers both old 115b5ce1d83SYoshihisa Abe * and new values of the identifier to handle any in-flight upcalls. 116b5ce1d83SYoshihisa Abe * The real solution is to use globally unique UUIDs as identifiers, but 117b5ce1d83SYoshihisa Abe * retrofitting the existing userspace code for this is non-trivial. */ 1181da177e4SLinus Torvalds void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 1191da177e4SLinus Torvalds struct CodaFid *newfid) 1201da177e4SLinus Torvalds { 121b5ce1d83SYoshihisa Abe struct coda_inode_info *cii = ITOC(inode); 1221da177e4SLinus Torvalds unsigned long hash = coda_f2i(newfid); 1231da177e4SLinus Torvalds 124c5d3237cSEric Sesterhenn BUG_ON(!coda_fideq(&cii->c_fid, oldfid)); 1251da177e4SLinus Torvalds 1261da177e4SLinus Torvalds /* replace fid and rehash inode */ 1271da177e4SLinus Torvalds /* XXX we probably need to hold some lock here! */ 1281da177e4SLinus Torvalds remove_inode_hash(inode); 1291da177e4SLinus Torvalds cii->c_fid = *newfid; 1301da177e4SLinus Torvalds inode->i_ino = hash; 1311da177e4SLinus Torvalds __insert_inode_hash(inode, hash); 1321da177e4SLinus Torvalds } 1331da177e4SLinus Torvalds 1341da177e4SLinus Torvalds /* convert a fid to an inode. */ 1351da177e4SLinus Torvalds struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 1361da177e4SLinus Torvalds { 1371da177e4SLinus Torvalds struct inode *inode; 1381da177e4SLinus Torvalds unsigned long hash = coda_f2i(fid); 1391da177e4SLinus Torvalds 1401da177e4SLinus Torvalds if ( !sb ) { 1416d6bd94fSFabian Frederick pr_warn("%s: no sb!\n", __func__); 1421da177e4SLinus Torvalds return NULL; 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds 145ed31a7ddSJan Harkes inode = ilookup5(sb, hash, coda_test_inode, fid); 1461da177e4SLinus Torvalds if ( !inode ) 1471da177e4SLinus Torvalds return NULL; 1481da177e4SLinus Torvalds 1491da177e4SLinus Torvalds /* we should never see newly created inodes because we intentionally 1501da177e4SLinus Torvalds * fail in the initialization callback */ 1511da177e4SLinus Torvalds BUG_ON(inode->i_state & I_NEW); 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds return inode; 1541da177e4SLinus Torvalds } 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds /* the CONTROL inode is made without asking attributes from Venus */ 1570b2c4e39SAl Viro struct inode *coda_cnode_makectl(struct super_block *sb) 1581da177e4SLinus Torvalds { 1590b2c4e39SAl Viro struct inode *inode = new_inode(sb); 1600b2c4e39SAl Viro if (inode) { 1610b2c4e39SAl Viro inode->i_ino = CTL_INO; 1620b2c4e39SAl Viro inode->i_op = &coda_ioctl_inode_operations; 1630b2c4e39SAl Viro inode->i_fop = &coda_ioctl_operations; 1640b2c4e39SAl Viro inode->i_mode = 0444; 1650b2c4e39SAl Viro return inode; 1661da177e4SLinus Torvalds } 1670b2c4e39SAl Viro return ERR_PTR(-ENOMEM); 1681da177e4SLinus Torvalds } 1691da177e4SLinus Torvalds 170