1*b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * namei.c
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (c) 1999 Al Smith
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds #include <linux/buffer_head.h>
111da177e4SLinus Torvalds #include <linux/string.h>
1205da0804SChristoph Hellwig #include <linux/exportfs.h>
1345254b4fSChristoph Hellwig #include "efs.h"
1405da0804SChristoph Hellwig
151da177e4SLinus Torvalds
efs_find_entry(struct inode * inode,const char * name,int len)16ca356640SFabian Frederick static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
17ca356640SFabian Frederick {
181da177e4SLinus Torvalds struct buffer_head *bh;
191da177e4SLinus Torvalds
201da177e4SLinus Torvalds int slot, namelen;
211da177e4SLinus Torvalds char *nameptr;
221da177e4SLinus Torvalds struct efs_dir *dirblock;
231da177e4SLinus Torvalds struct efs_dentry *dirslot;
241da177e4SLinus Torvalds efs_ino_t inodenum;
251da177e4SLinus Torvalds efs_block_t block;
261da177e4SLinus Torvalds
271da177e4SLinus Torvalds if (inode->i_size & (EFS_DIRBSIZE-1))
28f403d1dbSFabian Frederick pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
29f403d1dbSFabian Frederick __func__);
301da177e4SLinus Torvalds
311da177e4SLinus Torvalds for(block = 0; block < inode->i_blocks; block++) {
321da177e4SLinus Torvalds
331da177e4SLinus Torvalds bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
341da177e4SLinus Torvalds if (!bh) {
35f403d1dbSFabian Frederick pr_err("%s(): failed to read dir block %d\n",
36f403d1dbSFabian Frederick __func__, block);
371da177e4SLinus Torvalds return 0;
381da177e4SLinus Torvalds }
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds dirblock = (struct efs_dir *) bh->b_data;
411da177e4SLinus Torvalds
421da177e4SLinus Torvalds if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
43f403d1dbSFabian Frederick pr_err("%s(): invalid directory block\n", __func__);
441da177e4SLinus Torvalds brelse(bh);
45ca356640SFabian Frederick return 0;
461da177e4SLinus Torvalds }
471da177e4SLinus Torvalds
481da177e4SLinus Torvalds for (slot = 0; slot < dirblock->slots; slot++) {
491da177e4SLinus Torvalds dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
501da177e4SLinus Torvalds
511da177e4SLinus Torvalds namelen = dirslot->namelen;
521da177e4SLinus Torvalds nameptr = dirslot->name;
531da177e4SLinus Torvalds
541da177e4SLinus Torvalds if ((namelen == len) && (!memcmp(name, nameptr, len))) {
551da177e4SLinus Torvalds inodenum = be32_to_cpu(dirslot->inode);
561da177e4SLinus Torvalds brelse(bh);
57ca356640SFabian Frederick return inodenum;
581da177e4SLinus Torvalds }
591da177e4SLinus Torvalds }
601da177e4SLinus Torvalds brelse(bh);
611da177e4SLinus Torvalds }
62ca356640SFabian Frederick return 0;
631da177e4SLinus Torvalds }
641da177e4SLinus Torvalds
efs_lookup(struct inode * dir,struct dentry * dentry,unsigned int flags)6500cd8dd3SAl Viro struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
6600cd8dd3SAl Viro {
671da177e4SLinus Torvalds efs_ino_t inodenum;
681da177e4SLinus Torvalds struct inode *inode = NULL;
691da177e4SLinus Torvalds
701da177e4SLinus Torvalds inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
71a9049376SAl Viro if (inodenum)
72298384cdSDavid Howells inode = efs_iget(dir->i_sb, inodenum);
731da177e4SLinus Torvalds
742d8a10cdSAl Viro return d_splice_alias(inode, dentry);
751da177e4SLinus Torvalds }
761da177e4SLinus Torvalds
efs_nfs_get_inode(struct super_block * sb,u64 ino,u32 generation)7705da0804SChristoph Hellwig static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
7805da0804SChristoph Hellwig u32 generation)
795ca29607SChristoph Hellwig {
805ca29607SChristoph Hellwig struct inode *inode;
815ca29607SChristoph Hellwig
825ca29607SChristoph Hellwig if (ino == 0)
835ca29607SChristoph Hellwig return ERR_PTR(-ESTALE);
84298384cdSDavid Howells inode = efs_iget(sb, ino);
85298384cdSDavid Howells if (IS_ERR(inode))
86298384cdSDavid Howells return ERR_CAST(inode);
875ca29607SChristoph Hellwig
88298384cdSDavid Howells if (generation && inode->i_generation != generation) {
895ca29607SChristoph Hellwig iput(inode);
9005da0804SChristoph Hellwig return ERR_PTR(-ESTALE);
9105da0804SChristoph Hellwig }
9205da0804SChristoph Hellwig
9305da0804SChristoph Hellwig return inode;
9405da0804SChristoph Hellwig }
9505da0804SChristoph Hellwig
efs_fh_to_dentry(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)9605da0804SChristoph Hellwig struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
9705da0804SChristoph Hellwig int fh_len, int fh_type)
9805da0804SChristoph Hellwig {
9905da0804SChristoph Hellwig return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
10005da0804SChristoph Hellwig efs_nfs_get_inode);
10105da0804SChristoph Hellwig }
10205da0804SChristoph Hellwig
efs_fh_to_parent(struct super_block * sb,struct fid * fid,int fh_len,int fh_type)10305da0804SChristoph Hellwig struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
10405da0804SChristoph Hellwig int fh_len, int fh_type)
10505da0804SChristoph Hellwig {
10605da0804SChristoph Hellwig return generic_fh_to_parent(sb, fid, fh_len, fh_type,
10705da0804SChristoph Hellwig efs_nfs_get_inode);
1085ca29607SChristoph Hellwig }
1095ca29607SChristoph Hellwig
efs_get_parent(struct dentry * child)1101da177e4SLinus Torvalds struct dentry *efs_get_parent(struct dentry *child)
1111da177e4SLinus Torvalds {
11244003728SChristoph Hellwig struct dentry *parent = ERR_PTR(-ENOENT);
1131da177e4SLinus Torvalds efs_ino_t ino;
1141da177e4SLinus Torvalds
1152b0143b5SDavid Howells ino = efs_find_entry(d_inode(child), "..", 2);
11644003728SChristoph Hellwig if (ino)
117fc64005cSAl Viro parent = d_obtain_alias(efs_iget(child->d_sb, ino));
11844003728SChristoph Hellwig
1191da177e4SLinus Torvalds return parent;
1201da177e4SLinus Torvalds }
121