patch-2.1.52 linux/fs/smbfs/dir.c

Next file: linux/fs/smbfs/file.c
Previous file: linux/fs/smbfs/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.51/linux/fs/smbfs/dir.c linux/fs/smbfs/dir.c
@@ -2,6 +2,7 @@
  *  dir.c
  *
  *  Copyright (C) 1995, 1996 by Paal-Kr. Engstad and Volker Lendecke
+ *  Copyright (C) 1997 by Volker Lendecke
  *
  */
 
@@ -19,35 +20,19 @@
 #include <asm/semaphore.h>
 
 static long
- smb_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count);
+smb_dir_read(struct inode *inode, struct file *filp,
+	     char *buf, unsigned long count);
 
 static int
- smb_readdir(struct inode *inode, struct file *filp,
-	     void *dirent, filldir_t filldir);
+smb_readdir(struct inode *inode, struct file *filp,
+	    void *dirent, filldir_t filldir);
 
-static struct smb_inode_info *
- smb_find_dir_inode(struct inode *parent, const char *name, int len);
-
-static int
- smb_lookup(struct inode *dir, const char *__name,
-	    int len, struct inode **result);
-
-static int
- smb_create(struct inode *dir, const char *name, int len, int mode,
-	    struct inode **result);
-
-static int
- smb_mkdir(struct inode *dir, const char *name, int len, int mode);
-
-static int
- smb_rmdir(struct inode *dir, const char *name, int len);
-
-static int
- smb_unlink(struct inode *dir, const char *name, int len);
-
-static int
- smb_rename(struct inode *old_dir, const char *old_name, int old_len,
-	    struct inode *new_dir, const char *new_name, int new_len);
+static int smb_lookup(struct inode *, struct dentry *);
+static int smb_create(struct inode *, struct dentry *, int);
+static int smb_mkdir(struct inode *, struct dentry *, int);
+static int smb_rmdir(struct inode *, struct dentry *);
+static int smb_unlink(struct inode *, struct dentry *);
+static int smb_rename(struct inode *, struct dentry *, struct inode *, struct dentry *);
 
 static struct file_operations smb_dir_operations =
 {
@@ -56,7 +41,7 @@
 	NULL,			/* write - bad */
 	smb_readdir,		/* readdir */
 	NULL,			/* poll - default */
-	smb_ioctl,		/* ioctl - default */
+	smb_ioctl,		/* ioctl */
 	NULL,			/* mmap */
 	NULL,			/* no special open code */
 	NULL,			/* no special release code */
@@ -76,6 +61,7 @@
 	NULL,			/* mknod */
 	smb_rename,		/* rename */
 	NULL,			/* readlink */
+	NULL,			/* follow_link */
 	NULL,			/* readpage */
 	NULL,			/* writepage */
 	NULL,			/* bmap */
@@ -84,100 +70,13 @@
 	NULL			/* smap */
 };
 
-static int
-strncasecmp(const char *s1, const char *s2, int len)
-{
-	int result = 0;
-
-	for (; len > 0; len -= 1)
-	{
-		char c1, c2;
-
-		c1 = (*s1 >= 'a' && *s1 <= 'z') ? *s1 - ('a' - 'A') : *s1;
-		c2 = (*s2 >= 'a' && *s2 <= 'z') ? *s2 - ('a' - 'A') : *s2;
-		s1 += 1;
-		s2 += 1;
-
-		if ((result = c1 - c2) != 0 || c1 == 0)
-		{
-			return result;
-		}
-	}
-	return result;
-}
-
-static int
-compare_filename(const struct smb_server *server,
-		 const char *s1, int len, struct smb_dirent *entry)
-{
-	if (len != entry->len)
-	{
-		return 1;
-	}
-	if (server->case_handling == CASE_DEFAULT)
-	{
-		return strncasecmp(s1, entry->name, len);
-	}
-	return strncmp(s1, entry->name, len);
-}
-
-struct smb_inode_info *
-smb_find_inode(struct smb_server *server, ino_t ino)
-{
-	struct smb_inode_info *root = &(server->root);
-	struct smb_inode_info *this = root;
-
-	do
-	{
-		if (ino == smb_info_ino(this))
-		{
-			return this;
-		}
-		this = this->next;
-	}
-	while (this != root);
-
-	return NULL;
-}
-
-static ino_t
-smb_fresh_inodes(struct smb_server *server, int no)
-{
-	static ino_t seed = 1;
-	struct smb_inode_info *root = &(server->root);
-	struct smb_inode_info *this;
-
-      retry:
-	if (seed + no <= no)
-	{
-		/* avoid inode number of 0 at wrap-around */
-		seed += no;
-	}
-	this = root;
-	do
-	{
-		/* We assume that ino_t is unsigned! */
-		if (this->finfo.f_ino - seed < no)
-		{
-			seed += no;
-			goto retry;
-		}
-		this = this->next;
-	}
-	while (this != root);
-
-	seed += no;
-
-	return seed - no;
-}
-
 static long
