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_lookup.c (6013B)


      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 - lookup and other directory related code.
      9 */
     10#include <linux/fs.h>
     11#include <linux/time.h>
     12#include <linux/mm.h>
     13#include <linux/highmem.h>
     14#include <linux/kernel.h>
     15#include <linux/pagemap.h>
     16
     17#include "vxfs.h"
     18#include "vxfs_dir.h"
     19#include "vxfs_inode.h"
     20#include "vxfs_extern.h"
     21
     22/*
     23 * Number of VxFS blocks per page.
     24 */
     25#define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_SIZE / (sbp)->s_blocksize))
     26
     27
     28static struct dentry *	vxfs_lookup(struct inode *, struct dentry *, unsigned int);
     29static int		vxfs_readdir(struct file *, struct dir_context *);
     30
     31const struct inode_operations vxfs_dir_inode_ops = {
     32	.lookup =		vxfs_lookup,
     33};
     34
     35const struct file_operations vxfs_dir_operations = {
     36	.llseek =		generic_file_llseek,
     37	.read =			generic_read_dir,
     38	.iterate_shared =	vxfs_readdir,
     39};
     40
     41
     42/**
     43 * vxfs_find_entry - find a mathing directory entry for a dentry
     44 * @ip:		directory inode
     45 * @dp:		dentry for which we want to find a direct
     46 * @ppp:	gets filled with the page the return value sits in
     47 *
     48 * Description:
     49 *   vxfs_find_entry finds a &struct vxfs_direct for the VFS directory
     50 *   cache entry @dp.  @ppp will be filled with the page the return
     51 *   value resides in.
     52 *
     53 * Returns:
     54 *   The wanted direct on success, else a NULL pointer.
     55 */
     56static struct vxfs_direct *
     57vxfs_find_entry(struct inode *ip, struct dentry *dp, struct page **ppp)
     58{
     59	u_long bsize = ip->i_sb->s_blocksize;
     60	const char *name = dp->d_name.name;
     61	int namelen = dp->d_name.len;
     62	loff_t limit = VXFS_DIRROUND(ip->i_size);
     63	struct vxfs_direct *de_exit = NULL;
     64	loff_t pos = 0;
     65	struct vxfs_sb_info *sbi = VXFS_SBI(ip->i_sb);
     66
     67	while (pos < limit) {
     68		struct page *pp;
     69		char *kaddr;
     70		int pg_ofs = pos & ~PAGE_MASK;
     71
     72		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
     73		if (IS_ERR(pp))
     74			return NULL;
     75		kaddr = (char *)page_address(pp);
     76
     77		while (pg_ofs < PAGE_SIZE && pos < limit) {
     78			struct vxfs_direct *de;
     79
     80			if ((pos & (bsize - 1)) < 4) {
     81				struct vxfs_dirblk *dbp =
     82					(struct vxfs_dirblk *)
     83					 (kaddr + (pos & ~PAGE_MASK));
     84				int overhead = VXFS_DIRBLKOV(sbi, dbp);
     85
     86				pos += overhead;
     87				pg_ofs += overhead;
     88			}
     89			de = (struct vxfs_direct *)(kaddr + pg_ofs);
     90
     91			if (!de->d_reclen) {
     92				pos += bsize - 1;
     93				pos &= ~(bsize - 1);
     94				break;
     95			}
     96
     97			pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
     98			pos += fs16_to_cpu(sbi, de->d_reclen);
     99			if (!de->d_ino)
    100				continue;
    101
    102			if (namelen != fs16_to_cpu(sbi, de->d_namelen))
    103				continue;
    104			if (!memcmp(name, de->d_name, namelen)) {
    105				*ppp = pp;
    106				de_exit = de;
    107				break;
    108			}
    109		}
    110		if (!de_exit)
    111			vxfs_put_page(pp);
    112		else
    113			break;
    114	}
    115
    116	return de_exit;
    117}
    118
    119/**
    120 * vxfs_inode_by_name - find inode number for dentry
    121 * @dip:	directory to search in
    122 * @dp:		dentry we search for
    123 *
    124 * Description:
    125 *   vxfs_inode_by_name finds out the inode number of
    126 *   the path component described by @dp in @dip.
    127 *
    128 * Returns:
    129 *   The wanted inode number on success, else Zero.
    130 */
    131static ino_t
    132vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
    133{
    134	struct vxfs_direct		*de;
    135	struct page			*pp;
    136	ino_t				ino = 0;
    137
    138	de = vxfs_find_entry(dip, dp, &pp);
    139	if (de) {
    140		ino = fs32_to_cpu(VXFS_SBI(dip->i_sb), de->d_ino);
    141		kunmap(pp);
    142		put_page(pp);
    143	}
    144	
    145	return (ino);
    146}
    147
    148/**
    149 * vxfs_lookup - lookup pathname component
    150 * @dip:	dir in which we lookup
    151 * @dp:		dentry we lookup
    152 * @flags:	lookup flags
    153 *
    154 * Description:
    155 *   vxfs_lookup tries to lookup the pathname component described
    156 *   by @dp in @dip.
    157 *
    158 * Returns:
    159 *   A NULL-pointer on success, else a negative error code encoded
    160 *   in the return pointer.
    161 */
    162static struct dentry *
    163vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
    164{
    165	struct inode		*ip = NULL;
    166	ino_t			ino;
    167			 
    168	if (dp->d_name.len > VXFS_NAMELEN)
    169		return ERR_PTR(-ENAMETOOLONG);
    170				 
    171	ino = vxfs_inode_by_name(dip, dp);
    172	if (ino)
    173		ip = vxfs_iget(dip->i_sb, ino);
    174	return d_splice_alias(ip, dp);
    175}
    176
    177/**
    178 * vxfs_readdir - read a directory
    179 * @fp:		the directory to read
    180 * @retp:	return buffer
    181 * @filler:	filldir callback
    182 *
    183 * Description:
    184 *   vxfs_readdir fills @retp with directory entries from @fp
    185 *   using the VFS supplied callback @filler.
    186 *
    187 * Returns:
    188 *   Zero.
    189 */
    190static int
    191vxfs_readdir(struct file *fp, struct dir_context *ctx)
    192{
    193	struct inode		*ip = file_inode(fp);
    194	struct super_block	*sbp = ip->i_sb;
    195	u_long			bsize = sbp->s_blocksize;
    196	loff_t			pos, limit;
    197	struct vxfs_sb_info	*sbi = VXFS_SBI(sbp);
    198
    199	if (ctx->pos == 0) {
    200		if (!dir_emit_dot(fp, ctx))
    201			goto out;
    202		ctx->pos++;
    203	}
    204	if (ctx->pos == 1) {
    205		if (!dir_emit(ctx, "..", 2, VXFS_INO(ip)->vii_dotdot, DT_DIR))
    206			goto out;
    207		ctx->pos++;
    208	}
    209
    210	limit = VXFS_DIRROUND(ip->i_size);
    211	if (ctx->pos > limit)
    212		goto out;
    213
    214	pos = ctx->pos & ~3L;
    215
    216	while (pos < limit) {
    217		struct page *pp;
    218		char *kaddr;
    219		int pg_ofs = pos & ~PAGE_MASK;
    220		int rc = 0;
    221
    222		pp = vxfs_get_page(ip->i_mapping, pos >> PAGE_SHIFT);
    223		if (IS_ERR(pp))
    224			return -ENOMEM;
    225
    226		kaddr = (char *)page_address(pp);
    227
    228		while (pg_ofs < PAGE_SIZE && pos < limit) {
    229			struct vxfs_direct *de;
    230
    231			if ((pos & (bsize - 1)) < 4) {
    232				struct vxfs_dirblk *dbp =
    233					(struct vxfs_dirblk *)
    234					 (kaddr + (pos & ~PAGE_MASK));
    235				int overhead = VXFS_DIRBLKOV(sbi, dbp);
    236
    237				pos += overhead;
    238				pg_ofs += overhead;
    239			}
    240			de = (struct vxfs_direct *)(kaddr + pg_ofs);
    241
    242			if (!de->d_reclen) {
    243				pos += bsize - 1;
    244				pos &= ~(bsize - 1);
    245				break;
    246			}
    247
    248			pg_ofs += fs16_to_cpu(sbi, de->d_reclen);
    249			pos += fs16_to_cpu(sbi, de->d_reclen);
    250			if (!de->d_ino)
    251				continue;
    252
    253			rc = dir_emit(ctx, de->d_name,
    254					fs16_to_cpu(sbi, de->d_namelen),
    255					fs32_to_cpu(sbi, de->d_ino),
    256					DT_UNKNOWN);
    257			if (!rc) {
    258				/* the dir entry was not read, fix pos. */
    259				pos -= fs16_to_cpu(sbi, de->d_reclen);
    260				break;
    261			}
    262		}
    263		vxfs_put_page(pp);
    264		if (!rc)
    265			break;
    266	}
    267
    268	ctx->pos = pos | 2;
    269
    270out:
    271	return 0;
    272}