lkml.org 
[lkml]   [2002]   [Oct]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
SubjectRe: [PATCH] dm update 3/3
From
On Tue, Oct 29, 2002 at 12:42:24PM -0500, Alexander Viro wrote:
> Ugh. See find_first_zero_bit() - no need to reinvent that wheel...


--- diff/drivers/md/dm.c 2002-10-30 09:38:39.000000000 +0000
+++ source/drivers/md/dm.c 2002-10-30 10:03:54.000000000 +0000
@@ -15,7 +15,7 @@
#include <linux/slab.h>

static const char *_name = DM_NAME;
-#define MAX_DEVICES 256
+#define MAX_DEVICES (1 << KDEV_MINOR_BITS)
#define SECTOR_SHIFT 9

static int major = 0;
@@ -483,13 +483,25 @@
return 0;
}

+/*-----------------------------------------------------------------
+ * A bitset is used to keep track of allocated minor numbers.
+ *---------------------------------------------------------------*/
+static spinlock_t _minor_lock = SPIN_LOCK_UNLOCKED;
+static unsigned long _minor_bits[MAX_DEVICES / BITS_PER_LONG];
+
+static void free_minor(int minor)
+{
+ spin_lock(&_minor_lock);
+ clear_bit(minor, _minor_bits);
+ spin_unlock(&_minor_lock);
+}
+
/*
* See if the device with a specific minor # is free.
*/
-static int specific_dev(int minor, struct mapped_device *md)
+static int specific_minor(int minor)
{
- struct gendisk *disk;
- int part;
+ int r = -EBUSY;

if (minor >= MAX_DEVICES) {
DMWARN("request for a mapped_device beyond MAX_DEVICES (%d)",
@@ -497,26 +509,27 @@
return -EINVAL;
}

- disk = get_gendisk(MKDEV(_major, minor), &part);
- if (disk) {
- put_disk(disk);
- return -EBUSY;
- }
+ spin_lock(&_minor_lock);
+ if (!test_and_set_bit(minor, _minor_bits))
+ r = minor;
+ spin_unlock(&_minor_lock);

- return minor;
+ return r;
}

-static int any_old_dev(struct mapped_device *md)
+static int next_free_minor(void)
{
- int i;
+ int minor, r = -EBUSY;

- for (i = 0; i < MAX_DEVICES; i++)
- if (specific_dev(i, md) >= 0) {
- DMWARN("allocating minor = %d", i);
- return i;
- }
+ spin_lock(&_minor_lock);
+ minor = find_first_zero_bit(_minor_bits, MAX_DEVICES);
+ if (minor != MAX_DEVICES) {
+ set_bit(minor, _minor_bits);
+ r = minor;
+ }
+ spin_unlock(&_minor_lock);

- return -EBUSY;
+ return r;
}

/*
@@ -532,12 +545,13 @@
}

/* get a minor number for the dev */
- minor = (minor < 0) ? any_old_dev(md) : specific_dev(minor, md);
+ minor = (minor < 0) ? next_free_minor() : specific_minor(minor);
if (minor < 0) {
kfree(md);
return NULL;
}

+ DMWARN("allocating minor %d.", minor);
memset(md, 0, sizeof(*md));
init_rwsem(&md->lock);
atomic_set(&md->holders, 1);
@@ -547,6 +561,7 @@

md->disk = alloc_disk(1);
if (!md->disk) {
+ free_minor(md->disk->first_minor);
kfree(md);
return NULL;
}
@@ -566,6 +581,7 @@

static void free_dev(struct mapped_device *md)
{
+ free_minor(md->disk->first_minor);
del_gendisk(md->disk);
put_disk(md->disk);
kfree(md);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:30    [from the cache]
©2003-2011 Jasper Spaans. Advertise on this site