diff options
author | NeilBrown <neilb@suse.de> | 2005-11-09 00:39:34 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-09 10:56:38 -0500 |
commit | a9701a30470856408d08657eb1bd7ae29a146190 (patch) | |
tree | eb6ea8c82fdc1b50bf56abadeee63a935034cf27 /include | |
parent | bd926c63b7a6843d3ce2728396c0891e54fce5c4 (diff) |
[PATCH] md: support BIO_RW_BARRIER for md/raid1
We can only accept BARRIER requests if all slaves handle
barriers, and that can, of course, change with time....
So we keep track of whether the whole array seems safe for barriers,
and also whether each individual rdev handles barriers.
We initially assumes barriers are OK.
When writing the superblock we try a barrier, and if that fails, we flag
things for no-barriers. This will usually clear the flags fairly quickly.
If writing the superblock finds that BIO_RW_BARRIER is -ENOTSUPP, we need to
resubmit, so introduce function "md_super_wait" which waits for requests to
finish, and retries ENOTSUPP requests without the barrier flag.
When writing the real raid1, write requests which were BIO_RW_BARRIER but
which aresn't supported need to be retried. So raid1d is enhanced to do this,
and when any bio write completes (i.e. no retry needed) we remove it from the
r1bio, so that devices needing retry are easy to find.
We should hardly ever get -ENOTSUPP errors when writing data to the raid.
It should only happen if:
1/ the device used to support BARRIER, but now doesn't. Few devices
change like this, though raid1 can!
or
2/ the array has no persistent superblock, so there was no opportunity to
pre-test for barriers when writing the superblock.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/raid/md.h | 1 | ||||
-rw-r--r-- | include/linux/raid/md_k.h | 8 | ||||
-rw-r--r-- | include/linux/raid/raid1.h | 4 |
3 files changed, 12 insertions, 1 deletions
diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 91467a3c4a52..13e7c4b62367 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h | |||
@@ -89,6 +89,7 @@ extern void md_print_devices (void); | |||
89 | 89 | ||
90 | extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, | 90 | extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, |
91 | sector_t sector, int size, struct page *page); | 91 | sector_t sector, int size, struct page *page); |
92 | extern void md_super_wait(mddev_t *mddev); | ||
92 | extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, | 93 | extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, |
93 | struct page *page, int rw); | 94 | struct page *page, int rw); |
94 | 95 | ||
diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 11629f92180a..d5854c2b2721 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h | |||
@@ -122,6 +122,7 @@ struct mdk_rdev_s | |||
122 | #define Faulty 1 /* device is known to have a fault */ | 122 | #define Faulty 1 /* device is known to have a fault */ |
123 | #define In_sync 2 /* device is in_sync with rest of array */ | 123 | #define In_sync 2 /* device is in_sync with rest of array */ |
124 | #define WriteMostly 4 /* Avoid reading if at all possible */ | 124 | #define WriteMostly 4 /* Avoid reading if at all possible */ |
125 | #define BarriersNotsupp 5 /* BIO_RW_BARRIER is not supported */ | ||
125 | 126 | ||
126 | int desc_nr; /* descriptor index in the superblock */ | 127 | int desc_nr; /* descriptor index in the superblock */ |
127 | int raid_disk; /* role of device in array */ | 128 | int raid_disk; /* role of device in array */ |
@@ -210,6 +211,13 @@ struct mddev_s | |||
210 | int degraded; /* whether md should consider | 211 | int degraded; /* whether md should consider |
211 | * adding a spare | 212 | * adding a spare |
212 | */ | 213 | */ |
214 | int barriers_work; /* initialised to true, cleared as soon | ||
215 | * as a barrier request to slave | ||
216 | * fails. Only supported | ||
217 | */ | ||
218 | struct bio *biolist; /* bios that need to be retried | ||
219 | * because BIO_RW_BARRIER is not supported | ||
220 | */ | ||
213 | 221 | ||
214 | atomic_t recovery_active; /* blocks scheduled, but not written */ | 222 | atomic_t recovery_active; /* blocks scheduled, but not written */ |
215 | wait_queue_head_t recovery_wait; | 223 | wait_queue_head_t recovery_wait; |
diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index 60e19b667548..292b98f2b408 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h | |||
@@ -110,7 +110,9 @@ struct r1bio_s { | |||
110 | #define R1BIO_Uptodate 0 | 110 | #define R1BIO_Uptodate 0 |
111 | #define R1BIO_IsSync 1 | 111 | #define R1BIO_IsSync 1 |
112 | #define R1BIO_Degraded 2 | 112 | #define R1BIO_Degraded 2 |
113 | #define R1BIO_BehindIO 3 | 113 | #define R1BIO_BehindIO 3 |
114 | #define R1BIO_Barrier 4 | ||
115 | #define R1BIO_BarrierRetry 5 | ||
114 | /* For write-behind requests, we call bi_end_io when | 116 | /* For write-behind requests, we call bi_end_io when |
115 | * the last non-write-behind device completes, providing | 117 | * the last non-write-behind device completes, providing |
116 | * any write was successful. Otherwise we call when | 118 | * any write was successful. Otherwise we call when |