-smb_dir_read(struct inode *inode, struct file *filp, char *buf, unsigned long count)
+smb_dir_read(struct inode *inode, struct file *filp, char *buf,
+	     unsigned long count)
 {
 	return -EISDIR;
 }
 
-
 static unsigned long c_ino = 0;
 static kdev_t c_dev;
 static int c_size;
@@ -206,8 +105,7 @@
 }
 
 static int
-smb_refill_dir_cache(struct smb_server *server, struct inode *dir,
-		     unsigned long f_pos)
+smb_refill_dir_cache(struct inode *dir, unsigned long f_pos)
 {
 	int result;
 	static struct semaphore sem = MUTEX;
@@ -217,7 +115,7 @@
 	do
 	{
 		down(&sem);
-		result = smb_proc_readdir(server, dir, f_pos,
+		result = smb_proc_readdir(dir, f_pos,
 					  SMB_READDIR_CACHE_SIZE, c_entry);
 
 		if (result <= 0)
@@ -232,15 +130,12 @@
 		c_size = result;
 		c_last_returned_index = 0;
 
-		ino = smb_fresh_inodes(server, c_size);
+		ino = smb_invent_inos(c_size);
+
 		for (i = 0; i < c_size; i++)
-		{
-			c_entry[i].f_ino = ino;
-			ino += 1;
-		}
+			c_entry[i].attr.f_ino = ino++;
 
 		up(&sem);
-
 	}
 	while ((c_dev != dir->i_dev) || (c_ino != dir->i_ino));
 
@@ -253,15 +148,13 @@
 {
 	int result, i = 0;
 	struct smb_dirent *entry = NULL;
-	struct smb_server *server = SMB_SERVER(dir);
 
-	DPRINTK("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos);
-	DDPRINTK("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n",
+	pr_debug("smb_readdir: filp->f_pos = %d\n", (int) filp->f_pos);
+	pr_debug("smb_readdir: dir->i_ino = %ld, c_ino = %ld\n",
 		 dir->i_ino, c_ino);
 
 	if ((dir == NULL) || !S_ISDIR(dir->i_mode))
 	{
-		printk("smb_readdir: dir is NULL or not a directory\n");
 		return -EBADF;
 	}
 	if (c_entry == NULL)
@@ -270,7 +163,6 @@
 		c_entry = (struct smb_dirent *) smb_vmalloc(i);
 		if (c_entry == NULL)
 		{
-			printk("smb_readdir: no MEMORY for cache\n");
 			return -ENOMEM;
 		}
 	}
@@ -280,20 +172,17 @@
 		c_dev = 0;
 		c_seen_eof = 0;
 
-		if (filldir(dirent, ".", 1, filp->f_pos,
-			    smb_info_ino(SMB_INOP(dir))) < 0)
-		{
+		if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino) < 0)
 			return 0;
-		}
+
 		filp->f_pos += 1;
 	}
 	if (filp->f_pos == 1)
 	{
 		if (filldir(dirent, "..", 2, filp->f_pos,
-			    smb_info_ino(SMB_INOP(dir)->dir)) < 0)
-		{
+			    filp->f_dentry->d_parent->d_inode->i_ino) < 0)
 			return 0;
-		}
+
 		filp->f_pos += 1;
 	}
 	entry = smb_search_in_cache(dir, filp->f_pos);
