Skip to contentSkip to conversation

loop: add management interface for on-demand device allocation

PATCH In review Kay Sievers 2 participants 4 messages Jul 26, 2011 – Jul 30, 2011

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 loop: add management interface for on-demand device allocation

From: Kay Sievers <[email protected]>
Subject: loop: add management interface for on-demand device allocation

Loop devices today have a fixed pre-allocated number of usually 8. The number can only be changed at init time. To find a free device to use, /dev/loop%i needs to be scanned and all devices need to be opened.

This adds a new /dev/loop-control device node allows to dynamically request new, and to add and remove loop devices from the running system:
LOOP_CTL_ADD adds a specific device. Arg is the number of the device. It returns the device nr or a negative error code.

LOOP_CTL_REMOVE removes a specific device, Arg is the number the device. It returns the device nr or a negative error code.

LOOP_CTL_GET_FREE finds the next unbound device or allocates a new one. No arg is given. It returns the device nr or a negative error code.

The loop kernel module gets automatically loaded when /dev/loop-control is accessed the first time. The alias specified in the module, instructs udev to create this device node, even when the module is not loaded.

A kernel config option BLK_DEV_LOOP_MIN_COUNT is introduced to allow setups without any pre-created dead loop device, if none is needed. The default is the historic value of 8.

The linked list to keep track of allocated loop devices is replaced by a more efficient idr index.

Example:
cfd = open("/dev/loop-control", O_RDWR);

  # add a new specific loop device
  err = ioctl(cfd, LOOP_CTL_ADD, devnr);
  # remove a specific loop device
  err = ioctl(cfd, LOOP_CTL_REMOVE, devnr);
  # find or allocate a free loop device to use
  devnr = ioctl(cfd, LOOP_CTL_GET_FREE);
  sprintf(loopname, "/dev/loop%i", devnr);
  ffd = open("backing-file", O_RDWR);
  lfd = open(loopname, O_RDWR);
  err = ioctl(lfd, LOOP_SET_FD, ffd);

---

 Documentation/kernel-parameters.txt |   13 -
 drivers/block/Kconfig               |   15 +
 drivers/block/loop.c                |  361 +++++++++++++++++++++++-------------
 include/linux/loop.h                |   10 
 include/linux/miscdevice.h          |    1 
 5 files changed, 266 insertions(+), 134 deletions(-)
Documentation/kernel-parameters.txt +9 -4
index 40cc653..504471b 100644
@@ -1289,6 +1289,15 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			kernel log messages and is useful when debugging
 			kernel boot problems.
 
+	loop.max_loop=	[LOOP] The number of loop block devices that get
+	(max_loop)	unconditionally pre-created at init time. The default
+			number is configured by BLK_DEV_LOOP_MIN_COUNT. Loop
+			devices can be requested on-demand with the
+			/dev/loop-control interface.
+
+	loop.max_part=	[LOOP] Maximum possible number of partitions to create
+			per loop device.
+
 	lp=0		[LP]	Specify parallel ports to use, e.g,
 	lp=port[,port...]	lp=none,parport0 (lp0 not configured, lp1 uses
 	lp=reset		first parallel port). 'lp=0' disables the
@@ -1340,10 +1349,6 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			it is equivalent to "nosmp", which also disables
 			the IO APIC.
 
-	max_loop=	[LOOP] Maximum number of loopback devices that can
-			be mounted
-			Format: <1-256>
-
 	mcatest=	[IA-64]
 
 	mce		[X86-32] Machine Check Exception
drivers/block/Kconfig +14 -1
index 717d6e4..a382ab5 100644
@@ -254,7 +254,20 @@ config BLK_DEV_LOOP
 	  To compile this driver as a module, choose M here: the
 	  module will be called loop.
 
-	  Most users will answer N here.
+config BLK_DEV_LOOP_MIN_COUNT
+	int "Number of loop devices to pre-create at init time"
+	depends on BLK_DEV_LOOP
+	default 8
+	help
+	  Number of loop devices to be unconditionally pre-created at
+	  init time.
+
+	  This default value can be overwritten on the kernel command
+	  line or with module-parameter loop.max_loop.
+
+	  The historic default is 8, if a late 2011 version of losetup(8)
+	  is used, it can be set to 0, since needed loop devices can be
+	  dynamically allocated with the /dev/loop-control interface.
 
 config BLK_DEV_CRYPTOLOOP
 	tristate "Cryptoloop Support"
drivers/block/loop.c +235 -126

