summary refs log tree commit diff
path: root/drivers
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 11:55:42 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-26 11:55:42 -0700
commit09c0dc68625c06f5b1e786aad0d5369b592179e6 (patch)
tree19fd06de08792a4c07ee8b61e5615ee35e8ccec0 /drivers
parent2a2ed2db353d949c06b6ef8b6913f65b39111eab (diff)
downloadlinux-09c0dc68625c06f5b1e786aad0d5369b592179e6.tar.gz
Revert "[PATCH] kthread: update loop.c to use kthread"
This reverts commit c7b2eff059fcc2d1b7085ee3d84b79fd657a537b.

Hugh Dickins explains:

 "It seems too little tested: "losetup -d /dev/loop0" fails with
  EINVAL because nothing sets lo_thread; but even when you patch
  loop_thread() to set lo->lo_thread = current, it can't survive
  more than a few dozen iterations of the loop below (with a tmpfs
  mounted on /tst):

	j=0
	cp /dev/zero /tst
	while :
	do
	    let j=j+1
	    echo "Doing pass $j"
	    losetup /dev/loop0 /tst/zero
	    mkfs -t ext2 -b 1024 /dev/loop0 >/dev/null 2>&1
	    mount -t ext2 /dev/loop0 /mnt
	    umount /mnt
	    losetup -d /dev/loop0
	done

  it collapses with failed ioctl then BUG_ON(!bio).

  I think the original lo_done completion was more subtle and safe
  than the kthread conversion has allowed for."

Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/block/loop.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 9dc294a74953..3c74ea729fc7 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -74,7 +74,6 @@
 #include <linux/completion.h>
 #include <linux/highmem.h>
 #include <linux/gfp.h>
-#include <linux/kthread.h>
 
 #include <asm/uaccess.h>
 
@@ -579,6 +578,8 @@ static int loop_thread(void *data)
 	struct loop_device *lo = data;
 	struct bio *bio;
 
+	daemonize("loop%d", lo->lo_number);
+
 	/*
 	 * loop can be used in an encrypted device,
 	 * hence, it mustn't be stopped at all
@@ -591,6 +592,11 @@ static int loop_thread(void *data)
 	lo->lo_state = Lo_bound;
 	lo->lo_pending = 1;
 
+	/*
+	 * complete it, we are running
+	 */
+	complete(&lo->lo_done);
+
 	for (;;) {
 		int pending;
 
@@ -623,6 +629,7 @@ static int loop_thread(void *data)
 			break;
 	}
 
+	complete(&lo->lo_done);
 	return 0;
 }
 
@@ -739,7 +746,6 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
 	unsigned lo_blocksize;
 	int		lo_flags = 0;
 	int		error;
-	struct task_struct *tsk;
 	loff_t		size;
 
 	/* This is safe, since we have a reference from open(). */
@@ -833,11 +839,10 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
 
 	set_blocksize(bdev, lo_blocksize);
 
-	tsk = kthread_run(loop_thread, lo, "loop%d", lo->lo_number);
-	if (IS_ERR(tsk)) {
-		error = PTR_ERR(tsk);
+	error = kernel_thread(loop_thread, lo, CLONE_KERNEL);
+	if (error < 0)
 		goto out_putf;
-	}
+	wait_for_completion(&lo->lo_done);
 	return 0;
 
  out_putf:
@@ -893,9 +898,6 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 	if (lo->lo_state != Lo_bound)
 		return -ENXIO;
 
-	if (!lo->lo_thread)
-		return -EINVAL;
-
 	if (lo->lo_refcnt > 1)	/* we needed one fd for the ioctl */
 		return -EBUSY;
 
@@ -909,7 +911,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 		complete(&lo->lo_bh_done);
 	spin_unlock_irq(&lo->lo_lock);
 
-	kthread_stop(lo->lo_thread);
+	wait_for_completion(&lo->lo_done);
 
 	lo->lo_backing_file = NULL;
 
@@ -922,7 +924,6 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
 	lo->lo_sizelimit = 0;
 	lo->lo_encrypt_key_size = 0;
 	lo->lo_flags = 0;
-	lo->lo_thread = NULL;
 	memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
 	memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
 	memset(lo->lo_file_name, 0, LO_NAME_SIZE);
@@ -1287,6 +1288,7 @@ static int __init loop_init(void)
 		if (!lo->lo_queue)
 			goto out_mem4;
 		mutex_init(&lo->lo_ctl_mutex);
+		init_completion(&lo->lo_done);
 		init_completion(&lo->lo_bh_done);
 		lo->lo_number = i;
 		spin_lock_init(&lo->lo_lock);