lkml.org 
[lkml]   [2009]   [Jun]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    Subject[BUG] bugs in jbd2_dev_to_name() (was Re: [PATCH 00/11] [GIT PULL] more updates for the tag format)
    Theodore Tso wrote:
    > On Thu, Jun 11, 2009 at 07:14:36PM +0200, Frederic Weisbecker wrote:
    >> For the filters, we could enter the text name which would be
    >> internally converted into a dev_t, there should be no problem.
    >>
    >> Also the raw dev_t can be stored and then human-friendly printed on
    >> print time.
    >>
    >> Both seem about trivial to add.
    >
    > If someone wants to take this code and drop it into the core tracing
    > code, please feel free.
    >

    Just notice this code has been merge, but there are 2 bugs in it.

    > - Ted
    >
    > /*
    > * jbd2_dev_to_name is a utility function used by the jbd2 and ext4
    > * tracing infrastructure to map a dev_t to a device name.
    > *
    > * The caller should use rcu_read_lock() in order to make sure the
    > * device name stays valid until its done with it. We use
    > * rcu_read_lock() as well to make sure we're safe in case the caller
    > * gets sloppy, and because rcu_read_lock() is cheap and can be safely
    > * nested.
    > */
    > struct devname_cache {
    > struct rcu_head rcu;
    > dev_t device;
    > char devname[BDEVNAME_SIZE];
    > };
    > #define CACHE_SIZE_BITS 6
    > static struct devname_cache *devcache[1 << CACHE_SIZE_BITS];
    > static DEFINE_SPINLOCK(devname_cache_lock);
    >
    > static void free_devcache(struct rcu_head *rcu)
    > {
    > kfree(rcu);
    > }
    >
    > const char *jbd2_dev_to_name(dev_t device)
    > {
    > int i = hash_32(device, CACHE_SIZE_BITS);
    > char *ret;
    > struct block_device *bd;
    >
    > rcu_read_lock();
    > if (devcache[i] && devcache[i]->device == device) {
    > ret = devcache[i]->devname;
    > rcu_read_unlock();
    > return ret;

    It doesn't seem safe to dereference @ret outside rcu read section.

    > }
    > rcu_read_unlock();
    >
    > spin_lock(&devname_cache_lock);
    > if (devcache[i]) {
    > if (devcache[i]->device == device) {
    > ret = devcache[i]->devname;
    > spin_unlock(&devname_cache_lock);
    > return ret;
    > }
    > call_rcu(&devcache[i]->rcu, free_devcache);
    > }
    > devcache[i] = kmalloc(sizeof(struct devname_cache), GFP_KERNEL);

    kmalloc(GFP_KERNEL) called with spin_lock held..

    > if (!devcache[i]) {
    > spin_unlock(&devname_cache_lock);
    > return "NODEV-ALLOCFAILURE"; /* Something non-NULL */
    > }
    > devcache[i]->device = device;
    > bd = bdget(device);
    > if (bd) {
    > bdevname(bd, devcache[i]->devname);
    > bdput(bd);
    > } else
    > __bdevname(device, devcache[i]->devname);
    > ret = devcache[i]->devname;
    > spin_unlock(&devname_cache_lock);
    > return ret;
    > }
    > EXPORT_SYMBOL(jbd2_dev_to_name);


    \
     
     \ /
      Last update: 2009-06-19 10:15    [W:4.056 / U:1.412 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site