505 lines not on this page · raw message

include/linux/loop.h +7 -3
index 66c194e..5c6d011 100644
@@ -30,10 +30,10 @@ struct loop_func_table;
 
 struct loop_device {
 	int		lo_number;
-	int		lo_refcnt;
+	int		lo_flags;
 	loff_t		lo_offset;
 	loff_t		lo_sizelimit;
-	int		lo_flags;
+	atomic_t	lo_open_count;
 	int		(*transfer)(struct loop_device *, int cmd,
 				    struct page *raw_page, unsigned raw_off,
 				    struct page *loop_page, unsigned loop_off,
@@ -64,7 +64,6 @@ struct loop_device {
 
 	struct request_queue	*lo_queue;
 	struct gendisk		*lo_disk;
-	struct list_head	lo_list;
 };
 
 #endif /* __KERNEL__ */
@@ -161,4 +160,9 @@ int loop_unregister_transfer(int number);
 #define LOOP_CHANGE_FD		0x4C06
 #define LOOP_SET_CAPACITY	0x4C07
 
+/* /dev/loop-control interface */
+#define LOOP_CTL_ADD		0x4C80
+#define LOOP_CTL_REMOVE		0x4C81
+#define LOOP_CTL_GET_FREE	0x4C82
+
 #endif
include/linux/miscdevice.h +1 -0
index 18fd130..c309b1e 100644
@@ -40,6 +40,7 @@
 #define BTRFS_MINOR		234
 #define AUTOFS_MINOR		235
 #define MAPPER_CTRL_MINOR	236
+#define LOOP_CTRL_MINOR		237
 #define MISC_DYNAMIC_MINOR	255
 
 struct device;
#1 lore raw

Hello, Kay.

Quoted 7 lines · Kay Sievers

From: Kay Sievers <[email protected]>
Subject: loop: add management interface for on-demand device allocation

Loop devices today have a fixed pre-allocated number of usually 8. The number can only be changed at init time. To find a free device to use, /dev/loop%i needs to be scanned and all devices need to be opened.

It generally looks good to me but I really hope it were split into multiple patches. I think it's a bit too big and doing too many different things. Can you please split it up?

drivers/block/loop.c line 91

Quoted 2 lines
drivers/block/loop.c +2 -0
+static int loop_lookup(struct loop_device **lo, int nr);
+static int loop_add(struct loop_device **lo, int nr);

Also, can't these return loop_device * and ERR_PTR() value on errors?

Thanks.

Signature · 1 line
tejun
#2 lore raw
Quoted 4 lines · Tejun Heo
Quoted 3 lines · Kay Sievers

From: Kay Sievers <[email protected]>
Subject: loop: add management interface for on-demand device allocation

Quoted 8 lines
Quoted 4 lines

Loop devices today have a fixed pre-allocated number of usually 8. The number can only be changed at init time. To find a free device to use, /dev/loop%i needs to be scanned and all devices need to be opened.

It generally looks good to me but I really hope it were split into multiple patches.  I think it's a bit too big and doing too many different things.  Can you please split it up?

Hmm, split into what? Like splitting the loop-control stuff off? The rest can't really be split I guess, because all the linked lists need to be converted to idr at once.

Quoted 4 lines

drivers/block/loop.c line 91

Quoted 2 lines
drivers/block/loop.c +2 -0
+static int loop_lookup(struct loop_device **lo, int nr);
+static int loop_add(struct loop_device **lo, int nr);

Also, can't these return loop_device * and ERR_PTR() value on errors?

I think ERR_PTR is a nasty hack and looks ugly, and stuff should return only pointers when the retuned errno can only ever be -ENOMEM, like on malloc(). :)

Kay

#3 lore raw
Quoted 10 lines · Kay Sievers
Quoted 9 lines · Tejun Heo
Quoted 7 lines · Kay Sievers

From: Kay Sievers <[email protected]>
Subject: loop: add management interface for on-demand device allocation

Loop devices today have a fixed pre-allocated number of usually 8. The number can only be changed at init time. To find a free device to use, /dev/loop%i needs to be scanned and all devices need to be opened.

Quoted 7 lines
Quoted 3 lines

It generally looks good to me but I really hope it were split into multiple patches.  I think it's a bit too big and doing too many different things.  Can you please split it up?

Hmm, split into what? Like splitting the loop-control stuff off? The rest can't really be split I guess, because all the linked lists need to be converted to idr at once.

Split it into 3 pieces, which I'll send now.

Thanks,
Kay