diff options
Diffstat (limited to 'drivers/md/md.h')
-rw-r--r-- | drivers/md/md.h | 48 |
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/md/md.h b/drivers/md/md.h index 7d906a96477a..85af8433f8b8 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -29,6 +29,13 @@ | |||
29 | typedef struct mddev_s mddev_t; | 29 | typedef struct mddev_s mddev_t; |
30 | typedef struct mdk_rdev_s mdk_rdev_t; | 30 | typedef struct mdk_rdev_s mdk_rdev_t; |
31 | 31 | ||
32 | /* Bad block numbers are stored sorted in a single page. | ||
33 | * 64bits is used for each block or extent. | ||
34 | * 54 bits are sector number, 9 bits are extent size, | ||
35 | * 1 bit is an 'acknowledged' flag. | ||
36 | */ | ||
37 | #define MD_MAX_BADBLOCKS (PAGE_SIZE/8) | ||
38 | |||
32 | /* | 39 | /* |
33 | * MD's 'extended' device | 40 | * MD's 'extended' device |
34 | */ | 41 | */ |
@@ -111,8 +118,47 @@ struct mdk_rdev_s | |||
111 | 118 | ||
112 | struct sysfs_dirent *sysfs_state; /* handle for 'state' | 119 | struct sysfs_dirent *sysfs_state; /* handle for 'state' |
113 | * sysfs entry */ | 120 | * sysfs entry */ |
121 | |||
122 | struct badblocks { | ||
123 | int count; /* count of bad blocks */ | ||
124 | int shift; /* shift from sectors to block size | ||
125 | * a -ve shift means badblocks are | ||
126 | * disabled.*/ | ||
127 | u64 *page; /* badblock list */ | ||
128 | int changed; | ||
129 | seqlock_t lock; | ||
130 | } badblocks; | ||
114 | }; | 131 | }; |
115 | 132 | ||
133 | #define BB_LEN_MASK (0x00000000000001FFULL) | ||
134 | #define BB_OFFSET_MASK (0x7FFFFFFFFFFFFE00ULL) | ||
135 | #define BB_ACK_MASK (0x8000000000000000ULL) | ||
136 | #define BB_MAX_LEN 512 | ||
137 | #define BB_OFFSET(x) (((x) & BB_OFFSET_MASK) >> 9) | ||
138 | #define BB_LEN(x) (((x) & BB_LEN_MASK) + 1) | ||
139 | #define BB_ACK(x) (!!((x) & BB_ACK_MASK)) | ||
140 | #define BB_MAKE(a, l, ack) (((a)<<9) | ((l)-1) | ((u64)(!!(ack)) << 63)) | ||
141 | |||
142 | extern int md_is_badblock(struct badblocks *bb, sector_t s, int sectors, | ||
143 | sector_t *first_bad, int *bad_sectors); | ||
144 | static inline int is_badblock(mdk_rdev_t *rdev, sector_t s, int sectors, | ||
145 | sector_t *first_bad, int *bad_sectors) | ||
146 | { | ||
147 | if (unlikely(rdev->badblocks.count)) { | ||
148 | int rv = md_is_badblock(&rdev->badblocks, rdev->data_offset + s, | ||
149 | sectors, | ||
150 | first_bad, bad_sectors); | ||
151 | if (rv) | ||
152 | *first_bad -= rdev->data_offset; | ||
153 | return rv; | ||
154 | } | ||
155 | return 0; | ||
156 | } | ||
157 | extern int rdev_set_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors, | ||
158 | int acknowledged); | ||
159 | extern int rdev_clear_badblocks(mdk_rdev_t *rdev, sector_t s, int sectors); | ||
160 | extern void md_ack_all_badblocks(struct badblocks *bb); | ||
161 | |||
116 | struct mddev_s | 162 | struct mddev_s |
117 | { | 163 | { |
118 | void *private; | 164 | void *private; |
@@ -517,7 +563,7 @@ extern void mddev_init(mddev_t *mddev); | |||
517 | extern int md_run(mddev_t *mddev); | 563 | extern int md_run(mddev_t *mddev); |
518 | extern void md_stop(mddev_t *mddev); | 564 | extern void md_stop(mddev_t *mddev); |
519 | extern void md_stop_writes(mddev_t *mddev); | 565 | extern void md_stop_writes(mddev_t *mddev); |
520 | extern void md_rdev_init(mdk_rdev_t *rdev); | 566 | extern int md_rdev_init(mdk_rdev_t *rdev); |
521 | 567 | ||
522 | extern void mddev_suspend(mddev_t *mddev); | 568 | extern void mddev_suspend(mddev_t *mddev); |
523 | extern void mddev_resume(mddev_t *mddev); | 569 | extern void mddev_resume(mddev_t *mddev); |