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