2.6.0-test4-mm2 drivers/char.c Oops on open()
PATCH 1/1 2.6.0-test4-mm2 drivers/char.c Oops on open()
The raw.c character device Oopses dereferencing a NULL pointer in bd_claim() This problem occurred after bd_claim() in block_dev.c was modified to "claim the whole device when a partition is claimed".
raw_open() made the mistake of calling bd_claim BEFORE calling blkdev_get(). At that time, the bdev->bd_contains field. has't been initialized yet. Switching the order allows blkdev_get() to initialize those fields before calling bd_claim().
Also fixed up some error return paths:
igrab() should never fail under these circumstances since the caller already has a reference to that inode through the bdev at that time.
In the event of blkdev_get() failure or set_blocksize() failure, not all the work to unwind from the error was done.
drivers/char/raw.c +12 -12
@@ -60,25 +60,25 @@ bdev = raw_devices[minor].binding; err = -ENODEV ;if (bdev) { - err =bd_claim (bdev, raw_open); + err =blkdev_get (bdev, filp->f_mode,0 ,BDEV_RAW );if (err) goto out; - err = -ENODEV ; -if (!igrab (bdev->bd_inode)) +igrab (bdev->bd_inode); + err =bd_claim (bdev, raw_open); +if (err) { +blkdev_put (bdev,BDEV_RAW ); goto out; - err =blkdev_get (bdev, filp->f_mode,0 ,BDEV_RAW ); + } + err =set_blocksize (bdev,bdev_hardsect_size (bdev));if (err) {bd_release (bdev); +blkdev_put (bdev,BDEV_RAW ); goto out; - }else { - err =set_blocksize (bdev,bdev_hardsect_size (bdev)); -if (err ==0 ) { - filp->f_flags |=O_DIRECT ; -if (++raw_devices[minor].inuse ==1 ) - filp->f_dentry->d_inode->i_mapping = - bdev->bd_inode->i_mapping; - } } + filp->f_flags |=O_DIRECT ; +if (++raw_devices[minor].inuse ==1 ) + filp->f_dentry->d_inode->i_mapping = + bdev->bd_inode->i_mapping; } filp->private_data = bdev; out:
Re: [PATCH] 2.6.0-test4-mm2 drivers/char.c ---> drivers/char/raw.c
Mistake in subject line... should refer to drivers/char/raw.c
Quoted 58 lines · Dave Olien
The
raw.ccharacter device Oopses dereferencing a NULL pointer inbd_claim()This problem occurred afterbd_claim()inblock_dev.cwas modified to "claim the whole device when a partition is claimed".
raw_open()made the mistake of callingbd_claimBEFORE callingblkdev_get(). At that time, thebdev->bd_containsfield. has't been initialized yet. Switching the order allowsblkdev_get()to initialize those fields before callingbd_claim().Also fixed up some error return paths:
igrab()should never fail under these circumstances since the caller already has a reference to that inode through the bdev at that time.In the event of
blkdev_get()failure orset_blocksize()failure, not all the work to unwind from the error was done.drivers/char/raw.c +12
-12@@ -60,25 +60,25 @@ bdev = raw_devices[minor].binding; err = -ENODEV ;if (bdev) { - err =bd_claim (bdev, raw_open); + err =blkdev_get (bdev, filp->f_mode,0 ,BDEV_RAW );if (err) goto out; - err = -ENODEV ; -if (!igrab (bdev->bd_inode)) +igrab (bdev->bd_inode); + err =bd_claim (bdev, raw_open); +if (err) { +blkdev_put (bdev,BDEV_RAW ); goto out; - err =blkdev_get (bdev, filp->f_mode,0 ,BDEV_RAW ); + } + err =set_blocksize (bdev,bdev_hardsect_size (bdev));if (err) {bd_release (bdev); +blkdev_put (bdev,BDEV_RAW ); goto out; - }else { - err =set_blocksize (bdev,bdev_hardsect_size (bdev)); -if (err ==0 ) { - filp->f_flags |=O_DIRECT ; -if (++raw_devices[minor].inuse ==1 ) - filp->f_dentry->d_inode->i_mapping = - bdev->bd_inode->i_mapping; - } } + filp->f_flags |=O_DIRECT ; +if (++raw_devices[minor].inuse ==1 ) + filp->f_dentry->d_inode->i_mapping = + bdev->bd_inode->i_mapping; } filp->private_data = bdev; out: