The recent fix to the raw driver wasn't quite right: it rewrites the character-special inode's i_mapping to point back to itself on each close. So any other currently-open handles against /dev/raw/rawN get a nasty surprise. Change it to only rewrite i_mapping on the final close. Also, change it so that it only redirects its i_mapping on the initial open. This is not necessary, but is neater. drivers/char/raw.c | 20 ++++++++++++-------- 1 files changed, 12 insertions(+), 8 deletions(-) diff -puN drivers/char/raw.c~raw-fix-address_space-rewriting drivers/char/raw.c --- 25/drivers/char/raw.c~raw-fix-address_space-rewriting 2003-03-20 03:11:45.000000000 -0800 +++ 25-akpm/drivers/char/raw.c 2003-03-20 03:11:45.000000000 -0800 @@ -70,10 +70,10 @@ static int raw_open(struct inode *inode, } else { err = set_blocksize(bdev, bdev_hardsect_size(bdev)); if (err == 0) { - raw_devices[minor].inuse++; - 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; } } } @@ -83,6 +83,10 @@ out: return err; } +/* + * When the final fd which refers to this character-special node is closed, we + * make its ->mapping point back at its own i_data. + */ static int raw_release(struct inode *inode, struct file *filp) { const int minor= minor(inode->i_rdev); @@ -90,12 +94,12 @@ static int raw_release(struct inode *ino down(&raw_mutex); bdev = raw_devices[minor].binding; - raw_devices[minor].inuse--; + if (--raw_devices[minor].inuse == 0) { + /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ + inode->i_mapping = &inode->i_data; + inode->i_mapping->backing_dev_info = &default_backing_dev_info; + } up(&raw_mutex); - - /* Here inode->i_mapping == bdev->bd_inode->i_mapping */ - inode->i_mapping = &inode->i_data; - inode->i_mapping->backing_dev_info = &default_backing_dev_info; bd_release(bdev); blkdev_put(bdev, BDEV_RAW); _