brintos

brintos / linux-shallow public Read only

0
0
Text · 7.8 KiB · 20600e9 Raw
315 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2000-2001 Christoph Hellwig.4 * Copyright (c) 2016 Krzysztof Blaszkowski5 */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 DIAGNOSTIC23/*24 * Dump inode contents (partially).25 */26void27vxfs_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	else33		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#endif44 45/**46 * vxfs_transmod - mode for a VxFS inode47 * @vip:	VxFS inode48 *49 * Description:50 *  vxfs_transmod returns a Linux mode_t for a given51 *  VxFS inode structure.52 */53static __inline__ umode_t54vxfs_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_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 in123 * @extent:	number of the extent to search124 * @ino:	inode number to search125 *126 * Description:127 *  vxfs_blkiget searches inode @ino in the filesystem described by128 *  @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 the133 *  buffercache.  This function should not be used outside the134 *  read_super() method, otherwise the data may be incoherent.135 */136struct inode *137vxfs_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 DIAGNOSTIC160		vxfs_dumpi(vip, ino);161#endif162		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 facility174 * @ilistp:		inode list175 * @vip:		VxFS inode to fill in176 * @ino:		inode number177 *178 * Description:179 *  Search the for inode number @ino in the filesystem180 *  described by @sbp.  Use the specified inode table (@ilistp).181 *  Returns the matching inode on success, else an error code.182 */183static int184__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 DIAGNOSTIC200		vxfs_dumpi(vip, ino);201#endif202		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 list213 * @sbp:	VFS superblock214 * @ino:	inode #215 *216 * Description:217 *  Find inode @ino in the filesystem described by @sbp using218 *  the structural inode list.219 *  Returns the matching inode on success, else a NULL pointer.220 */221struct inode *222vxfs_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 inode243 * @sbp:	the superblock to get the inode for244 * @ino:	the number of the inode to get245 *246 * Description:247 *  vxfs_read_inode creates an inode, reads the disk inode for @ino and fills248 *  in all relevant fields in the new inode.249 */250struct inode *251vxfs_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	else274		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	} else295		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 memory303 * @ip:		inode to discard.304 *305 * Description:306 *  vxfs_evict_inode() is called on the final iput and frees the private307 *  inode area.308 */309void310vxfs_evict_inode(struct inode *ip)311{312	truncate_inode_pages_final(&ip->i_data);313	clear_inode(ip);314}315