root/fs/efs/namei.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. efs_find_entry
  2. efs_lookup
  3. efs_nfs_get_inode
  4. efs_fh_to_dentry
  5. efs_fh_to_parent
  6. efs_get_parent

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

/* [<][>][^][v][top][bottom][index][help] */