Whamcloud - gitweb
06ae8e7e4c318041165e8bb9383ca1d4d4a1ce72
[fs/lustre-release.git] / lustre / kernel_patches / patches / dev_read_only-2.6.18-vanilla.patch
1 Index: linux-2.6.18.1/block/ll_rw_blk.c
2 ===================================================================
3 --- linux-2.6.18.1.orig/block/ll_rw_blk.c
4 +++ linux-2.6.18.1/block/ll_rw_blk.c
5 @@ -3067,6 +3067,8 @@ static void handle_bad_sector(struct bio
6         set_bit(BIO_EOF, &bio->bi_flags);
7  }
8  
9 +int dev_check_rdonly(struct block_device *bdev);
10 +
11  /**
12   * generic_make_request: hand a buffer to its device driver for I/O
13   * @bio:  The bio describing the location in memory and on the device.
14 @@ -3151,6 +3153,23 @@ end_io:
15  
16                 if (unlikely(test_bit(QUEUE_FLAG_DEAD, &q->queue_flags)))
17                         goto end_io;
18
19 +               /* this is cfs's dev_rdonly check */
20 +               if (bio->bi_rw == WRITE && dev_check_rdonly(bio->bi_bdev)) {
21 +                       struct block_device *bdev = bio->bi_bdev;
22 +
23 +                       printk(KERN_WARNING "Write to readonly device %s (%#x) "
24 +                              "bi_flags: %lx, bi_vcnt: %d, bi_idx: %d, "
25 +                              "bi->size: %d, bi_cnt: %d, bi_private: %p\n",
26 +                              bdev->bd_disk ? bdev->bd_disk->disk_name : "",
27 +                              bdev->bd_dev, bio->bi_flags, bio->bi_vcnt,
28 +                              bio->bi_idx, bio->bi_size,
29 +                              atomic_read(&bio->bi_cnt), bio->bi_private);
30 +                       set_bit(BIO_RDONLY, &bio->bi_flags);
31 +                       bio_endio(bio, bio->bi_size, 0);
32 +                       clear_bit(BIO_RDONLY, &bio->bi_flags);
33 +                       break;
34 +               }
35 +
36                 /*
37                  * If this device has partitions, remap block n
38 @@ -3765,6 +3784,91 @@ void swap_io_context(struct io_context *
39         *ioc2 = temp;
40  }
41  EXPORT_SYMBOL(swap_io_context);
42 + /*
43 + * Debug code for turning block devices "read-only" (will discard writes
44 + * silently).  This is for filesystem crash/recovery testing.
45 + */
46 +struct deventry {
47 +       dev_t dev;
48 +       struct deventry *next;
49 +};
50 +
51 +static struct deventry *devlist = NULL;
52 +static spinlock_t devlock = SPIN_LOCK_UNLOCKED; 
53 +
54 +int dev_check_rdonly(struct block_device *bdev) 
55 +{
56 +       struct deventry *cur;
57 +       if (!bdev) return 0;
58 +       spin_lock(&devlock);
59 +       cur = devlist;
60 +       while(cur) {
61 +               if (bdev->bd_dev == cur->dev) {
62 +                       spin_unlock(&devlock);
63 +                       return 1;
64 +       }
65 +               cur = cur->next;
66 +       }
67 +       spin_unlock(&devlock);
68 +       return 0;
69 +}
70 +
71 +void dev_set_rdonly(struct block_device *bdev)
72 +{
73 +       struct deventry *newdev, *cur;
74 +
75 +       if (!bdev) 
76 +               return;
77 +       newdev = kmalloc(sizeof(struct deventry), GFP_KERNEL);
78 +       if (!newdev) 
79 +               return;
80 +       
81 +       spin_lock(&devlock);
82 +       cur = devlist;
83 +       while(cur) {
84 +               if (bdev->bd_dev == cur->dev) {
85 +                       spin_unlock(&devlock);
86 +                       kfree(newdev);
87 +                       return;
88 +               }
89 +               cur = cur->next;
90 +       }
91 +       newdev->dev = bdev->bd_dev;
92 +       newdev->next = devlist;
93 +       devlist = newdev;
94 +       spin_unlock(&devlock);
95 +       printk(KERN_WARNING "Turning device %s (%#x) read-only\n",
96 +              bdev->bd_disk ? bdev->bd_disk->disk_name : "", bdev->bd_dev);
97 +}
98 +
99 +void dev_clear_rdonly(struct block_device *bdev) 
100 +{
101 +       struct deventry *cur, *last = NULL;
102 +       if (!bdev) return;
103 +       spin_lock(&devlock);
104 +       cur = devlist;
105 +       while(cur) {
106 +               if (bdev->bd_dev == cur->dev) {
107 +                       if (last) 
108 +                               last->next = cur->next;
109 +                       else
110 +                               devlist = cur->next;
111 +                       spin_unlock(&devlock);
112 +                       kfree(cur);
113 +                       printk(KERN_WARNING "Removing read-only on %s (%#x)\n",
114 +                              bdev->bd_disk ? bdev->bd_disk->disk_name :
115 +                                              "unknown block", bdev->bd_dev);
116 +                       return;
117 +               }
118 +               last = cur;
119 +               cur = cur->next;
120 +       }
121 +       spin_unlock(&devlock);
122 +}
123 +
124 +EXPORT_SYMBOL(dev_set_rdonly);
125 +EXPORT_SYMBOL(dev_clear_rdonly);
126 +EXPORT_SYMBOL(dev_check_rdonly);
127  
128  /*
129   * sysfs parts below
130 Index: linux-2.6.18.1/fs/block_dev.c
131 ===================================================================
132 --- linux-2.6.18.1.orig/fs/block_dev.c
133 +++ linux-2.6.18.1/fs/block_dev.c
134 @@ -1059,6 +1059,7 @@ static int __blkdev_put(struct block_dev
135                 if (bdev != bdev->bd_contains)
136                         victim = bdev->bd_contains;
137                 bdev->bd_contains = NULL;
138 +               dev_clear_rdonly(bdev);
139         }
140         unlock_kernel();
141         mutex_unlock(&bdev->bd_mutex);
142 Index: linux-2.6.18.1/include/linux/fs.h
143 ===================================================================
144 --- linux-2.6.18.1.orig/include/linux/fs.h
145 +++ linux-2.6.18.1/include/linux/fs.h
146 @@ -1685,6 +1685,10 @@ extern void file_kill(struct file *f);
147  struct bio;
148  extern void submit_bio(int, struct bio *);
149  extern int bdev_read_only(struct block_device *);
150 +#define HAVE_CLEAR_RDONLY_ON_PUT
151 +void dev_set_rdonly(struct block_device *bdev);
152 +int dev_check_rdonly(struct block_device *bdev);
153 +void dev_clear_rdonly(struct block_device *bdev);
154  extern int set_blocksize(struct block_device *, int);
155  extern int sb_set_blocksize(struct super_block *, int);
156  extern int sb_min_blocksize(struct super_block *, int);
157 Index: linux-2.6.18.1/include/linux/bio.h
158 ===================================================================
159 --- linux-2.6.18.1.orig/include/linux/bio.h
160 +++ linux-2.6.18.1/include/linux/bio.h
161 @@ -124,6 +124,7 @@ struct bio {
162  #define BIO_BOUNCED    5       /* bio is a bounce bio */
163  #define BIO_USER_MAPPED 6      /* contains user pages */
164  #define BIO_EOPNOTSUPP 7       /* not supported */
165 +#define BIO_RDONLY     31      /* device is readonly */
166  #define bio_flagged(bio, flag) ((bio)->bi_flags & (1 << (flag)))
167  
168  /*