diff options
author | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 11:55:42 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-26 11:55:42 -0700 |
commit | 09c0dc68625c06f5b1e786aad0d5369b592179e6 (patch) | |
tree | 19fd06de08792a4c07ee8b61e5615ee35e8ccec0 | |
parent | 2a2ed2db353d949c06b6ef8b6913f65b39111eab (diff) |
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>
-rw-r--r-- | drivers/block/loop.c | 24 | ||||
-rw-r--r-- | include/linux/loop.h | 2 |
2 files changed, 14 insertions, 12 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); diff --git a/include/linux/loop.h b/include/linux/loop.h index bf3d2345ce99..e76c7611d6cc 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -59,7 +59,7 @@ struct loop_device { struct bio *lo_bio; struct bio *lo_biotail; int lo_state; - struct task_struct *lo_thread; + struct completion lo_done; struct completion lo_bh_done; struct mutex lo_ctl_mutex; int lo_pending; |