- drivers/block/ll_rw_blk.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++
- include/linux/blkdev.h | 1
- 2 files changed, 50 insertions(+)
-
Index: linux-2.6.10/drivers/block/ll_rw_blk.c
===================================================================
--- linux-2.6.10.orig/drivers/block/ll_rw_blk.c 2004-12-25 05:33:59.000000000 +0800
-+++ linux-2.6.10/drivers/block/ll_rw_blk.c 2005-04-05 15:42:58.075467024 +0800
-@@ -2679,6 +2679,13 @@
- if (test_bit(QUEUE_FLAG_DEAD, &q->queue_flags))
- goto end_io;
++++ linux-2.6.10/drivers/block/ll_rw_blk.c 2005-04-07 00:37:34.299974720 +0800
+@@ -2598,6 +2598,8 @@
+ set_bit(BIO_EOF, &bio->bi_flags);
+ }
-+ /* this is cfs's dev_rdonly check */
-+ if (bio->bi_rw == WRITE &&
-+ dev_check_rdonly(bio->bi_bdev->bd_dev)) {
-+ bio_endio(bio, bio->bi_size, 0);
-+ break;
-+ }
++int dev_check_rdonly(struct block_device *bdev);
+
+ /**
+ * generic_make_request: hand a buffer to its device driver for I/O
+ * @bio: The bio describing the location in memory and on the device.
+@@ -2681,6 +2683,13 @@
+
block_wait_queue_running(q);
++ /* this is cfs's dev_rdonly check */
++ if (bio->bi_rw == WRITE &&
++ dev_check_rdonly(bio->bi_bdev)) {
++ bio_endio(bio, bio->bi_size, 0);
++ break;
++ }
++
/*
-@@ -3287,6 +3294,58 @@
- return queue_var_show(max_hw_sectors_kb, (page));
- }
+ * If this device has partitions, remap block n
+ * of partition p to block n+start(p) of the disk.
+@@ -3156,6 +3165,91 @@
+ EXPORT_SYMBOL(swap_io_context);
-+#define MAX_RDONLY_DEVS 16
-+
-+static dev_t rdonly_devs[MAX_RDONLY_DEVS] = {0, };
-+
-+/*
+ /*
+ * Debug code for turning block devices "read-only" (will discard writes
+ * silently). This is for filesystem crash/recovery testing.
+ */
-+void dev_set_rdonly(struct block_device *bdev, int no_write)
-+{
-+ if (no_write >= MAX_RDONLY_DEVS) {
-+ printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
-+ __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
-+ return;
-+ }
++struct deventry {
++ dev_t dev;
++ struct deventry *next;
++};
++
++static struct deventry *devlist = NULL;
++static spinlock_t devlock = SPIN_LOCK_UNLOCKED;
+
-+ if (bdev) {
-+ printk(KERN_WARNING "Turning device %s read-only at %d\n",
-+ bdev->bd_disk ? bdev->bd_disk->disk_name : "?",
-+ no_write);
-+ rdonly_devs[no_write] = bdev->bd_dev;
-+ }
++int dev_check_rdonly(struct block_device *bdev)
++{
++ struct deventry *cur;
++ if (!bdev) return 0;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ return 1;
++ }
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
++ return 0;
+}
+
-+void dev_clear_rdonly(int no_write)
++void dev_set_rdonly(struct block_device *bdev)
+{
-+ if (no_write >= MAX_RDONLY_DEVS) {
-+ printk(KERN_ALERT "%s:%d illegal arg %d (max %d)\n",
-+ __FILE__, __LINE__, no_write, MAX_RDONLY_DEVS);
-+ return;
-+ }
++ struct deventry *newdev, *cur;
++
++ if (!bdev)
++ return;
++ newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
++ if (!newdev)
++ return;
+
-+ if (rdonly_devs[no_write] == 0)
-+ return;
-+
-+ printk(KERN_WARNING "Clearing read-only at %d\n", no_write);
-+ rdonly_devs[no_write] = 0;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ spin_unlock(&devlock);
++ kfree(newdev);
++ return;
++ }
++ cur = cur->next;
++ }
++ newdev->dev = bdev->bd_dev;
++ newdev->next = devlist;
++ devlist = newdev;
++ spin_unlock(&devlock);
++ printk(KERN_WARNING "Turning device %s read-only\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
+}
+
-+int dev_check_rdonly(dev_t dev)
++void dev_clear_rdonly(struct block_device *bdev)
+{
-+ int i;
-+
-+ for (i = 0; i < MAX_RDONLY_DEVS; i++)
-+ if (rdonly_devs[i] == dev)
-+ return 1;
-+ return 0;
++ struct deventry *cur, *last = NULL;
++ if (!bdev) return;
++ spin_lock(&devlock);
++ cur = devlist;
++ while(cur) {
++ if (bdev->bd_dev == cur->dev) {
++ if (last)
++ last->next = cur->next;
++ else
++ devlist = cur->next;
++ spin_unlock(&devlock);
++ kfree(cur);
++ printk(KERN_WARNING "Removing read-only on %s\n",
++ bdev->bd_disk ? bdev->bd_disk->disk_name : "?");
++ return;
++ }
++ last = cur;
++ cur = cur->next;
++ }
++ spin_unlock(&devlock);
+}
+
+EXPORT_SYMBOL(dev_set_rdonly);
+EXPORT_SYMBOL(dev_clear_rdonly);
+EXPORT_SYMBOL(dev_check_rdonly);
-
- static struct queue_sysfs_entry queue_requests_entry = {
- .attr = {.name = "nr_requests", .mode = S_IRUGO | S_IWUSR },
++
++/*
+ * sysfs parts below
+ */
+ struct queue_sysfs_entry {