1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2000-2001 Christoph Hellwig. 4 * Copyright (c) 2016 Krzysztof Blaszkowski 5 */ 6 7 /* 8 * Veritas filesystem driver - inode routines. 9 */ 10 #include <linux/fs.h> 11 #include <linux/buffer_head.h> 12 #include <linux/pagemap.h> 13 #include <linux/kernel.h> 14 #include <linux/slab.h> 15 #include <linux/namei.h> 16 17 #include "vxfs.h" 18 #include "vxfs_inode.h" 19 #include "vxfs_extern.h" 20 21 22 #ifdef DIAGNOSTIC 23 /* 24 * Dump inode contents (partially). 25 */ 26 void 27 vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) 28 { 29 printk(KERN_DEBUG "\n\n"); 30 if (ino) 31 printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino); 32 else 33 printk(KERN_DEBUG "dumping unknown vxfs inode\n"); 34 35 printk(KERN_DEBUG "---------------------------\n"); 36 printk(KERN_DEBUG "mode is %x\n", vip->vii_mode); 37 printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n", 38 vip->vii_nlink, vip->vii_uid, vip->vii_gid); 39 printk(KERN_DEBUG "size:%Lx, blocks:%u\n", 40 vip->vii_size, vip->vii_blocks); 41 printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype); 42 } 43 #endif 44 45 /** 46 * vxfs_transmod - mode for a VxFS inode 47 * @vip: VxFS inode 48 * 49 * Description: 50 * vxfs_transmod returns a Linux mode_t for a given 51 * VxFS inode structure. 52 */ 53 static __inline__ umode_t 54 vxfs_transmod(struct vxfs_inode_info *vip) 55 { 56 umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; 57 58 if (VXFS_ISFIFO(vip)) 59 ret |= S_IFIFO; 60 if (VXFS_ISCHR(vip)) 61 ret |= S_IFCHR; 62 if (VXFS_ISDIR(vip)) 63 ret |= S_IFDIR; 64 if (VXFS_ISBLK(vip)) 65 ret |= S_IFBLK; 66 if (VXFS_ISLNK(vip)) 67 ret |= S_IFLNK; 68 if (VXFS_ISREG(vip)) 69 ret |= S_IFREG; 70 if (VXFS_ISSOC(vip)) 71 ret |= S_IFSOCK; 72 73 return (ret); 74 } 75 76 static inline void dip2vip_cpy(struct vxfs_sb_info *sbi, 77 struct vxfs_inode_info *vip, struct vxfs_dinode *dip) 78 { 79 struct inode *inode = &vip->vfs_inode; 80 81 vip->vii_mode = fs32_to_cpu(sbi, dip->vdi_mode); 82 vip->vii_nlink = fs32_to_cpu(sbi, dip->vdi_nlink); 83 vip->vii_uid = fs32_to_cpu(sbi, dip->vdi_uid); 84 vip->vii_gid = fs32_to_cpu(sbi, dip->vdi_gid); 85 vip->vii_size = fs64_to_cpu(sbi, dip->vdi_size); 86 vip->vii_atime = fs32_to_cpu(sbi, dip->vdi_atime); 87 vip->vii_autime = fs32_to_cpu(sbi, dip->vdi_autime); 88 vip->vii_mtime = fs32_to_cpu(sbi, dip->vdi_mtime); 89 vip->vii_mutime = fs32_to_cpu(sbi, dip->vdi_mutime); 90 vip->vii_ctime = fs32_to_cpu(sbi, dip->vdi_ctime); 91 vip->vii_cutime = fs32_to_cpu(sbi, dip->vdi_cutime); 92 vip->vii_orgtype = dip->vdi_orgtype; 93 94 vip->vii_blocks = fs32_to_cpu(sbi, dip->vdi_blocks); 95 vip->vii_gen = fs32_to_cpu(sbi, dip->vdi_gen); 96 97 if (VXFS_ISDIR(vip)) 98 vip->vii_dotdot = fs32_to_cpu(sbi, dip->vdi_dotdot); 99 else if (!VXFS_ISREG(vip) && !VXFS_ISLNK(vip)) 100 vip->vii_rdev = fs32_to_cpu(sbi, dip->vdi_rdev); 101 102 /* don't endian swap the fields that differ by orgtype */ 103 memcpy(&vip->vii_org, &dip->vdi_org, sizeof(vip->vii_org)); 104 105 inode->i_mode = vxfs_transmod(vip); 106 i_uid_write(inode, (uid_t)vip->vii_uid); 107 i_gid_write(inode, (gid_t)vip->vii_gid); 108 109 set_nlink(inode, vip->vii_nlink); 110 inode->i_size = vip->vii_size; 111 112 inode_set_atime(inode, vip->vii_atime, 0); 113 inode_set_ctime(inode, vip->vii_ctime, 0); 114 inode_set_mtime(inode, vip->vii_mtime, 0); 115 116 inode->i_blocks = vip->vii_blocks; 117 inode->i_generation = vip->vii_gen; 118 } 119 120 /** 121 * vxfs_blkiget - find inode based on extent # 122 * @sbp: superblock of the filesystem we search in 123 * @extent: number of the extent to search 124 * @ino: inode number to search 125 * 126 * Description: 127 * vxfs_blkiget searches inode @ino in the filesystem described by 128 * @sbp in the extent @extent. 129 * Returns the matching VxFS inode on success, else a NULL pointer. 130 * 131 * NOTE: 132 * While __vxfs_iget uses the pagecache vxfs_blkiget uses the 133 * buffercache. This function should not be used outside the 134 * read_super() method, otherwise the data may be incoherent. 135 */ 136 struct inode * 137 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) 138 { 139 struct buffer_head *bp; 140 struct inode *inode; 141 u_long block, offset; 142 143 inode = new_inode(sbp); 144 if (!inode) 145 return NULL; 146 inode->i_ino = get_next_ino(); 147 148 block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); 149 offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); 150 bp = sb_bread(sbp, block); 151 152 if (bp && buffer_mapped(bp)) { 153 struct vxfs_inode_info *vip = VXFS_INO(inode); 154 struct vxfs_dinode *dip; 155 156 dip = (struct vxfs_dinode *)(bp->b_data + offset); 157 dip2vip_cpy(VXFS_SBI(sbp), vip, dip); 158 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; 159 #ifdef DIAGNOSTIC 160 vxfs_dumpi(vip, ino); 161 #endif 162 brelse(bp); 163 return inode; 164 } 165 166 printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); 167 brelse(bp); 168 iput(inode); 169 return NULL; 170 } 171 172 /** 173 * __vxfs_iget - generic find inode facility 174 * @ilistp: inode list 175 * @vip: VxFS inode to fill in 176 * @ino: inode number 177 * 178 * Description: 179 * Search the for inode number @ino in the filesystem 180 * described by @sbp. Use the specified inode table (@ilistp). 181 * Returns the matching inode on success, else an error code. 182 */ 183 static int 184 __vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) 185 { 186 struct page *pp; 187 u_long offset; 188 189 offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; 190 pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); 191 192 if (!IS_ERR(pp)) { 193 struct vxfs_dinode *dip; 194 caddr_t kaddr = (char *)page_address(pp); 195 196 dip = (struct vxfs_dinode *)(kaddr + offset); 197 dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); 198 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; 199 #ifdef DIAGNOSTIC 200 vxfs_dumpi(vip, ino); 201 #endif 202 vxfs_put_page(pp); 203 return 0; 204 } 205 206 printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", 207 pp, (unsigned long)ino); 208 return PTR_ERR(pp); 209 } 210 211 /** 212 * vxfs_stiget - find inode using the structural inode list 213 * @sbp: VFS superblock 214 * @ino: inode # 215 * 216 * Description: 217 * Find inode @ino in the filesystem described by @sbp using 218 * the structural inode list. 219 * Returns the matching inode on success, else a NULL pointer. 220 */ 221 struct inode * 222 vxfs_stiget(struct super_block *sbp, ino_t ino) 223 { 224 struct inode *inode; 225 int error; 226 227 inode = new_inode(sbp); 228 if (!inode) 229 return NULL; 230 inode->i_ino = get_next_ino(); 231 232 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); 233 if (error) { 234 iput(inode); 235 return NULL; 236 } 237 238 return inode; 239 } 240 241 /** 242 * vxfs_iget - get an inode 243 * @sbp: the superblock to get the inode for 244 * @ino: the number of the inode to get 245 * 246 * Description: 247 * vxfs_read_inode creates an inode, reads the disk inode for @ino and fills 248 * in all relevant fields in the new inode. 249 */ 250 struct inode * 251 vxfs_iget(struct super_block *sbp, ino_t ino) 252 { 253 struct vxfs_inode_info *vip; 254 const struct address_space_operations *aops; 255 struct inode *ip; 256 int error; 257 258 ip = iget_locked(sbp, ino); 259 if (!ip) 260 return ERR_PTR(-ENOMEM); 261 if (!(ip->i_state & I_NEW)) 262 return ip; 263 264 vip = VXFS_INO(ip); 265 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); 266 if (error) { 267 iget_failed(ip); 268 return ERR_PTR(error); 269 } 270 271 if (VXFS_ISIMMED(vip)) 272 aops = &vxfs_immed_aops; 273 else 274 aops = &vxfs_aops; 275 276 if (S_ISREG(ip->i_mode)) { 277 ip->i_fop = &generic_ro_fops; 278 ip->i_mapping->a_ops = aops; 279 } else if (S_ISDIR(ip->i_mode)) { 280 ip->i_op = &vxfs_dir_inode_ops; 281 ip->i_fop = &vxfs_dir_operations; 282 ip->i_mapping->a_ops = aops; 283 } else if (S_ISLNK(ip->i_mode)) { 284 if (!VXFS_ISIMMED(vip)) { 285 ip->i_op = &page_symlink_inode_operations; 286 inode_nohighmem(ip); 287 ip->i_mapping->a_ops = &vxfs_aops; 288 } else { 289 ip->i_op = &simple_symlink_inode_operations; 290 ip->i_link = vip->vii_immed.vi_immed; 291 nd_terminate_link(ip->i_link, ip->i_size, 292 sizeof(vip->vii_immed.vi_immed) - 1); 293 } 294 } else 295 init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); 296 297 unlock_new_inode(ip); 298 return ip; 299 } 300 301 /** 302 * vxfs_evict_inode - remove inode from main memory 303 * @ip: inode to discard. 304 * 305 * Description: 306 * vxfs_evict_inode() is called on the final iput and frees the private 307 * inode area. 308 */ 309 void 310 vxfs_evict_inode(struct inode *ip) 311 { 312 truncate_inode_pages_final(&ip->i_data); 313 clear_inode(ip); 314 } 315
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.