cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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}