@@ -305,7 +194,7 @@
 			/* End of directory */
 			return 0;
 		}
-		result = smb_refill_dir_cache(server, dir, filp->f_pos);
+		result = smb_refill_dir_cache(dir, filp->f_pos);
 		if (result <= 0)
 		{
 			return result;
@@ -314,35 +203,18 @@
 	}
 	while (entry < &(c_entry[c_size]))
 	{
-		/* We found it.  For getwd(), we have to return the
-		   correct inode in d_ino if the inode is currently in
-		   use. Otherwise the inode number does not
-		   matter. (You can argue a lot about this..) */
-
-		struct smb_inode_info *ino_info
-		= smb_find_dir_inode(dir, entry->name, entry->len);
+		ino_t ino = entry->attr.f_ino;
 
-		ino_t ino = entry->f_ino;
-
-		if (ino_info != NULL)
-		{
-			ino = smb_info_ino(ino_info);
-		}
-		DDPRINTK("smb_readdir: entry->name = %s\n", entry->name);
-		DDPRINTK("smb_readdir: entry->f_pos = %ld\n", entry->f_pos);
+		pr_debug("smb_readdir: entry->name = %s\n", entry->name);
 
 		if (filldir(dirent, entry->name, strlen(entry->name),
 			    entry->f_pos, ino) < 0)
-		{
 			break;
-		}
+
 		if ((dir->i_dev != c_dev) || (dir->i_ino != c_ino)
 		    || (entry->f_pos != filp->f_pos))
-		{
-			/* Someone has destroyed the cache while we slept
-			   in filldir */
 			break;
-		}
+
 		filp->f_pos += 1;
 		entry += 1;
 	}
@@ -360,7 +232,7 @@
 void
 smb_invalid_dir_cache(unsigned long ino)
 {
-	/* TODO: check for dev as well */
+	/* FIXME: check for dev as well */
 	if (ino == c_ino)
 	{
 		c_ino = 0;
@@ -378,466 +250,198 @@
 	c_entry = NULL;
 }
 
-/* Insert a NEW smb_inode_info into the inode tree of our filesystem,
-   under dir. The caller must assure that it's not already there. We
-   assume that path is allocated for us. */
-
-static struct inode *
-smb_iget(struct inode *dir, struct smb_inode_info *new_inode_info)
+static int
+smb_lookup(struct inode *dir, struct dentry *d_entry)
 {
+	struct smb_fattr finfo;
 	struct inode *inode;
-	struct smb_inode_info *root;
-
-	if ((dir == NULL) || (new_inode_info == NULL))
-	{
-		printk("smb_iget: parameter is NULL\n");
-		return NULL;
-	}
-	new_inode_info->state = SMB_INODE_LOOKED_UP;
-	new_inode_info->nused = 0;
-	new_inode_info->dir = SMB_INOP(dir);
-
-	SMB_INOP(dir)->nused += 1;
-
-	/* We have to link the new inode_info into the doubly linked
-	   list of inode_infos to make a complete linear search
-	   possible. */
-
-	root = &(SMB_SERVER(dir)->root);
-
-	new_inode_info->prev = root;
-	new_inode_info->next = root->next;
-	root->next->prev = new_inode_info;
-	root->next = new_inode_info;
-
-	if (!(inode = iget(dir->i_sb, smb_info_ino(new_inode_info))))
-	{
-		new_inode_info->next->prev = new_inode_info->prev;
-		new_inode_info->prev->next = new_inode_info->next;
-		SMB_INOP(dir)->nused -= 1;
-
-		printk("smb_iget: iget failed!");
-		return NULL;
-	}
-	return inode;
-}
+	int len = d_entry->d_name.len;
+	int error;
 
-void
-smb_free_inode_info(struct smb_inode_info *i)
-{
-	if (i == NULL)
-	{
-		printk("smb_free_inode: i == NULL\n");
-		return;
+	if (!dir || !S_ISDIR(dir->i_mode)) {
+		printk("smb_lookup: inode is NULL or not a directory\n");
+		return -ENOENT;
 	}
-	i->state = SMB_INODE_CACHED;
-	while ((i->nused == 0) && (i->state == SMB_INODE_CACHED))
-	{
-		struct smb_inode_info *dir = i->dir;
-
-		i->next->prev = i->prev;
-		i->prev->next = i->next;
 
-		smb_kfree_s(i, sizeof(struct smb_inode_info));
+	if (len > SMB_MAXNAMELEN)
+		return -ENAMETOOLONG;
 
-		if (dir == NULL)
-		{
-			return;
-		}
-		dir->nused -= 1;
-		i = dir;
-	}
-}
-
-void
-smb_init_root(struct smb_server *server)
-{
-	struct smb_inode_info *root = &(server->root);
+	error = smb_proc_getattr(dir, &(d_entry->d_name), &finfo);
 
-	root->state = SMB_INODE_LOOKED_UP;
-	root->nused = 1;
-	root->dir = NULL;
-	root->next = root->prev = root;
+	inode = NULL;
+	if (!error) {
+		error = -ENOENT;
+		finfo.f_ino = smb_invent_inos(1);
+		inode = smb_iget(dir->i_sb, &finfo);
+		if (!inode)
+			return -EACCES;
+	} else if (error != -ENOENT)
+		return error;
 
-	return;
+	d_add(d_entry, inode);
+	return 0;
 }
 
-void
-smb_free_all_inodes(struct smb_server *server)
+static int smb_create(struct inode *dir, struct dentry *dentry, int mode)
 {
-	/* Here nothing should be to do. I do not know whether it's
-	   better to leave some memory allocated or be stuck in an
-	   endless loop */
-#if 1
-	struct smb_inode_info *root = &(server->root);
+	struct smb_fattr fattr;
+	struct inode *inode;
+	int error;
 
-	if (root->next != root)
-	{
-		printk("smb_free_all_inodes: INODES LEFT!!!\n");
-	}
-	while (root->next != root)
+	if (!dir || !S_ISDIR(dir->i_mode))
 	{
-		printk("smb_free_all_inodes: freeing inode\n");
-		smb_free_inode_info(root->next);
-		/* In case we have an endless loop.. */
-		schedule();
+		printk("smb_create: inode is NULL or not a directory\n");
+		return -ENOENT;
 	}
-#endif
 
-	return;
-}
+	if (dentry->d_name.len > SMB_MAXNAMELEN)
+		return -ENAMETOOLONG;
 
-/* This has to be called when a connection has gone down, so that all
-   file-handles we got from the server are invalid */
-void
-smb_invalidate_all_inodes(struct smb_server *server)
-{
-	struct smb_inode_info *ino = &(server->root);
+	error = smb_proc_create(dir, &(dentry->d_name), 0, CURRENT_TIME);
+	if (error < 0)
+		return error;
 
-	do
-	{
-		ino->finfo.opened = 0;
-		ino = ino->next;
-	}
-	while (ino != &(server->root));
+	smb_invalid_dir_cache(dir->i_ino);
 
-	return;
-}
+	/* FIXME: In the CIFS create call we get the file in open
+         * state. Currently we close it directly again, although this
+	 * is not necessary anymore. */
 
-/* We will search the inode that belongs to this name, currently by a
-   complete linear search through the inodes belonging to this
-   filesystem. This has to be fixed. */
-static struct smb_inode_info *
-smb_find_dir_inode(struct inode *parent, const char *name, int len)
-{
-	struct smb_server *server = SMB_SERVER(parent);
-	struct smb_inode_info *dir = SMB_INOP(parent);
-	struct smb_inode_info *result = &(server->root);
+	error = smb_proc_getattr(dir, &(dentry->d_name), &fattr);
+	if (error < 0)
+		return error;
 
-	if (name == NULL)
-	{
-		return NULL;
-	}
-	if ((len == 1) && (name[0] == '.'))
-	{
-		return dir;
-	}
-	if ((len == 2) && (name[0] == '.') && (name[1] == '.'))
-	{
-		return dir->dir;
-	}
-	do
-	{
-		if (result->dir == dir)
-		{
-			if (compare_filename(server, name, len,
-					     &(result->finfo)) == 0)
-			{
-				return result;
-			}
-		}
-		result = result->next;
-	}
-	while (result != &(server->root));
+	fattr.f_ino = smb_invent_inos(1);
 
-	return NULL;
+	inode = smb_iget(dir->i_sb, &fattr);
+	if (!inode)
+		return -EACCES;
+
+	d_instantiate(dentry, inode);
+	return 0;
 }
 
 static int
-smb_lookup(struct inode *dir, const char *name, int len,
-	   struct inode **result)
+smb_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 {
-	struct smb_dirent finfo;
-	struct smb_inode_info *result_info;
+	struct smb_fattr fattr;
+	struct inode *inode;
 	int error;
-	int found_in_cache;
-
-	struct smb_inode_info *new_inode_info = NULL;
-
-	*result = NULL;
 
 	if (!dir || !S_ISDIR(dir->i_mode))
 	{
-		printk("smb_lookup: inode is NULL or not a directory.\n");
-		iput(dir);
+		printk("smb_mkdir: inode is NULL or not a directory\n");
 		return -ENOENT;
 	}
-	DDPRINTK("smb_lookup: %s\n", name);
-
-	/* Fast cheat for . */
-	if (len == 0 || (len == 1 && name[0] == '.'))
-	{
-		*result = dir;
-		return 0;
-	}
-	/* ..and for .. */
-	if (len == 2 && name[0] == '.' && name[1] == '.')
-	{
-		struct smb_inode_info *parent = SMB_INOP(dir)->dir;
-
-		if (parent->state == SMB_INODE_CACHED)
-		{
-			parent->state = SMB_INODE_LOOKED_UP;
-		}
-		*result = iget(dir->i_sb, smb_info_ino(parent));
-		iput(dir);
-		if (*result == 0)
-		{
-			return -EACCES;
-		}
-		return 0;
-	}
-	result_info = smb_find_dir_inode(dir, name, len);
-
-      in_tree:
-	if (result_info != NULL)
-	{
-		if (result_info->state == SMB_INODE_CACHED)
-		{
-			result_info->state = SMB_INODE_LOOKED_UP;
-		}
-		*result = iget(dir->i_sb, smb_info_ino(result_info));
-		iput(dir);
-
-		if (new_inode_info != NULL)
-		{
-			smb_kfree_s(new_inode_info,
-				    sizeof(struct smb_inode_info));
-		}
-		if (*result == NULL)
-		{
-			return -EACCES;
-		}
-		return 0;
-	}
-	/* If the file is in the dir cache, we do not have to ask the
-	   server. */
-	found_in_cache = 0;
 
-	if ((dir->i_dev == c_dev) && (dir->i_ino == c_ino) && (c_size != 0))
-	{
-		int first = c_last_returned_index;
-		int i;
+	if (dentry->d_name.len > SMB_MAXNAMELEN)
+		return -ENAMETOOLONG;
 
-		i = first;
-		do
-		{
-			if (compare_filename(SMB_SERVER(dir), name, len,
-					     &(c_entry[i])) == 0)
-			{
-				finfo = c_entry[i];
-				found_in_cache = 1;
-				break;
-			}
-			i = (i + 1) % c_size;
-		}
-		while (i != first);
-	}
-	if (found_in_cache == 0)
-	{
-		DPRINTK("smb_lookup: not found in cache: %s\n", name);
-		if (len > SMB_MAXNAMELEN)
-		{
-			iput(dir);
-			return -ENAMETOOLONG;
-		}
-		error = smb_proc_getattr(dir, name, len, &finfo);
-		if (error < 0)
-		{
-			iput(dir);
-			return error;
-		}
-		finfo.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
-	}
-	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
-				     GFP_KERNEL);
+	error = smb_proc_mkdir(dir, &(dentry->d_name));
+	if (error)
+		return error;
 
-	/* Here somebody else might have inserted the inode */
+	smb_invalid_dir_cache(dir->i_ino);
 
-	result_info = smb_find_dir_inode(dir, name, len);
-	if (result_info != NULL)
-	{
-		goto in_tree;
-	}
-	new_inode_info->finfo = finfo;
+	error = smb_proc_getattr(dir, &(dentry->d_name), &fattr);
+	if (error < 0)
+		return error;
 
-	DPRINTK("attr: %x\n", finfo.attr);
+	fattr.f_ino = smb_invent_inos(1);
 
-	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
-	{
-		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
-		iput(dir);
+	inode = smb_iget(dir->i_sb, &fattr);
+	if (!inode)
 		return -EACCES;
-	}
-	DDPRINTK("smb_lookup: %s => %lu\n", name, (unsigned long) result_info);
-	iput(dir);
+
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
 static int
-smb_create(struct inode *dir, const char *name, int len, int mode,
-	   struct inode **result)
+smb_rmdir(struct inode *dir, struct dentry *dentry)
 {
 	int error;
-	struct smb_dirent entry;
-	struct smb_inode_info *new_inode_info;
-
-	*result = NULL;
 
 	if (!dir || !S_ISDIR(dir->i_mode))
 	{
-		printk("smb_create: inode is NULL or not a directory\n");
-		iput(dir);
+		printk("smb_rmdir: inode is NULL or not a directory\n");
 		return -ENOENT;
 	}
-	new_inode_info = smb_kmalloc(sizeof(struct smb_inode_info),
-				     GFP_KERNEL);
-	if (new_inode_info == NULL)
-	{
-		iput(dir);
-		return -ENOMEM;
-	}
-	error = smb_proc_create(dir, name, len, 0, CURRENT_TIME);
-	if (error < 0)
-	{
-		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
-		iput(dir);
-		return error;
-	}
-	smb_invalid_dir_cache(dir->i_ino);
-
-	if ((error = smb_proc_getattr(dir, name, len, &entry)) < 0)
-	{
-		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
-		iput(dir);
-		return error;
-	}
-	entry.f_ino = smb_fresh_inodes(SMB_SERVER(dir), 1);
 
-	new_inode_info->finfo = entry;
+	if (dentry->d_name.len > NFS_MAXNAMLEN)
+		return -ENAMETOOLONG;
 
-	if ((*result = smb_iget(dir, new_inode_info)) == NULL)
-	{
-		smb_kfree_s(new_inode_info, sizeof(struct smb_inode_info));
-		iput(dir);
+	error = smb_proc_rmdir(dir, &(dentry->d_name));
+	if (error)
 		return error;
-	}
-	iput(dir);
+
+	d_delete(dentry);
 	return 0;
 }
 
 static int
-smb_mkdir(struct inode *dir, const char *name, int len, int mode)
+smb_unlink(struct inode *dir, struct dentry *dentry)
 {
 	int error;
 
 	if (!dir || !S_ISDIR(dir->i_mode))
 	{
-		iput(dir);
-		return -EINVAL;
-	}
-	if ((error = smb_proc_mkdir(dir, name, len)) == 0)
-	{
-		smb_invalid_dir_cache(dir->i_ino);
+		printk("smb_unlink: inode is NULL or not a directory\n");
+		return -ENOENT;
 	}
-	iput(dir);
-	return error;
-}
 
-static int
-smb_rmdir(struct inode *dir, const char *name, int len)
-{
-	int error;
+	if (dentry->d_name.len > SMB_MAXNAMELEN)
+		return -ENAMETOOLONG;
 
-	if (!dir || !S_ISDIR(dir->i_mode))
-	{
-		printk("smb_rmdir: inode is NULL or not a directory\n");
-		iput(dir);
-		return -ENOENT;
-	}
-	if (smb_find_dir_inode(dir, name, len) != NULL)
-	{
-		error = -EBUSY;
-	} else
-	{
-		if ((error = smb_proc_rmdir(dir, name, len)) == 0)
-		{
-			smb_invalid_dir_cache(dir->i_ino);
-		}
-	}
-	iput(dir);
-	return error;
-}
+	error = smb_proc_unlink(dir, &(dentry->d_name));
+	if (error)
+		return error;
 
-static int
-smb_unlink(struct inode *dir, const char *name, int len)
-{
-	int error;
+	smb_invalid_dir_cache(dir->i_ino);
 
-	if (!dir || !S_ISDIR(dir->i_mode))
-	{
-		printk("smb_unlink: inode is NULL or not a directory\n");
-		iput(dir);
-		return -ENOENT;
-	}
-	if (smb_find_dir_inode(dir, name, len) != NULL)
-	{
-		error = -EBUSY;
-	} else
-	{
-		if ((error = smb_proc_unlink(dir, name, len)) == 0)
-		{
-			smb_invalid_dir_cache(dir->i_ino);
-		}
-	}
-	iput(dir);
-	return error;
+	d_delete(dentry);
+	return 0;
 }
 
-static int
-smb_rename(struct inode *old_dir, const char *old_name, int old_len,
-	   struct inode *new_dir, const char *new_name, int new_len)
+static int smb_rename(struct inode *old_dir, struct dentry *old_dentry,
+		      struct inode *new_dir, struct dentry *new_dentry)
 {
-	int res;
+	int error;
 
 	if (!old_dir || !S_ISDIR(old_dir->i_mode))
 	{
 		printk("smb_rename: old inode is NULL or not a directory\n");
-		res = -ENOENT;
-		goto finished;
+		return -ENOENT;
 	}
+
 	if (!new_dir || !S_ISDIR(new_dir->i_mode))
 	{
 		printk("smb_rename: new inode is NULL or not a directory\n");
-		res = -ENOENT;
-		goto finished;
-	}
-	if ((smb_find_dir_inode(old_dir, old_name, old_len) != NULL)
-	    || (smb_find_dir_inode(new_dir, new_name, new_len) != NULL))
-	{
-		res = -EBUSY;
-		goto finished;
+		return -ENOENT;
 	}
-	res = smb_proc_mv(old_dir, old_name, old_len,
-			  new_dir, new_name, new_len);
 
-	if (res == -EEXIST)
-	{
-		int res1 = smb_proc_unlink(old_dir, new_name, new_len);
+	if (old_dentry->d_name.len > SMB_MAXNAMELEN ||
+	    new_dentry->d_name.len > SMB_MAXNAMELEN)
+		return -ENAMETOOLONG;
+
+	error = smb_proc_mv(old_dir, &(old_dentry->d_name),
+			    new_dir, &(new_dentry->d_name));
+
+	if (error == -EEXIST)
+	{
+		error = smb_proc_unlink(old_dir, &(new_dentry->d_name));
+					
+		if (error)
+			return error;
 
-		if (res1 == 0)
-		{
-			res = smb_proc_mv(old_dir, old_name, old_len,
-					  new_dir, new_name, new_len);
-		}
-	}
-	if (res == 0)
-	{
-		smb_invalid_dir_cache(old_dir->i_ino);
-		smb_invalid_dir_cache(new_dir->i_ino);
+		error = smb_proc_mv(old_dir, &(old_dentry->d_name),
+				    new_dir, &(new_dentry->d_name));
 	}
-      finished:
-	iput(old_dir);
-	iput(new_dir);
-	return res;
+
+	if (error)
+		return error;
+
+	smb_invalid_dir_cache(old_dir->i_ino);
+	smb_invalid_dir_cache(new_dir->i_ino);
+	return 0;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov