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    [W:0.044 / U:0.084 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site