Эх сурвалжийг харах

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
  ext3/4 with synchronous writes gets wedged by Postfix
  Fix nobh_truncate_page() to not pass stack garbage to get_block()
Linus Torvalds 16 жил өмнө
parent
commit
81ee1bad86
2 өөрчлөгдсөн 27 нэмэгдсэн , 6 устгасан
  1. 2 0
      fs/buffer.c
  2. 25 6
      fs/inode.c

+ 2 - 0
fs/buffer.c

@@ -2736,6 +2736,8 @@ has_buffers:
 		pos += blocksize;
 		pos += blocksize;
 	}
 	}
 
 
+	map_bh.b_size = blocksize;
+	map_bh.b_state = 0;
 	err = get_block(inode, iblock, &map_bh, 0);
 	err = get_block(inode, iblock, &map_bh, 0);
 	if (err)
 	if (err)
 		goto unlock;
 		goto unlock;

+ 25 - 6
fs/inode.c

@@ -1053,13 +1053,22 @@ int insert_inode_locked(struct inode *inode)
 	struct super_block *sb = inode->i_sb;
 	struct super_block *sb = inode->i_sb;
 	ino_t ino = inode->i_ino;
 	ino_t ino = inode->i_ino;
 	struct hlist_head *head = inode_hashtable + hash(sb, ino);
 	struct hlist_head *head = inode_hashtable + hash(sb, ino);
-	struct inode *old;
 
 
 	inode->i_state |= I_LOCK|I_NEW;
 	inode->i_state |= I_LOCK|I_NEW;
 	while (1) {
 	while (1) {
+		struct hlist_node *node;
+		struct inode *old = NULL;
 		spin_lock(&inode_lock);
 		spin_lock(&inode_lock);
-		old = find_inode_fast(sb, head, ino);
-		if (likely(!old)) {
+		hlist_for_each_entry(old, node, head, i_hash) {
+			if (old->i_ino != ino)
+				continue;
+			if (old->i_sb != sb)
+				continue;
+			if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))
+				continue;
+			break;
+		}
+		if (likely(!node)) {
 			hlist_add_head(&inode->i_hash, head);
 			hlist_add_head(&inode->i_hash, head);
 			spin_unlock(&inode_lock);
 			spin_unlock(&inode_lock);
 			return 0;
 			return 0;
@@ -1081,14 +1090,24 @@ int insert_inode_locked4(struct inode *inode, unsigned long hashval,
 {
 {
 	struct super_block *sb = inode->i_sb;
 	struct super_block *sb = inode->i_sb;
 	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
 	struct hlist_head *head = inode_hashtable + hash(sb, hashval);
-	struct inode *old;
 
 
 	inode->i_state |= I_LOCK|I_NEW;
 	inode->i_state |= I_LOCK|I_NEW;
 
 
 	while (1) {
 	while (1) {
+		struct hlist_node *node;
+		struct inode *old = NULL;
+
 		spin_lock(&inode_lock);
 		spin_lock(&inode_lock);
-		old = find_inode(sb, head, test, data);
-		if (likely(!old)) {
+		hlist_for_each_entry(old, node, head, i_hash) {
+			if (old->i_sb != sb)
+				continue;
+			if (!test(old, data))
+				continue;
+			if (old->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE))
+				continue;
+			break;
+		}
+		if (likely(!node)) {
 			hlist_add_head(&inode->i_hash, head);
 			hlist_add_head(&inode->i_hash, head);
 			spin_unlock(&inode_lock);
 			spin_unlock(&inode_lock);
 			return 0;
 			return 0;