^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * namei.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (c) 1999 Al Smith
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Portions derived from work (c) 1995,1996 Christian Vogelgsang.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/buffer_head.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/exportfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include "efs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) struct buffer_head *bh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) int slot, namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) char *nameptr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct efs_dir *dirblock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct efs_dentry *dirslot;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) efs_ino_t inodenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) efs_block_t block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) if (inode->i_size & (EFS_DIRBSIZE-1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) for(block = 0; block < inode->i_blocks; block++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) bh = sb_bread(inode->i_sb, efs_bmap(inode, block));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) if (!bh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) pr_err("%s(): failed to read dir block %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) __func__, block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) dirblock = (struct efs_dir *) bh->b_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) pr_err("%s(): invalid directory block\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) for (slot = 0; slot < dirblock->slots; slot++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) namelen = dirslot->namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) nameptr = dirslot->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) if ((namelen == len) && (!memcmp(name, nameptr, len))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) inodenum = be32_to_cpu(dirslot->inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return inodenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) brelse(bh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) efs_ino_t inodenum;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) struct inode *inode = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (inodenum)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) inode = efs_iget(dir->i_sb, inodenum);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return d_splice_alias(inode, dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) static struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 generation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) struct inode *inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (ino == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return ERR_PTR(-ESTALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) inode = efs_iget(sb, ino);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (IS_ERR(inode))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return ERR_CAST(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) if (generation && inode->i_generation != generation) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) iput(inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) return ERR_PTR(-ESTALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return inode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) int fh_len, int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return generic_fh_to_dentry(sb, fid, fh_len, fh_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) efs_nfs_get_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int fh_len, int fh_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) return generic_fh_to_parent(sb, fid, fh_len, fh_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) efs_nfs_get_inode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) struct dentry *efs_get_parent(struct dentry *child)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) struct dentry *parent = ERR_PTR(-ENOENT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) efs_ino_t ino;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) ino = efs_find_entry(d_inode(child), "..", 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) if (ino)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) parent = d_obtain_alias(efs_iget(child->d_sb, ino));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }