Skip to contentSkip to conversation

2.6.0-test4-mm2 drivers/char.c Oops on open()

PATCH In review Dave Olien 1 participant 2 messages Aug 28, 2003 Char and misc drivers

lore
Share & tools
lore

Dave Olien

author
#0 lore raw

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:
author
#1 lore raw

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.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: