patch-2.1.45 linux/fs/ext2/namei.c

Next file: linux/fs/ext2/super.c
Previous file: linux/fs/ext2/ioctl.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.44/linux/fs/ext2/namei.c linux/fs/ext2/namei.c
@@ -155,31 +155,26 @@
 	return NULL;
 }
 
-int ext2_lookup(struct inode * dir, struct qstr *name, struct inode ** result)
+int ext2_lookup(struct inode * dir, struct dentry *dentry)
 {
-	unsigned long ino;
+	struct inode * inode;
 	struct ext2_dir_entry * de;
 	struct buffer_head * bh;
 
-	*result = NULL;
-	if (!dir)
-		return -ENOENT;
-
-	if (!S_ISDIR(dir->i_mode))
-		return -ENOTDIR;
-
-	if (name->len > EXT2_NAME_LEN)
+	if (dentry->d_name.len > EXT2_NAME_LEN)
 		return -ENAMETOOLONG;
 
-	ino = dir->i_version;
-	if (!(bh = ext2_find_entry (dir, name->name, name->len, &de)))
-		return -ENOENT;
-
-	ino = le32_to_cpu(de->inode);
-	brelse (bh);
-	if (!(*result = iget (dir->i_sb, ino)))
-		return -EACCES;
+	bh = ext2_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &de);
+	inode = NULL;
+	if (bh) {
+		unsigned long ino = le32_to_cpu(de->inode);
+		brelse (bh);
+		inode = iget(dir->i_sb, ino);
 
+		if (!inode)
+			return -EACCES;
+	}
+	d_add(dentry, inode);
 	return 0;
 }
 
@@ -252,7 +247,7 @@
 				de->inode = le32_to_cpu(0);
 				de->rec_len = le16_to_cpu(sb->s_blocksize);
 				dir->i_size = offset + sb->s_blocksize;
-				dir->i_dirt = 1;
+				mark_inode_dirty(dir);
 			} else {
 
 				ext2_debug ("skipping to next block\n");
@@ -297,7 +292,7 @@
 			 * and/or different from the directory change time.
 			 */
 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-			dir->i_dirt = 1;
+			mark_inode_dirty(dir);
 			dir->i_version = ++event;
 			mark_buffer_dirty(bh, 1);
 			*res_dir = de;
@@ -346,10 +341,10 @@
 /*
  * By the time this is called, we already have created
  * the directory cache entry for the new file, but it
- * is so far marked "D_NEGATIVE".
+ * is so far negative - it has no inode.
  *
- * If the create succeeds, remove the D_NEGATIVE flag,
- * and fill in the inode information with d_instantiate().
+ * If the create succeeds, we fill in the inode information
+ * with d_instantiate(). 
  */
 int ext2_create (struct inode * dir, struct dentry * dentry, int mode)
 {
@@ -366,11 +361,11 @@
 
 	inode->i_op = &ext2_file_inode_operations;
 	inode->i_mode = mode;
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
-		inode->i_dirt = 1;
+		mark_inode_dirty(inode);
 		iput (inode);
 		return err;
 	}
@@ -382,7 +377,7 @@
 		wait_on_buffer (bh);
 	}
 	brelse (bh);
-	d_instantiate(dentry, inode, 0);
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
@@ -423,11 +418,11 @@
 		init_fifo(inode);
 	if (S_ISBLK(mode) || S_ISCHR(mode))
 		inode->i_rdev = to_kdev_t(rdev);
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
-		inode->i_dirt = 1;
+		mark_inode_dirty(inode);
 		iput(inode);
 		return err;
 	}
@@ -439,7 +434,7 @@
 		wait_on_buffer (bh);
 	}
 	brelse(bh);
-	d_instantiate(dentry, inode, 0);
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
@@ -465,7 +460,7 @@
 	dir_block = ext2_bread (inode, 0, 1, &err);
 	if (!dir_block) {
 		inode->i_nlink--;
-		inode->i_dirt = 1;
+		mark_inode_dirty(inode);
 		iput (inode);
 		return err;
 	}
@@ -486,11 +481,11 @@
 	inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
 	if (dir->i_mode & S_ISGID)
 		inode->i_mode |= S_ISGID;
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink = 0;
-		inode->i_dirt = 1;
+		mark_inode_dirty(inode);
 		iput (inode);
 		return err;
 	}
@@ -502,8 +497,8 @@
 		wait_on_buffer (bh);
 	}
 	dir->i_nlink++;
-	dir->i_dirt = 1;
-	d_instantiate(dentry, inode, D_DIR);
+	mark_inode_dirty(dir);
+	d_instantiate(dentry, inode);
 	brelse (bh);
 	return 0;
 }
@@ -613,7 +608,7 @@
 	else if (le32_to_cpu(de->inode) != inode->i_ino)
 		retval = -ENOENT;
 	else {
-		if (atomic_read(&inode->i_count) > 1) {
+		if (inode->i_count > 1) {
 		/*
 		 * Are we deleting the last instance of a busy directory?
 		 * Better clean up if so.
@@ -640,10 +635,10 @@
 			      inode->i_nlink);
 	inode->i_version = ++event;
 	inode->i_nlink = 0;
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 	dir->i_nlink--;
 	inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	dir->i_dirt = 1;
+	mark_inode_dirty(dir);
 	d_delete(dentry);
 
 end_rmdir:
@@ -701,9 +696,9 @@
 		wait_on_buffer (bh);
 	}
 	dir->i_ctime = dir->i_mtime = CURRENT_TIME;
-	dir->i_dirt = 1;
+	mark_inode_dirty(dir);
 	inode->i_nlink--;
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 	inode->i_ctime = dir->i_ctime;
 	retval = 0;
 	d_delete(dentry);	/* This also frees the inode */
@@ -738,7 +733,7 @@
 		name_block = ext2_bread (inode, 0, 1, &err);
 		if (!name_block) {
 			inode->i_nlink--;
-			inode->i_dirt = 1;
+			mark_inode_dirty(inode);
 			iput (inode);
 			return err;
 		}
@@ -758,12 +753,12 @@
 		brelse (name_block);
 	}
 	inode->i_size = i;
-	inode->i_dirt = 1;
+	mark_inode_dirty(inode);
 
 	bh = ext2_add_entry (dir, dentry->d_name.name, dentry->d_name.len, &de, &err);
 	if (!bh) {
 		inode->i_nlink--;
-		inode->i_dirt = 1;
+		mark_inode_dirty(inode);
 		iput (inode);
 		return err;
 	}
@@ -775,7 +770,7 @@
 		wait_on_buffer (bh);
 	}
 	brelse (bh);
-	d_instantiate(dentry, inode, 0);
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
@@ -808,33 +803,31 @@
 	brelse (bh);
 	inode->i_nlink++;
 	inode->i_ctime = CURRENT_TIME;
-	inode->i_dirt = 1;
-	atomic_inc(&inode->i_count);
-	d_instantiate(dentry, inode, 0);
+	mark_inode_dirty(inode);
+	inode->i_count++;
+	d_instantiate(dentry, inode);
 	return 0;
 }
 
-static int subdir (struct inode * new_inode, struct inode * old_inode)
+/*
+ * Trivially implemented using the dcache structure
+ */
+static int subdir (struct dentry * new_dentry, struct dentry * old_dentry)
 {
-	int ino;
 	int result;
 
-	atomic_inc(&new_inode->i_count);
 	result = 0;
 	for (;;) {
-		if (new_inode == old_inode) {
-			result = 1;
-			break;
-		}
-		if (new_inode->i_dev != old_inode->i_dev)
-			break;
-		ino = new_inode->i_ino;
-		if (ext2_lookup (new_inode, &(struct qstr) { "..", 2, 0 }, &new_inode))
-			break;
-		if (new_inode->i_ino == ino)
-			break;
+		if (new_dentry != old_dentry) {
+			struct dentry * parent = new_dentry->d_parent;
+			if (parent == new_dentry)
+				break;
+			new_dentry = parent;
+			continue;
+		}
+		result = 1;
+		break;
 	}
-	iput (new_inode);
 	return result;
 }
 
@@ -842,10 +835,6 @@
 	((struct ext2_dir_entry *) ((char *) buffer + \
 	le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->inode
 
-#define PARENT_NAME(buffer) \
-	((struct ext2_dir_entry *) ((char *) buffer + \
-	le16_to_cpu(((struct ext2_dir_entry *) buffer)->rec_len)))->name
-
 /*
  * rename uses retrying to avoid race-conditions: at least they should be
  * minimal.
@@ -906,13 +895,13 @@
 		if (!S_ISDIR(old_inode->i_mode))
 			goto end_rename;
 		retval = -EINVAL;
-		if (subdir (new_dir, old_inode))
+		if (subdir(new_dentry, old_dentry))
 			goto end_rename;
 		retval = -ENOTEMPTY;
 		if (!empty_dir (new_inode))
 			goto end_rename;
 		retval = -EBUSY;
-		if (atomic_read(&new_inode->i_count) > 1)
+		if (new_inode->i_count > 1)
 			goto end_rename;
 	}
 	retval = -EPERM;
@@ -925,7 +914,7 @@
 		if (new_inode && !S_ISDIR(new_inode->i_mode))
 			goto end_rename;
 		retval = -EINVAL;
-		if (subdir (new_dir, old_inode))
+		if (subdir(new_dentry, old_dentry))
 			goto end_rename;
 		dir_bh = ext2_bread (old_inode, 0, 0, &retval);
 		if (!dir_bh)
@@ -953,21 +942,21 @@
 	if (new_inode) {
 		new_inode->i_nlink--;
 		new_inode->i_ctime = CURRENT_TIME;
-		new_inode->i_dirt = 1;
+		mark_inode_dirty(new_inode);
 	}
 	old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
-	old_dir->i_dirt = 1;
+	mark_inode_dirty(old_dir);
 	if (dir_bh) {
 		PARENT_INO(dir_bh->b_data) = le32_to_cpu(new_dir->i_ino);
 		mark_buffer_dirty(dir_bh, 1);
 		old_dir->i_nlink--;
-		old_dir->i_dirt = 1;
+		mark_inode_dirty(old_dir);
 		if (new_inode) {
 			new_inode->i_nlink--;
-			new_inode->i_dirt = 1;
+			mark_inode_dirty(new_inode);
 		} else {
 			new_dir->i_nlink++;
-			new_dir->i_dirt = 1;
+			mark_inode_dirty(new_dir);
 		}
 	}
 	mark_buffer_dirty(old_bh,  1);

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