Whamcloud - gitweb
Branch HEAD
[fs/lustre-release.git] / lustre / kernel_patches / patches / dev_read_only-2.6.22-vanilla.patch
1 Set the underlying block device "read only" and silently discard writes
2 to the device at the block layer.  This allows the block device queue
3 to drain quickly for controlled failback of the device.
4
5 At one time it was required to avoid crashes in the JBD layer during
6 failover, but it may also be possible to just allow the inflight IO to
7 complete and have Lustre handle this more gracefully.
8
9 diff -urp linux-2.6.18.1.orig/block/ll_rw_blk.c linux-2.6.18.1/block/ll_rw_blk.c
10 --- linux-2.6.18.1.orig/block/ll_rw_blk.c       2006-10-14 06:34:03.000000000 +0300
11 +++ linux-2.6.18.1/block/ll_rw_blk.c    2007-05-29 14:50:46.000000000 +0300
12 @@ -2993,6 +2993,8 @@ static void handle_bad_sector(struct bio
13         set_bit(BIO_EOF, &bio->bi_flags);
14  }
15  
16 +int dev_check_rdonly(struct block_device *bdev);
17 +
18  /**
19   * generic_make_request: hand a buffer to its device driver for I/O
20   * @bio:  The bio describing the location in memory and on the device.
21 @@ -3076,6 +3078,12 @@ end_io:
22  
23                 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
24                         goto end_io;
25 +               /* this is cfs's dev_rdonly check */
26 +               if (bio->bi_rw == WRITE &&
27 +                               dev_check_rdonly(bio->bi_bdev)) {
28 +                       bio_endio(bio, bio->bi_size, 0);
29 +                       break;
30 +               }
31  
32                 /*
33                  * If this device has partitions, remap block n
34 @@ -3675,6 +3683,91 @@ void swap_io_context(struct io_context *
35         *ioc2 = temp;
36  }
37  EXPORT_SYMBOL(swap_io_context);
38 + /*
39 + * Debug code for turning block devices "read-only" (will discard writes
40 + * silently).  This is for filesystem crash/recovery testing.
41 + */
42 +struct deventry {
43 +       dev_t dev;
44 +       struct deventry *next;
45 +};
46 +
47 +static struct deventry *devlist = NULL;
48 +static spinlock_t devlock = SPIN_LOCK_UNLOCKED; 
49 +
50 +int dev_check_rdonly(struct block_device *bdev) 
51 +{
52 +       struct deventry *cur;
53 +       if (!bdev) return 0;
54 +       spin_lock(&devlock);
55 +       cur = devlist;
56 +       while(cur) {
57 +               if (bdev->bd_dev == cur->dev) {
58 +                       spin_unlock(&devlock);
59 +                       return 1;
60 +       }
61 +               cur = cur->next;
62 +       }
63 +       spin_unlock(&devlock);
64 +       return 0;
65 +}
66 +
67 +void dev_set_rdonly(struct block_device *bdev)
68 +{
69 +       struct deventry *newdev, *cur;
70 +
71 +       if (!bdev) 
72 +               return;
73 +       newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
74 +       if (!newdev) 
75 +               return;
76 +       
77 +       spin_lock(&devlock);
78 +       cur = devlist;
79 +       while(cur) {
80 +               if (bdev->bd_dev == cur->dev) {
81 +                       spin_unlock(&devlock);
82 +                       kfree(newdev);
83 +                       return;
84 +               }
85 +               cur = cur->next;
86 +       }
87 +       newdev->dev = bdev->bd_dev;
88 +       newdev->next = devlist;
89 +       devlist = newdev;
90 +       spin_unlock(&devlock);
91 +       printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
92 +              bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
93 +}
94 +
95 +void dev_clear_rdonly(struct block_device *bdev) 
96 +{
97 +       struct deventry *cur, *last = NULL;
98 +       if (!bdev) return;
99 +       spin_lock(&devlock);
100 +       cur = devlist;
101 +       while(cur) {
102 +               if (bdev->bd_dev == cur->dev) {
103 +                       if (last) 
104 +                               last->next = cur->next;
105 +                       else
106 +                               devlist = cur->next;
107 +                       spin_unlock(&devlock);
108 +                       kfree(cur);
109 +                       printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
110 +                              bdev->bd_disk ? bdev->bd_disk->disk_name :
111 +                                              "unknown block", bdev->bd_dev);
112 +                       return;
113 +               }
114 +               last = cur;
115 +               cur = cur->next;
116 +       }
117 +       spin_unlock(&devlock);
118 +}
119 +
120 +EXPORT_SYMBOL(dev_set_rdonly);
121 +EXPORT_SYMBOL(dev_clear_rdonly);
122 +EXPORT_SYMBOL(dev_check_rdonly);
123  
124  /*
125   * sysfs parts below
126 diff -urp linux-2.6.18.1.orig/fs/block_dev.c linux-2.6.18.1/fs/block_dev.c
127 --- linux-2.6.18.1.orig/fs/block_dev.c  2006-10-14 06:34:03.000000000 +0300
128 +++ linux-2.6.18.1/fs/block_dev.c       2007-05-29 14:53:38.000000000 +0300
129 @@ -58,6 +58,7 @@ static void kill_bdev(struct block_devic
130  {
131         invalidate_bdev(bdev, 1);
132         truncate_inode_pages(bdev->bd_inode->i_mapping, 0);
133 +       dev_clear_rdonly(bdev);
134  }      
135  
136  int set_blocksize(struct block_device *bdev, int size)
137 diff -urp linux-2.6.18.1.orig/include/linux/fs.h linux-2.6.18.1/include/linux/fs.h
138 --- linux-2.6.18.1.orig/include/linux/fs.h      2006-10-14 06:34:03.000000000 +0300
139 +++ linux-2.6.18.1/include/linux/fs.h   2007-05-29 14:50:46.000000000 +0300
140 @@ -1632,6 +1632,10 @@ extern void file_kill(struct file *f);
141  extern void submit_bio(int, struct bio *);
142  extern int bdev_read_only(struct block_device *);
143  #endif
144 +#define HAVE_CLEAR_RDONLY_ON_PUT
145 +extern void dev_set_rdonly(struct block_device *bdev);
146 +extern int dev_check_rdonly(struct block_device *bdev);
147 +extern void dev_clear_rdonly(struct block_device *bdev);
148  extern int set_blocksize(struct block_device *, int);
149  extern int sb_set_blocksize(struct super_block *, int);
150  extern int sb_min_blocksize(struct super_block *, int);