1 /* 2 * Copyright (c) 2000-2001 Christoph Hellwig. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions, and the following disclaimer, 10 * without modification. 11 * 2. The name of the author may not be used to endorse or promote products 12 * derived from this software without specific prior written permission. 13 * 14 * Alternatively, this software may be distributed under the terms of the 15 * GNU General Public License ("GPL"). 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * Veritas filesystem driver - inode routines. 32 */ 33 #include <linux/fs.h> 34 #include <linux/buffer_head.h> 35 #include <linux/pagemap.h> 36 #include <linux/kernel.h> 37 #include <linux/slab.h> 38 #include <linux/namei.h> 39 40 #include "vxfs.h" 41 #include "vxfs_inode.h" 42 #include "vxfs_extern.h" 43 44 45 struct kmem_cache *vxfs_inode_cachep; 46 47 48 #ifdef DIAGNOSTIC 49 /* 50 * Dump inode contents (partially). 51 */ 52 void 53 vxfs_dumpi(struct vxfs_inode_info *vip, ino_t ino) 54 { 55 printk(KERN_DEBUG "\n\n"); 56 if (ino) 57 printk(KERN_DEBUG "dumping vxfs inode %ld\n", ino); 58 else 59 printk(KERN_DEBUG "dumping unknown vxfs inode\n"); 60 61 printk(KERN_DEBUG "---------------------------\n"); 62 printk(KERN_DEBUG "mode is %x\n", vip->vii_mode); 63 printk(KERN_DEBUG "nlink:%u, uid:%u, gid:%u\n", 64 vip->vii_nlink, vip->vii_uid, vip->vii_gid); 65 printk(KERN_DEBUG "size:%Lx, blocks:%u\n", 66 vip->vii_size, vip->vii_blocks); 67 printk(KERN_DEBUG "orgtype:%u\n", vip->vii_orgtype); 68 } 69 #endif 70 71 72 /** 73 * vxfs_blkiget - find inode based on extent # 74 * @sbp: superblock of the filesystem we search in 75 * @extent: number of the extent to search 76 * @ino: inode number to search 77 * 78 * Description: 79 * vxfs_blkiget searches inode @ino in the filesystem described by 80 * @sbp in the extent @extent. 81 * Returns the matching VxFS inode on success, else a NULL pointer. 82 * 83 * NOTE: 84 * While __vxfs_iget uses the pagecache vxfs_blkiget uses the 85 * buffercache. This function should not be used outside the 86 * read_super() method, otherwise the data may be incoherent. 87 */ 88 struct vxfs_inode_info * 89 vxfs_blkiget(struct super_block *sbp, u_long extent, ino_t ino) 90 { 91 struct buffer_head *bp; 92 u_long block, offset; 93 94 block = extent + ((ino * VXFS_ISIZE) / sbp->s_blocksize); 95 offset = ((ino % (sbp->s_blocksize / VXFS_ISIZE)) * VXFS_ISIZE); 96 bp = sb_bread(sbp, block); 97 98 if (bp && buffer_mapped(bp)) { 99 struct vxfs_inode_info *vip; 100 struct vxfs_dinode *dip; 101 102 if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) 103 goto fail; 104 dip = (struct vxfs_dinode *)(bp->b_data + offset); 105 memcpy(vip, dip, sizeof(*vip)); 106 #ifdef DIAGNOSTIC 107 vxfs_dumpi(vip, ino); 108 #endif 109 brelse(bp); 110 return (vip); 111 } 112 113 fail: 114 printk(KERN_WARNING "vxfs: unable to read block %ld\n", block); 115 brelse(bp); 116 return NULL; 117 } 118 119 /** 120 * __vxfs_iget - generic find inode facility 121 * @sbp: VFS superblock 122 * @ino: inode number 123 * @ilistp: inode list 124 * 125 * Description: 126 * Search the for inode number @ino in the filesystem 127 * described by @sbp. Use the specified inode table (@ilistp). 128 * Returns the matching VxFS inode on success, else an error code. 129 */ 130 static struct vxfs_inode_info * 131 __vxfs_iget(ino_t ino, struct inode *ilistp) 132 { 133 struct page *pp; 134 u_long offset; 135 136 offset = (ino % (PAGE_SIZE / VXFS_ISIZE)) * VXFS_ISIZE; 137 pp = vxfs_get_page(ilistp->i_mapping, ino * VXFS_ISIZE / PAGE_SIZE); 138 139 if (!IS_ERR(pp)) { 140 struct vxfs_inode_info *vip; 141 struct vxfs_dinode *dip; 142 caddr_t kaddr = (char *)page_address(pp); 143 144 if (!(vip = kmem_cache_alloc(vxfs_inode_cachep, GFP_KERNEL))) 145 goto fail; 146 dip = (struct vxfs_dinode *)(kaddr + offset); 147 memcpy(vip, dip, sizeof(*vip)); 148 #ifdef DIAGNOSTIC 149 vxfs_dumpi(vip, ino); 150 #endif 151 vxfs_put_page(pp); 152 return (vip); 153 } 154 155 printk(KERN_WARNING "vxfs: error on page %p\n", pp); 156 return ERR_CAST(pp); 157 158 fail: 159 printk(KERN_WARNING "vxfs: unable to read inode %ld\n", (unsigned long)ino); 160 vxfs_put_page(pp); 161 return ERR_PTR(-ENOMEM); 162 } 163 164 /** 165 * vxfs_stiget - find inode using the structural inode list 166 * @sbp: VFS superblock 167 * @ino: inode # 168 * 169 * Description: 170 * Find inode @ino in the filesystem described by @sbp using 171 * the structural inode list. 172 * Returns the matching VxFS inode on success, else a NULL pointer. 173 */ 174 struct vxfs_inode_info * 175 vxfs_stiget(struct super_block *sbp, ino_t ino) 176 { 177 struct vxfs_inode_info *vip; 178 179 vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_stilist); 180 return IS_ERR(vip) ? NULL : vip; 181 } 182 183 /** 184 * vxfs_transmod - mode for a VxFS inode 185 * @vip: VxFS inode 186 * 187 * Description: 188 * vxfs_transmod returns a Linux mode_t for a given 189 * VxFS inode structure. 190 */ 191 static __inline__ umode_t 192 vxfs_transmod(struct vxfs_inode_info *vip) 193 { 194 umode_t ret = vip->vii_mode & ~VXFS_TYPE_MASK; 195 196 if (VXFS_ISFIFO(vip)) 197 ret |= S_IFIFO; 198 if (VXFS_ISCHR(vip)) 199 ret |= S_IFCHR; 200 if (VXFS_ISDIR(vip)) 201 ret |= S_IFDIR; 202 if (VXFS_ISBLK(vip)) 203 ret |= S_IFBLK; 204 if (VXFS_ISLNK(vip)) 205 ret |= S_IFLNK; 206 if (VXFS_ISREG(vip)) 207 ret |= S_IFREG; 208 if (VXFS_ISSOC(vip)) 209 ret |= S_IFSOCK; 210 211 return (ret); 212 } 213 214 /** 215 * vxfs_iinit- helper to fill inode fields 216 * @ip: VFS inode 217 * @vip: VxFS inode 218 * 219 * Description: 220 * vxfs_instino is a helper function to fill in all relevant 221 * fields in @ip from @vip. 222 */ 223 static void 224 vxfs_iinit(struct inode *ip, struct vxfs_inode_info *vip) 225 { 226 227 ip->i_mode = vxfs_transmod(vip); 228 i_uid_write(ip, (uid_t)vip->vii_uid); 229 i_gid_write(ip, (gid_t)vip->vii_gid); 230 231 set_nlink(ip, vip->vii_nlink); 232 ip->i_size = vip->vii_size; 233 234 ip->i_atime.tv_sec = vip->vii_atime; 235 ip->i_ctime.tv_sec = vip->vii_ctime; 236 ip->i_mtime.tv_sec = vip->vii_mtime; 237 ip->i_atime.tv_nsec = 0; 238 ip->i_ctime.tv_nsec = 0; 239 ip->i_mtime.tv_nsec = 0; 240 241 ip->i_blocks = vip->vii_blocks; 242 ip->i_generation = vip->vii_gen; 243 244 ip->i_private = vip; 245 246 } 247 248 /** 249 * vxfs_get_fake_inode - get fake inode structure 250 * @sbp: filesystem superblock 251 * @vip: fspriv inode 252 * 253 * Description: 254 * vxfs_fake_inode gets a fake inode (not in the inode hash) for a 255 * superblock, vxfs_inode pair. 256 * Returns the filled VFS inode. 257 */ 258 struct inode * 259 vxfs_get_fake_inode(struct super_block *sbp, struct vxfs_inode_info *vip) 260 { 261 struct inode *ip = NULL; 262 263 if ((ip = new_inode(sbp))) { 264 ip->i_ino = get_next_ino(); 265 vxfs_iinit(ip, vip); 266 ip->i_mapping->a_ops = &vxfs_aops; 267 } 268 return (ip); 269 } 270 271 /** 272 * vxfs_put_fake_inode - free faked inode 273 * *ip: VFS inode 274 * 275 * Description: 276 * vxfs_put_fake_inode frees all data associated with @ip. 277 */ 278 void 279 vxfs_put_fake_inode(struct inode *ip) 280 { 281 iput(ip); 282 } 283 284 /** 285 * vxfs_iget - get an inode 286 * @sbp: the superblock to get the inode for 287 * @ino: the number of the inode to get 288 * 289 * Description: 290 * vxfs_read_inode creates an inode, reads the disk inode for @ino and fills 291 * in all relevant fields in the new inode. 292 */ 293 struct inode * 294 vxfs_iget(struct super_block *sbp, ino_t ino) 295 { 296 struct vxfs_inode_info *vip; 297 const struct address_space_operations *aops; 298 struct inode *ip; 299 300 ip = iget_locked(sbp, ino); 301 if (!ip) 302 return ERR_PTR(-ENOMEM); 303 if (!(ip->i_state & I_NEW)) 304 return ip; 305 306 vip = __vxfs_iget(ino, VXFS_SBI(sbp)->vsi_ilist); 307 if (IS_ERR(vip)) { 308 iget_failed(ip); 309 return ERR_CAST(vip); 310 } 311 312 vxfs_iinit(ip, vip); 313 314 if (VXFS_ISIMMED(vip)) 315 aops = &vxfs_immed_aops; 316 else 317 aops = &vxfs_aops; 318 319 if (S_ISREG(ip->i_mode)) { 320 ip->i_fop = &generic_ro_fops; 321 ip->i_mapping->a_ops = aops; 322 } else if (S_ISDIR(ip->i_mode)) { 323 ip->i_op = &vxfs_dir_inode_ops; 324 ip->i_fop = &vxfs_dir_operations; 325 ip->i_mapping->a_ops = aops; 326 } else if (S_ISLNK(ip->i_mode)) { 327 if (!VXFS_ISIMMED(vip)) { 328 ip->i_op = &page_symlink_inode_operations; 329 ip->i_mapping->a_ops = &vxfs_aops; 330 } else { 331 ip->i_op = &simple_symlink_inode_operations; 332 ip->i_link = vip->vii_immed.vi_immed; 333 nd_terminate_link(ip->i_link, ip->i_size, 334 sizeof(vip->vii_immed.vi_immed) - 1); 335 } 336 } else 337 init_special_inode(ip, ip->i_mode, old_decode_dev(vip->vii_rdev)); 338 339 unlock_new_inode(ip); 340 return ip; 341 } 342 343 static void vxfs_i_callback(struct rcu_head *head) 344 { 345 struct inode *inode = container_of(head, struct inode, i_rcu); 346 kmem_cache_free(vxfs_inode_cachep, inode->i_private); 347 } 348 349 /** 350 * vxfs_evict_inode - remove inode from main memory 351 * @ip: inode to discard. 352 * 353 * Description: 354 * vxfs_evict_inode() is called on the final iput and frees the private 355 * inode area. 356 */ 357 void 358 vxfs_evict_inode(struct inode *ip) 359 { 360 truncate_inode_pages_final(&ip->i_data); 361 clear_inode(ip); 362 call_rcu(&ip->i_rcu, vxfs_i_callback); 363 } 364