namei.c revision 440037287c5ebb07033ab927ca16bb68c291d309
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> 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/smp_lock.h> 1205da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig#include <linux/exportfs.h> 1345254b4fb2aef51c94a7397df1e481c4137b4b97Christoph Hellwig#include "efs.h" 1405da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len) { 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)) 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_WARNING "EFS: WARNING: find_entry(): directory size not a multiple of EFS_DIRBSIZE\n"); 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(block = 0; block < inode->i_blocks; block++) { 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds bh = sb_bread(inode->i_sb, efs_bmap(inode, block)); 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!bh) { 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "EFS: find_entry(): failed to read dir block %d\n", block); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirblock = (struct efs_dir *) bh->b_data; 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (be16_to_cpu(dirblock->magic) != EFS_DIRBLK_MAGIC) { 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_ERR "EFS: find_entry(): invalid directory block\n"); 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for(slot = 0; slot < dirblock->slots; slot++) { 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds dirslot = (struct efs_dentry *) (((char *) bh->b_data) + EFS_SLOTAT(dirblock, slot)); 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds namelen = dirslot->namelen; 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds nameptr = dirslot->name; 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if ((namelen == len) && (!memcmp(name, nameptr, len))) { 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inodenum = be32_to_cpu(dirslot->inode); 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(inodenum); 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds brelse(bh); 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return(0); 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) { 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_ino_t inodenum; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct inode * inode = NULL; 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_kernel(); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds inodenum = efs_find_entry(dir, dentry->d_name.name, dentry->d_name.len); 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (inodenum) { 69298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells inode = efs_iget(dir->i_sb, inodenum); 70298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells if (IS_ERR(inode)) { 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 72298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells return ERR_CAST(inode); 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 772d8a10cd1760e7ecc07a21e409485947c68a3291Al Viro return d_splice_alias(inode, dentry); 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 8005da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstatic struct inode *efs_nfs_get_inode(struct super_block *sb, u64 ino, 8105da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig u32 generation) 825ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig{ 835ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig struct inode *inode; 845ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 855ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig if (ino == 0) 865ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig return ERR_PTR(-ESTALE); 87298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells inode = efs_iget(sb, ino); 88298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells if (IS_ERR(inode)) 89298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells return ERR_CAST(inode); 905ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 91298384cd7929a3a14d7b116095973f0d02f5d09eDavid Howells if (generation && inode->i_generation != generation) { 9205da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig iput(inode); 9305da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return ERR_PTR(-ESTALE); 945ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig } 955ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 9605da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return inode; 9705da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig} 985ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 9905da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstruct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid, 10005da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig int fh_len, int fh_type) 10105da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig{ 10205da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return generic_fh_to_dentry(sb, fid, fh_len, fh_type, 10305da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig efs_nfs_get_inode); 10405da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig} 10505da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig 10605da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwigstruct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid, 10705da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig int fh_len, int fh_type) 10805da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig{ 10905da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig return generic_fh_to_parent(sb, fid, fh_len, fh_type, 11005da08048226cefd2ecc5fe925002d3cf849c7ddChristoph Hellwig efs_nfs_get_inode); 1115ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig} 1125ca29607331fe37980dc3b488793ef8b1409b722Christoph Hellwig 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct dentry *efs_get_parent(struct dentry *child) 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 115440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig struct dentry *parent = ERR_PTR(-ENOENT); 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds efs_ino_t ino; 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds lock_kernel(); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ino = efs_find_entry(child->d_inode, "..", 2); 120440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig if (ino) 121440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig parent = d_obtain_alias(efs_iget(child->d_inode->i_sb, ino)); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds unlock_kernel(); 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 124440037287c5ebb07033ab927ca16bb68c291d309Christoph Hellwig return parent; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 126