vxfs_inode.c (8083B)
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 */ 26void 27vxfs_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 */ 53static __inline__ umode_t 54vxfs_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 76static 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->i_atime.tv_sec = vip->vii_atime; 113 inode->i_ctime.tv_sec = vip->vii_ctime; 114 inode->i_mtime.tv_sec = vip->vii_mtime; 115 inode->i_atime.tv_nsec = 0; 116 inode->i_ctime.tv_nsec = 0; 117 inode->i_mtime.tv_nsec = 0; 118 119 inode->i_blocks = vip->vii_blocks; 120 inode->i_generation = vip->vii_gen; 121} 122 123/** 124 * vxfs_blkiget - find inode based on extent # 125 * @sbp: superblock of the filesystem we search in 126 * @extent: number of the extent to search 127 * @ino: inode number to search 128 * 129 * Description: 130 * vxfs_blkiget searches inode @ino in the filesystem described by 131 * @sbp in the extent @extent. 132 * Returns the matching VxFS inode on success, else a NULL pointer. 133 * 134 * NOTE: 135 * While __vxfs_iget uses the pagecache vxfs_blkiget uses the 136 * buffercache. This function should not be used outside the 137 * read_super() method, otherwise the data may be incoherent. 138 */ 139struct inode * 140vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) 141{ 142 struct buffer_head *bp; 143 struct inode *inode; 144 u_long block, offset; 145 146 inode = new_inode(sbp); 147 if (!inode) 148 return NULL; 149 inode->i_ino = get_next_ino(); 150 151 block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); 152 offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); 153 bp = sb_bread(sbp, block); 154 155 if (bp && buffer_mapped(bp)) { 156 struct vxfs_inode_info *vip = VXFS_INO(inode); 157 struct vxfs_dinode *dip; 158 159 dip = (struct vxfs_dinode *)(bp->b_data + offset); 160 dip2vip_cpy(VXFS_SBI(sbp), vip, dip); 161 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; 162#ifdef DIAGNOSTIC 163 vxfs_dumpi(vip, ino); 164#endif 165 brelse(bp); 166 return inode; 167 } 168 169 printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); 170 brelse(bp); 171 iput(inode); 172 return NULL; 173} 174 175/** 176 * __vxfs_iget - generic find inode facility 177 * @ilistp: inode list 178 * @vip: VxFS inode to fill in 179 * @ino: inode number 180 * 181 * Description: 182 * Search the for inode number @ino in the filesystem 183 * described by @sbp. Use the specified inode table (@ilistp). 184 * Returns the matching inode on success, else an error code. 185 */ 186static int 187__vxfs_iget(struct inode *ilistp, struct vxfs_inode_info *vip, ino_t ino) 188{ 189 struct page *pp; 190 u_long offset; 191 192 offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; 193 pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); 194 195 if (!IS_ERR(pp)) { 196 struct vxfs_dinode *dip; 197 caddr_t kaddr = (char *)page_address(pp); 198 199 dip = (struct vxfs_dinode *)(kaddr + offset); 200 dip2vip_cpy(VXFS_SBI(ilistp->i_sb), vip, dip); 201 vip->vfs_inode.i_mapping->a_ops = &vxfs_aops; 202#ifdef DIAGNOSTIC 203 vxfs_dumpi(vip, ino); 204#endif 205 vxfs_put_page(pp); 206 return 0; 207 } 208 209 printk(KERN_WARNING "vxfs: error on page 0x%p for inode %ld\n", 210 pp, (unsigned long)ino); 211 return PTR_ERR(pp); 212} 213 214/** 215 * vxfs_stiget - find inode using the structural inode list 216 * @sbp: VFS superblock 217 * @ino: inode # 218 * 219 * Description: 220 * Find inode @ino in the filesystem described by @sbp using 221 * the structural inode list. 222 * Returns the matching inode on success, else a NULL pointer. 223 */ 224struct inode * 225vxfs_stiget(struct super_block *sbp, ino_t ino) 226{ 227 struct inode *inode; 228 int error; 229 230 inode = new_inode(sbp); 231 if (!inode) 232 return NULL; 233 inode->i_ino = get_next_ino(); 234 235 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_stilist, VXFS_INO(inode), ino); 236 if (error) { 237 iput(inode); 238 return NULL; 239 } 240 241 return inode; 242} 243 244/** 245 * vxfs_iget - get an inode 246 * @sbp: the superblock to get the inode for 247 * @ino: the number of the inode to get 248 * 249 * Description: 250 * vxfs_read_inode creates an inode, reads the disk inode for @ino and fills 251 * in all relevant fields in the new inode. 252 */ 253struct inode * 254vxfs_iget(struct super_block *sbp, ino_t ino) 255{ 256 struct vxfs_inode_info *vip; 257 const struct address_space_operations *aops; 258 struct inode *ip; 259 int error; 260 261 ip = iget_locked(sbp, ino); 262 if (!ip) 263 return ERR_PTR(-ENOMEM); 264 if (!(ip->i_state & I_NEW)) 265 return ip; 266 267 vip = VXFS_INO(ip); 268 error = __vxfs_iget(VXFS_SBI(sbp)->vsi_ilist, vip, ino); 269 if (error) { 270 iget_failed(ip); 271 return ERR_PTR(error); 272 } 273 274 if (VXFS_ISIMMED(vip)) 275 aops = &vxfs_immed_aops; 276 else 277 aops = &vxfs_aops; 278 279 if (S_ISREG(ip->i_mode)) { 280 ip->i_fop = &generic_ro_fops; 281 ip->i_mapping->a_ops = aops; 282 } else if (S_ISDIR(ip->i_mode)) { 283 ip->i_op = &vxfs_dir_inode_ops; 284 ip->i_fop = &vxfs_dir_operations; 285 ip->i_mapping->a_ops = aops; 286 } else if (S_ISLNK(ip->i_mode)) { 287 if (!VXFS_ISIMMED(vip)) { 288 ip->i_op = &page_symlink_inode_operations; 289 inode_nohighmem(ip); 290 ip->i_mapping->a_ops = &vxfs_aops; 291 } else { 292 ip->i_op = &simple_symlink_inode_operations; 293 ip->i_link = vip->vii_immed.vi_immed; 294 nd_terminate_link(ip->i_link, ip->i_size, 295 sizeof(vip->vii_immed.vi_immed) - 1); 296 } 297 } else 298 init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); 299 300 unlock_new_inode(ip); 301 return ip; 302} 303 304/** 305 * vxfs_evict_inode - remove inode from main memory 306 * @ip: inode to discard. 307 * 308 * Description: 309 * vxfs_evict_inode() is called on the final iput and frees the private 310 * inode area. 311 */ 312void 313vxfs_evict_inode(struct inode *ip) 314{ 315 truncate_inode_pages_final(&ip->i_data); 316 clear_inode(ip); 317}