Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* cnode related routines for the coda kernel code
0003    (C) 1996 Peter Braam
0004    */
0005 
0006 #include <linux/types.h>
0007 #include <linux/string.h>
0008 #include <linux/time.h>
0009 
0010 #include <linux/coda.h>
0011 #include <linux/pagemap.h>
0012 #include "coda_psdev.h"
0013 #include "coda_linux.h"
0014 
0015 static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
0016 {
0017     return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
0018 }
0019 
0020 static const struct inode_operations coda_symlink_inode_operations = {
0021     .get_link   = page_get_link,
0022     .setattr    = coda_setattr,
0023 };
0024 
0025 /* cnode.c */
0026 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
0027 {
0028         coda_vattr_to_iattr(inode, attr);
0029 
0030         if (S_ISREG(inode->i_mode)) {
0031                 inode->i_op = &coda_file_inode_operations;
0032                 inode->i_fop = &coda_file_operations;
0033         } else if (S_ISDIR(inode->i_mode)) {
0034                 inode->i_op = &coda_dir_inode_operations;
0035                 inode->i_fop = &coda_dir_operations;
0036         } else if (S_ISLNK(inode->i_mode)) {
0037         inode->i_op = &coda_symlink_inode_operations;
0038         inode_nohighmem(inode);
0039         inode->i_data.a_ops = &coda_symlink_aops;
0040         inode->i_mapping = &inode->i_data;
0041     } else
0042                 init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev));
0043 }
0044 
0045 static int coda_test_inode(struct inode *inode, void *data)
0046 {
0047     struct CodaFid *fid = (struct CodaFid *)data;
0048     struct coda_inode_info *cii = ITOC(inode);
0049     return coda_fideq(&cii->c_fid, fid);
0050 }
0051 
0052 static int coda_set_inode(struct inode *inode, void *data)
0053 {
0054     struct CodaFid *fid = (struct CodaFid *)data;
0055     struct coda_inode_info *cii = ITOC(inode);
0056     cii->c_fid = *fid;
0057     return 0;
0058 }
0059 
0060 struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
0061              struct coda_vattr * attr)
0062 {
0063     struct inode *inode;
0064     struct coda_inode_info *cii;
0065     unsigned long hash = coda_f2i(fid);
0066     umode_t inode_type = coda_inode_type(attr);
0067 
0068 retry:
0069     inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
0070     if (!inode)
0071         return ERR_PTR(-ENOMEM);
0072 
0073     if (inode->i_state & I_NEW) {
0074         cii = ITOC(inode);
0075         /* we still need to set i_ino for things like stat(2) */
0076         inode->i_ino = hash;
0077         /* inode is locked and unique, no need to grab cii->c_lock */
0078         cii->c_mapcount = 0;
0079         coda_fill_inode(inode, attr);
0080         unlock_new_inode(inode);
0081     } else if ((inode->i_mode & S_IFMT) != inode_type) {
0082         /* Inode has changed type, mark bad and grab a new one */
0083         remove_inode_hash(inode);
0084         coda_flag_inode(inode, C_PURGE);
0085         iput(inode);
0086         goto retry;
0087     }
0088     return inode;
0089 }
0090 
0091 /* this is effectively coda_iget:
0092    - get attributes (might be cached)
0093    - get the inode for the fid using vfs iget
0094    - link the two up if this is needed
0095    - fill in the attributes
0096 */
0097 struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
0098 {
0099         struct coda_vattr attr;
0100     struct inode *inode;
0101         int error;
0102         
0103     /* We get inode numbers from Venus -- see venus source */
0104     error = venus_getattr(sb, fid, &attr);
0105     if (error)
0106         return ERR_PTR(error);
0107 
0108     inode = coda_iget(sb, fid, &attr);
0109     if (IS_ERR(inode))
0110         pr_warn("%s: coda_iget failed\n", __func__);
0111     return inode;
0112 }
0113 
0114 
0115 /* Although we treat Coda file identifiers as immutable, there is one
0116  * special case for files created during a disconnection where they may
0117  * not be globally unique. When an identifier collision is detected we
0118  * first try to flush the cached inode from the kernel and finally
0119  * resort to renaming/rehashing in-place. Userspace remembers both old
0120  * and new values of the identifier to handle any in-flight upcalls.
0121  * The real solution is to use globally unique UUIDs as identifiers, but
0122  * retrofitting the existing userspace code for this is non-trivial. */
0123 void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
0124               struct CodaFid *newfid)
0125 {
0126     struct coda_inode_info *cii = ITOC(inode);
0127     unsigned long hash = coda_f2i(newfid);
0128     
0129     BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
0130 
0131     /* replace fid and rehash inode */
0132     /* XXX we probably need to hold some lock here! */
0133     remove_inode_hash(inode);
0134     cii->c_fid = *newfid;
0135     inode->i_ino = hash;
0136     __insert_inode_hash(inode, hash);
0137 }
0138 
0139 /* convert a fid to an inode. */
0140 struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 
0141 {
0142     struct inode *inode;
0143     unsigned long hash = coda_f2i(fid);
0144 
0145     inode = ilookup5(sb, hash, coda_test_inode, fid);
0146     if ( !inode )
0147         return NULL;
0148 
0149     /* we should never see newly created inodes because we intentionally
0150      * fail in the initialization callback */
0151     BUG_ON(inode->i_state & I_NEW);
0152 
0153     return inode;
0154 }
0155 
0156 struct coda_file_info *coda_ftoc(struct file *file)
0157 {
0158     struct coda_file_info *cfi = file->private_data;
0159 
0160     BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
0161 
0162     return cfi;
0163 
0164 }
0165 
0166 /* the CONTROL inode is made without asking attributes from Venus */
0167 struct inode *coda_cnode_makectl(struct super_block *sb)
0168 {
0169     struct inode *inode = new_inode(sb);
0170     if (inode) {
0171         inode->i_ino = CTL_INO;
0172         inode->i_op = &coda_ioctl_inode_operations;
0173         inode->i_fop = &coda_ioctl_operations;
0174         inode->i_mode = 0444;
0175         return inode;
0176     }
0177     return ERR_PTR(-ENOMEM);
0178 }
0179