root/fs/coda/cnode.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. coda_fideq
  2. coda_fill_inode
  3. coda_test_inode
  4. coda_set_inode
  5. coda_iget
  6. coda_cnode_make
  7. coda_replace_fid
  8. coda_fid_to_inode
  9. coda_ftoc
  10. coda_cnode_makectl

   1 // SPDX-License-Identifier: GPL-2.0
   2 /* cnode related routines for the coda kernel code
   3    (C) 1996 Peter Braam
   4    */
   5 
   6 #include <linux/types.h>
   7 #include <linux/string.h>
   8 #include <linux/time.h>
   9 
  10 #include <linux/coda.h>
  11 #include <linux/pagemap.h>
  12 #include "coda_psdev.h"
  13 #include "coda_linux.h"
  14 
  15 static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
  16 {
  17         return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
  18 }
  19 
  20 static const struct inode_operations coda_symlink_inode_operations = {
  21         .get_link       = page_get_link,
  22         .setattr        = coda_setattr,
  23 };
  24 
  25 /* cnode.c */
  26 static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
  27 {
  28         coda_vattr_to_iattr(inode, attr);
  29 
  30         if (S_ISREG(inode->i_mode)) {
  31                 inode->i_op = &coda_file_inode_operations;
  32                 inode->i_fop = &coda_file_operations;
  33         } else if (S_ISDIR(inode->i_mode)) {
  34                 inode->i_op = &coda_dir_inode_operations;
  35                 inode->i_fop = &coda_dir_operations;
  36         } else if (S_ISLNK(inode->i_mode)) {
  37                 inode->i_op = &coda_symlink_inode_operations;
  38                 inode_nohighmem(inode);
  39                 inode->i_data.a_ops = &coda_symlink_aops;
  40                 inode->i_mapping = &inode->i_data;
  41         } else
  42                 init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev));
  43 }
  44 
  45 static int coda_test_inode(struct inode *inode, void *data)
  46 {
  47         struct CodaFid *fid = (struct CodaFid *)data;
  48         struct coda_inode_info *cii = ITOC(inode);
  49         return coda_fideq(&cii->c_fid, fid);
  50 }
  51 
  52 static int coda_set_inode(struct inode *inode, void *data)
  53 {
  54         struct CodaFid *fid = (struct CodaFid *)data;
  55         struct coda_inode_info *cii = ITOC(inode);
  56         cii->c_fid = *fid;
  57         return 0;
  58 }
  59 
  60 struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
  61                          struct coda_vattr * attr)
  62 {
  63         struct inode *inode;
  64         struct coda_inode_info *cii;
  65         unsigned long hash = coda_f2i(fid);
  66 
  67         inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
  68 
  69         if (!inode)
  70                 return ERR_PTR(-ENOMEM);
  71 
  72         if (inode->i_state & I_NEW) {
  73                 cii = ITOC(inode);
  74                 /* we still need to set i_ino for things like stat(2) */
  75                 inode->i_ino = hash;
  76                 /* inode is locked and unique, no need to grab cii->c_lock */
  77                 cii->c_mapcount = 0;
  78                 unlock_new_inode(inode);
  79         }
  80 
  81         /* always replace the attributes, type might have changed */
  82         coda_fill_inode(inode, attr);
  83         return inode;
  84 }
  85 
  86 /* this is effectively coda_iget:
  87    - get attributes (might be cached)
  88    - get the inode for the fid using vfs iget
  89    - link the two up if this is needed
  90    - fill in the attributes
  91 */
  92 struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
  93 {
  94         struct coda_vattr attr;
  95         struct inode *inode;
  96         int error;
  97         
  98         /* We get inode numbers from Venus -- see venus source */
  99         error = venus_getattr(sb, fid, &attr);
 100         if (error)
 101                 return ERR_PTR(error);
 102 
 103         inode = coda_iget(sb, fid, &attr);
 104         if (IS_ERR(inode))
 105                 pr_warn("%s: coda_iget failed\n", __func__);
 106         return inode;
 107 }
 108 
 109 
 110 /* Although we treat Coda file identifiers as immutable, there is one
 111  * special case for files created during a disconnection where they may
 112  * not be globally unique. When an identifier collision is detected we
 113  * first try to flush the cached inode from the kernel and finally
 114  * resort to renaming/rehashing in-place. Userspace remembers both old
 115  * and new values of the identifier to handle any in-flight upcalls.
 116  * The real solution is to use globally unique UUIDs as identifiers, but
 117  * retrofitting the existing userspace code for this is non-trivial. */
 118 void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
 119                       struct CodaFid *newfid)
 120 {
 121         struct coda_inode_info *cii = ITOC(inode);
 122         unsigned long hash = coda_f2i(newfid);
 123         
 124         BUG_ON(!coda_fideq(&cii->c_fid, oldfid));
 125 
 126         /* replace fid and rehash inode */
 127         /* XXX we probably need to hold some lock here! */
 128         remove_inode_hash(inode);
 129         cii->c_fid = *newfid;
 130         inode->i_ino = hash;
 131         __insert_inode_hash(inode, hash);
 132 }
 133 
 134 /* convert a fid to an inode. */
 135 struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 
 136 {
 137         struct inode *inode;
 138         unsigned long hash = coda_f2i(fid);
 139 
 140         inode = ilookup5(sb, hash, coda_test_inode, fid);
 141         if ( !inode )
 142                 return NULL;
 143 
 144         /* we should never see newly created inodes because we intentionally
 145          * fail in the initialization callback */
 146         BUG_ON(inode->i_state & I_NEW);
 147 
 148         return inode;
 149 }
 150 
 151 struct coda_file_info *coda_ftoc(struct file *file)
 152 {
 153         struct coda_file_info *cfi = file->private_data;
 154 
 155         BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);
 156 
 157         return cfi;
 158 
 159 }
 160 
 161 /* the CONTROL inode is made without asking attributes from Venus */
 162 struct inode *coda_cnode_makectl(struct super_block *sb)
 163 {
 164         struct inode *inode = new_inode(sb);
 165         if (inode) {
 166                 inode->i_ino = CTL_INO;
 167                 inode->i_op = &coda_ioctl_inode_operations;
 168                 inode->i_fop = &coda_ioctl_operations;
 169                 inode->i_mode = 0444;
 170                 return inode;
 171         }
 172         return ERR_PTR(-ENOMEM);
 173 }
 174 

/* [<][>][^][v][top][bottom][index][help] */