From: Al Viro <viro@ftp.linux.org.uk>
To: Ken Chen <kenchen@google.com>
Cc: akpm@linux-foundation.org, mm-commits@vger.kernel.org,
viro@zeniv.linux.org.uk, linux-kernel@vger.kernel.org
Subject: Re: + loop-preallocate-eight-loop-devices.patch added to -mm tree
Date: Tue, 22 May 2007 02:48:22 +0100 [thread overview]
Message-ID: <20070522014822.GF4095@ftp.linux.org.uk> (raw)
In-Reply-To: <b040c32a0705211830h127dfd8dk8930de6655d37d90@mail.gmail.com>
On Mon, May 21, 2007 at 06:30:15PM -0700, Ken Chen wrote:
> On 5/21/07, Al Viro <viro@ftp.linux.org.uk> wrote:
> >On Mon, May 21, 2007 at 03:00:55PM -0700, akpm@linux-foundation.org wrote:
> >> + if (register_blkdev(LOOP_MAJOR, "loop"))
> >> + return -EIO;
> >> + blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
> >> + THIS_MODULE, loop_probe, NULL, NULL);
> >> +
> >> + for (i = 0; i < nr; i++) {
> >> + if (!loop_init_one(i))
> >> + goto err;
> >> + }
> >> +
> >> + printk(KERN_INFO "loop: module loaded\n");
> >> + return 0;
> >> +err:
> >> + loop_exit();
> >
> >This isn't good. You *can't* fail once a single disk has been registered.
> >Anyone could've opened it by now.
> >
> >IOW, you need to
> > * register region *after* you are past the point of no return
>
> That option is a lot harder than I thought. This requires an array to
> keep intermediate result of preallocated "lo" device, blk_queue, and
> disk structure before calling add_disk() or register region. And this
> array could be potentially 1 million entries. Maybe I will use
> vmalloc for it, but seems rather sick.
No, it doesn't. Really. It's easy to split; untested incremental to your
patch follows:
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 0aae8d8..2300490 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1394,16 +1394,11 @@ int loop_unregister_transfer(int number)
EXPORT_SYMBOL(loop_register_transfer);
EXPORT_SYMBOL(loop_unregister_transfer);
-static struct loop_device *loop_init_one(int i)
+static struct loop_device *loop_alloc(int i)
{
struct loop_device *lo;
struct gendisk *disk;
- list_for_each_entry(lo, &loop_devices, lo_list) {
- if (lo->lo_number == i)
- return lo;
- }
-
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
if (!lo)
goto out;
@@ -1427,8 +1422,6 @@ static struct loop_device *loop_init_one(int i)
disk->private_data = lo;
disk->queue = lo->lo_queue;
sprintf(disk->disk_name, "loop%d", i);
- add_disk(disk);
- list_add_tail(&lo->lo_list, &loop_devices);
return lo;
out_free_queue:
@@ -1439,6 +1432,23 @@ out:
return NULL;
}
+static struct loop_device *loop_init_one(int i)
+{
+ struct loop_device *lo;
+
+ list_for_each_entry(lo, &loop_devices, lo_list) {
+ if (lo->lo_number == i)
+ return lo;
+ }
+
+ lo = loop_alloc(i);
+ if (lo) {
+ add_disk(lo->lo_disk);
+ list_add_tail(&lo->lo_list, &loop_devices);
+ }
+ return lo;
+}
+
static void loop_del_one(struct loop_device *lo)
{
del_gendisk(lo->lo_disk);
@@ -1481,6 +1491,7 @@ static int __init loop_init(void)
{
int i, nr;
unsigned long range;
+ struct loop_device *lo;
/*
* loop module now has a feature to instantiate underlying device
@@ -1506,19 +1517,34 @@ static int __init loop_init(void)
if (register_blkdev(LOOP_MAJOR, "loop"))
return -EIO;
- blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
- THIS_MODULE, loop_probe, NULL, NULL);
for (i = 0; i < nr; i++) {
- if (!loop_init_one(i))
- goto err;
+ lo = loop_alloc(i);
+ if (!lo)
+ goto Enomem;
+ list_add_tail(&lo->lo_list, &loop_devices);
}
+ /* point of no return */
+
+ list_for_each_entry(lo, &loop_devices, lo_list)
+ add_disk(lo->lo_disk);
+
+ blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
+ THIS_MODULE, loop_probe, NULL, NULL);
+
printk(KERN_INFO "loop: module loaded\n");
return 0;
-err:
- loop_exit();
+
+Enomem:
printk(KERN_INFO "loop: out of memory\n");
+
+ while(!list_empty(&loop_devices)) {
+ lo = list_entry(loop_devices.next, struct loop_device, lo_list);
+ loop_del_one(lo);
+ }
+
+ unregister_blkdev(LOOP_MAJOR, "loop");
return -ENOMEM;
}
next prev parent reply other threads:[~2007-05-22 1:48 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <200705212200.l4LM0tYK021050@shell0.pdx.osdl.net>
2007-05-22 0:18 ` + loop-preallocate-eight-loop-devices.patch added to -mm tree Al Viro
2007-05-22 1:30 ` Ken Chen
2007-05-22 1:48 ` Al Viro [this message]
2007-05-22 2:14 ` Ken Chen
2007-05-22 2:40 ` Ken Chen
2007-05-22 4:18 ` Al Viro
2007-05-31 16:05 ` walt
2007-05-31 16:51 ` Ken Chen
2007-05-31 18:10 ` Andrew Morton
2007-05-31 18:23 ` Ken Chen
2007-05-31 18:34 ` Andrew Morton
2007-06-01 16:29 ` Ken Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20070522014822.GF4095@ftp.linux.org.uk \
--to=viro@ftp.linux.org.uk \
--cc=akpm@linux-foundation.org \
--cc=kenchen@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mm-commits@vger.kernel.org \
--cc=viro@zeniv.linux.org.uk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox