11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * namei.c 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 1999 Al Smith 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Portions derived from work (c) 1995,1996 Christian Vogelgsang. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/buffer_head.h> 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/string.h> 1105da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig#include <linux/exportfs.h> 1245254b4fb2aef51c94a7397df1e481c4137b4b97Christoph Hellwig#include "efs.h" 1305da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 15ca35664031e166ed57659daace5527f16d42e40eFabian Frederickstatic efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) 16ca35664031e166ed57659daace5527f16d42e40eFabian Frederick{ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct buffer_head *bh; 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int slot, namelen; 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char *nameptr; 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct efs_dir *dirblock; 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct efs_dentry *dirslot; 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_ino_t inodenum; 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_block_t block; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inode->i_size & (EFS_DIRBSIZE-1)) 27f403d1dbac6d1ef28f553f3996d5bb5cea90ce15Fabian Frederick pr_warn("%s(): directory size not a multiple of EFS_DIRBSIZE\n", 28f403d1dbac6d1ef28f553f3996d5bb5cea90ce15Fabian Frederick __func__); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(block = 0; block < inode->i_blocks; block++) { 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bh) { 34f403d1dbac6d1ef28f553f3996d5bb5cea90ce15Fabian Frederick pr_err("%s(): failed to read dir block %d\n", 35f403d1dbac6d1ef28f553f3996d5bb5cea90ce15Fabian Frederick __func__, block); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirblock = (struct efs_dir *) bh->b_data; 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 42f403d1dbac6d1ef28f553f3996d5bb5cea90ce15Fabian Frederick pr_err("%s(): invalid directory block\n", __func__); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 44ca35664031e166ed57659daace5527f16d42e40eFabian Frederick return 0; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 47ca35664031e166ed57659daace5527f16d42e40eFabian Frederick for (slot = 0; slot < dirblock->slots; slot++) { 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds namelen = dirslot->namelen; 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nameptr = dirslot->name; 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((namelen == len) && (!memcmp(name, nameptr, len))) { 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inodenum = be32_to_cpu(dirslot->inode); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 56ca35664031e166ed57659daace5527f16d42e40eFabian Frederick return inodenum; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 61ca35664031e166ed57659daace5527f16d42e40eFabian Frederick return 0; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6400cd8dd3bf95f2cc8435b4cac01d9995635c6d0bAl Virostruct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags) 6500cd8dd3bf95f2cc8435b4cac01d9995635c6d0bAl Viro{ 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_ino_t inodenum; 67a9049376ee05bf966bfe2b081b5071326856890aAl Viro struct inode *inode = NULL; 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 70a9049376ee05bf966bfe2b081b5071326856890aAl Viro if (inodenum) 71298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells inode = efs_iget(dir->i_sb, inodenum); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 732d8a10cd1760e7ecc07a21e409485947c68a3291Al Viro return d_splice_alias(inode, dentry); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7605da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstatic struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, 7705da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig u32 generation) 785ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig{ 795ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig struct inode *inode; 805ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 815ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig if (ino == 0) 825ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig return ERR_PTR(-ESTALE); 83298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells inode = efs_iget(sb, ino); 84298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells if (IS_ERR(inode)) 85298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells return ERR_CAST(inode); 865ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 87298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells if (generation && inode->i_generation != generation) { 8805da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig iput(inode); 8905da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return ERR_PTR(-ESTALE); 905ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig } 915ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 9205da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return inode; 9305da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig} 945ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 9505da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstruct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, 9605da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig int fh_len, int fh_type) 9705da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig{ 9805da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 9905da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig efs_nfs_get_inode); 10005da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig} 10105da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig 10205da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstruct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, 10305da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig int fh_len, int fh_type) 10405da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig{ 10505da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return generic_fh_to_parent(sb, fid, fh_len, fh_type, 10605da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig efs_nfs_get_inode); 1075ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig} 1085ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dentry *efs_get_parent(struct dentry *child) 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 111440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig struct dentry *parent = ERR_PTR(-ENOENT); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_ino_t ino; 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ino = efs_find_entry(child->d_inode, "..", 2); 115440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig if (ino) 116440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 118440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig return parent; 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 120