1 Index: linux-2.6/fs/block_dev.c
2 ===================================================================
3 --- linux-2.6.orig/fs/block_dev.c 2006-07-06 23:41:48.000000000 +0800
4 +++ linux-2.6/fs/block_dev.c 2006-07-15 16:20:25.000000000 +0800
5 @@ -1118,6 +1118,7 @@ static int __blkdev_put(struct block_dev
8 mutex_unlock(&bdev->bd_mutex);
9 + dev_clear_rdonly(bdev);
13 Index: linux-2.6/block/ll_rw_blk.c
14 ===================================================================
15 --- linux-2.6.orig/block/ll_rw_blk.c 2006-07-10 22:30:08.000000000 +0800
16 +++ linux-2.6/block/ll_rw_blk.c 2006-07-15 16:15:14.000000000 +0800
17 @@ -2993,6 +2993,8 @@ static void handle_bad_sector(struct bio
18 set_bit(BIO_EOF, &bio->bi_flags);
21 +int dev_check_rdonly(struct block_device *bdev);
24 * generic_make_request: hand a buffer to its device driver for I/O
25 * @bio: The bio describing the location in memory and on the device.
26 @@ -3076,6 +3078,12 @@ end_io:
28 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
30 + /* this is cfs's dev_rdonly check */
31 + if (bio->bi_rw == WRITE &&
32 + dev_check_rdonly(bio->bi_bdev)) {
33 + bio_endio(bio, bio->bi_size, 0);
38 * If this device has partitions, remap block n
39 @@ -3673,6 +3681,91 @@ void swap_io_context(struct io_context *
42 EXPORT_SYMBOL(swap_io_context);
44 + * Debug code for turning block devices "read-only" (will discard writes
45 + * silently). This is for filesystem crash/recovery testing.
49 + struct deventry *next;
52 +static struct deventry *devlist = NULL;
53 +static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
55 +int dev_check_rdonly(struct block_device *bdev)
57 + struct deventry *cur;
58 + if (!bdev) return 0;
59 + spin_lock(&devlock);
62 + if (bdev->bd_dev == cur->dev) {
63 + spin_unlock(&devlock);
68 + spin_unlock(&devlock);
72 +void dev_set_rdonly(struct block_device *bdev)
74 + struct deventry *newdev, *cur;
78 + newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
82 + spin_lock(&devlock);
85 + if (bdev->bd_dev == cur->dev) {
86 + spin_unlock(&devlock);
92 + newdev->dev = bdev->bd_dev;
93 + newdev->next = devlist;
95 + spin_unlock(&devlock);
96 + printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
97 + bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
100 +void dev_clear_rdonly(struct block_device *bdev)
102 + struct deventry *cur, *last = NULL;
104 + spin_lock(&devlock);
107 + if (bdev->bd_dev == cur->dev) {
109 + last->next = cur->next;
111 + devlist = cur->next;
112 + spin_unlock(&devlock);
114 + printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
115 + bdev->bd_disk ? bdev->bd_disk->disk_name :
116 + "unknown block", bdev->bd_dev);
122 + spin_unlock(&devlock);
125 +EXPORT_SYMBOL(dev_set_rdonly);
126 +EXPORT_SYMBOL(dev_clear_rdonly);
127 +EXPORT_SYMBOL(dev_check_rdonly);
131 Index: linux-2.6/include/linux/fs.h
132 ===================================================================
133 --- linux-2.6.orig/include/linux/fs.h 2006-07-15 16:14:58.000000000 +0800
134 +++ linux-2.6/include/linux/fs.h 2006-07-15 16:15:14.000000000 +0800
135 @@ -1648,6 +1648,10 @@ extern void file_kill(struct file *f);
137 extern void submit_bio(int, struct bio *);
138 extern int bdev_read_only(struct block_device *);
139 +#define HAVE_CLEAR_RDONLY_ON_PUT
140 +void dev_set_rdonly(struct block_device *bdev);
141 +int dev_check_rdonly(struct block_device *bdev);
142 +void dev_clear_rdonly(struct block_device *bdev);
143 extern int set_blocksize(struct block_device *, int);
144 extern int sb_set_blocksize(struct super_block *, int);
145 extern int sb_min_blocksize(struct super_block *, int);