1 diff -urp linux-2.6.18.1.orig/block/ll_rw_blk.c linux-2.6.18.1/block/ll_rw_blk.c
2 --- linux-2.6.18.1.orig/block/ll_rw_blk.c 2006-10-14 06:34:03.000000000 +0300
3 +++ linux-2.6.18.1/block/ll_rw_blk.c 2007-05-29 14:50:46.000000000 +0300
4 @@ -2993,6 +2993,8 @@ static void handle_bad_sector(struct bio
5 set_bit(BIO_EOF, &bio->bi_flags);
8 +int dev_check_rdonly(struct block_device *bdev);
11 * generic_make_request: hand a buffer to its device driver for I/O
12 * @bio: The bio describing the location in memory and on the device.
13 @@ -3076,6 +3078,12 @@ end_io:
15 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
17 + /* this is cfs's dev_rdonly check */
18 + if (bio->bi_rw == WRITE &&
19 + dev_check_rdonly(bio->bi_bdev)) {
20 + bio_endio(bio, bio->bi_size, 0);
25 * If this device has partitions, remap block n
26 @@ -3675,6 +3683,91 @@ void swap_io_context(struct io_context *
29 EXPORT_SYMBOL(swap_io_context);
31 + * Debug code for turning block devices "read-only" (will discard writes
32 + * silently). This is for filesystem crash/recovery testing.
36 + struct deventry *next;
39 +static struct deventry *devlist = NULL;
40 +static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
42 +int dev_check_rdonly(struct block_device *bdev)
44 + struct deventry *cur;
45 + if (!bdev) return 0;
46 + spin_lock(&devlock);
49 + if (bdev->bd_dev == cur->dev) {
50 + spin_unlock(&devlock);
55 + spin_unlock(&devlock);
59 +void dev_set_rdonly(struct block_device *bdev)
61 + struct deventry *newdev, *cur;
65 + newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
69 + spin_lock(&devlock);
72 + if (bdev->bd_dev == cur->dev) {
73 + spin_unlock(&devlock);
79 + newdev->dev = bdev->bd_dev;
80 + newdev->next = devlist;
82 + spin_unlock(&devlock);
83 + printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
84 + bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
87 +void dev_clear_rdonly(struct block_device *bdev)
89 + struct deventry *cur, *last = NULL;
91 + spin_lock(&devlock);
94 + if (bdev->bd_dev == cur->dev) {
96 + last->next = cur->next;
98 + devlist = cur->next;
99 + spin_unlock(&devlock);
101 + printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
102 + bdev->bd_disk ? bdev->bd_disk->disk_name :
103 + "unknown block", bdev->bd_dev);
109 + spin_unlock(&devlock);
112 +EXPORT_SYMBOL(dev_set_rdonly);
113 +EXPORT_SYMBOL(dev_clear_rdonly);
114 +EXPORT_SYMBOL(dev_check_rdonly);
118 diff -urp linux-2.6.18.1.orig/fs/block_dev.c linux-2.6.18.1/fs/block_dev.c
119 --- linux-2.6.18.1.orig/fs/block_dev.c 2006-10-14 06:34:03.000000000 +0300
120 +++ linux-2.6.18.1/fs/block_dev.c 2007-05-29 14:53:38.000000000 +0300
121 @@ -58,6 +58,7 @@ static void kill_bdev(struct block_devic
123 invalidate_bdev(bdev, 1);
124 truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
125 + dev_clear_rdonly(bdev);
128 int set_blocksize(struct block_device *bdev, int size)
129 diff -urp linux-2.6.18.1.orig/include/linux/fs.h linux-2.6.18.1/include/linux/fs.h
130 --- linux-2.6.18.1.orig/include/linux/fs.h 2006-10-14 06:34:03.000000000 +0300
131 +++ linux-2.6.18.1/include/linux/fs.h 2007-05-29 14:50:46.000000000 +0300
132 @@ -1632,6 +1632,10 @@ extern void file_kill(struct file *f);
133 extern void submit_bio(int, struct bio *);
134 extern int bdev_read_only(struct block_device *);
136 +#define HAVE_CLEAR_RDONLY_ON_PUT
137 +extern void dev_set_rdonly(struct block_device *bdev);
138 +extern int dev_check_rdonly(struct block_device *bdev);
139 +extern void dev_clear_rdonly(struct block_device *bdev);
140 extern int set_blocksize(struct block_device *, int);
141 extern int sb_set_blocksize(struct super_block *, int);
142 extern int sb_min_blocksize(struct super_block *, int);