1 Index: linux-2.6.5-lnxi/drivers/block/ll_rw_blk.c
2 ===================================================================
3 --- linux-2.6.5-lnxi.orig/drivers/block/ll_rw_blk.c
4 +++ linux-2.6.5-lnxi/drivers/block/ll_rw_blk.c
5 @@ -2718,7 +2718,7 @@ static inline void blk_partition_remap(s
9 -int dev_check_rdonly(dev_t dev);
10 +int dev_check_rdonly(struct block_device *bdev);
13 * generic_make_request: hand a buffer to its device driver for I/O
14 @@ -2810,7 +2810,7 @@ end_io:
16 /* this is cfs's dev_rdonly check */
17 if (bio->bi_rw == WRITE &&
18 - dev_check_rdonly(bio->bi_bdev->bd_dev)) {
19 + dev_check_rdonly(bio->bi_bdev)) {
20 bio_endio(bio, bio->bi_size, 0);
23 @@ -3395,53 +3395,86 @@ void swap_io_context(struct io_context *
27 -#define MAX_RDONLY_DEVS 16
29 -static dev_t rdonly_devs[MAX_RDONLY_DEVS] = {0, };
32 * Debug code for turning block devices "read-only" (will discard writes
33 * silently). This is for filesystem crash/recovery testing.
35 -void dev_set_rdonly(struct block_device *bdev, int no_write)
38 + struct deventry *next;
41 +static struct deventry *devlist = NULL;
42 +static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
44 +int dev_check_rdonly(struct block_device *bdev)
46 - if (no_write >= MAX_RDONLY_DEVS) {
47 - printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
48 - __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
50 + struct deventry *cur;
51 + if (!bdev) return 0;
52 + spin_lock(&devlock);
55 + if (bdev->bd_dev == cur->dev) {
56 + spin_unlock(&devlock);
61 - printk(KERN_WARNING "Turning device %s read-only at %d\n",
62 - bdev->bd_disk ? bdev->bd_disk->disk_name : "?",
64 - rdonly_devs[no_write] = bdev->bd_dev;
67 + spin_unlock(&devlock);
71 -void dev_clear_rdonly(int no_write)
72 +void dev_set_rdonly(struct block_device *bdev)
74 - if (no_write >= MAX_RDONLY_DEVS) {
75 - printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
76 - __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
79 + struct deventry *newdev, *cur;
81 - if (rdonly_devs[no_write] == 0)
84 + newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
88 - printk(KERN_WARNING "Clearing read-only at %d\n", no_write);
89 - rdonly_devs[no_write] = 0;
92 -int dev_check_rdonly(dev_t dev)
96 - for (i = 0; i < MAX_RDONLY_DEVS; i++)
97 - if (rdonly_devs[i] == dev)
100 + spin_lock(&devlock);
103 + if (bdev->bd_dev == cur->dev) {
104 + spin_unlock(&devlock);
110 + newdev->dev = bdev->bd_dev;
111 + newdev->next = devlist;
113 + spin_unlock(&devlock);
114 + printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
115 + bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
118 +void dev_clear_rdonly(struct block_device *bdev)
120 + struct deventry *cur, *last = NULL;
122 + spin_lock(&devlock);
125 + if (bdev->bd_dev == cur->dev) {
127 + last->next = cur->next;
129 + devlist = cur->next;
130 + spin_unlock(&devlock);
132 + printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
133 + bdev->bd_disk ? bdev->bd_disk->disk_name :
134 + "unknown block", bdev->bd_dev);
140 + spin_unlock(&devlock);
143 EXPORT_SYMBOL(dev_set_rdonly);
144 Index: linux-2.6.5-lnxi/fs/block_dev.c
145 ===================================================================
146 --- linux-2.6.5-lnxi.orig/fs/block_dev.c
147 +++ linux-2.6.5-lnxi/fs/block_dev.c
148 @@ -767,6 +767,7 @@ int blkdev_put(struct block_device *bdev
149 blkdev_put(bdev->bd_contains);
151 bdev->bd_contains = NULL;
152 + dev_clear_rdonly(bdev);
156 Index: linux-2.6.5-lnxi/include/linux/fs.h
157 ===================================================================
158 --- linux-2.6.5-lnxi.orig/include/linux/fs.h
159 +++ linux-2.6.5-lnxi/include/linux/fs.h
160 @@ -1424,6 +1424,10 @@ extern void file_kill(struct file *f);
162 extern int submit_bio(int, struct bio *);
163 extern int bdev_read_only(struct block_device *);
164 +#define HAVE_CLEAR_RDONLY_ON_PUT
165 +void dev_set_rdonly(struct block_device *bdev);
166 +int dev_check_rdonly(struct block_device *bdev);
167 +void dev_clear_rdonly(struct block_device *bdev);
168 extern int set_blocksize(struct block_device *, int);
169 extern int sb_set_blocksize(struct super_block *, int);
170 extern int sb_min_blocksize(struct super_block *, int);