diff options
Diffstat (limited to 'fs/gfs2/recovery.c')
| -rw-r--r-- | fs/gfs2/recovery.c | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 7389e445a7a7..2dac43065382 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c | |||
| @@ -182,6 +182,129 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk, | |||
| 182 | } | 182 | } |
| 183 | 183 | ||
| 184 | /** | 184 | /** |
| 185 | * find_good_lh - find a good log header | ||
| 186 | * @jd: the journal | ||
| 187 | * @blk: the segment to start searching from | ||
| 188 | * @lh: the log header to fill in | ||
| 189 | * @forward: if true search forward in the log, else search backward | ||
| 190 | * | ||
| 191 | * Call get_log_header() to get a log header for a segment, but if the | ||
| 192 | * segment is bad, either scan forward or backward until we find a good one. | ||
| 193 | * | ||
| 194 | * Returns: errno | ||
| 195 | */ | ||
| 196 | |||
| 197 | static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk, | ||
| 198 | struct gfs2_log_header_host *head) | ||
| 199 | { | ||
| 200 | unsigned int orig_blk = *blk; | ||
| 201 | int error; | ||
| 202 | |||
| 203 | for (;;) { | ||
| 204 | error = get_log_header(jd, *blk, head); | ||
| 205 | if (error <= 0) | ||
| 206 | return error; | ||
| 207 | |||
| 208 | if (++*blk == jd->jd_blocks) | ||
| 209 | *blk = 0; | ||
| 210 | |||
| 211 | if (*blk == orig_blk) { | ||
| 212 | gfs2_consist_inode(GFS2_I(jd->jd_inode)); | ||
| 213 | return -EIO; | ||
| 214 | } | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 218 | /** | ||
| 219 | * jhead_scan - make sure we've found the head of the log | ||
| 220 | * @jd: the journal | ||
| 221 | * @head: this is filled in with the log descriptor of the head | ||
| 222 | * | ||
| 223 | * At this point, seg and lh should be either the head of the log or just | ||
| 224 | * before. Scan forward until we find the head. | ||
| 225 | * | ||
| 226 | * Returns: errno | ||
| 227 | */ | ||
| 228 | |||
| 229 | static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) | ||
| 230 | { | ||
| 231 | unsigned int blk = head->lh_blkno; | ||
| 232 | struct gfs2_log_header_host lh; | ||
| 233 | int error; | ||
| 234 | |||
| 235 | for (;;) { | ||
| 236 | if (++blk == jd->jd_blocks) | ||
| 237 | blk = 0; | ||
| 238 | |||
| 239 | error = get_log_header(jd, blk, &lh); | ||
| 240 | if (error < 0) | ||
| 241 | return error; | ||
| 242 | if (error == 1) | ||
| 243 | continue; | ||
| 244 | |||
| 245 | if (lh.lh_sequence == head->lh_sequence) { | ||
| 246 | gfs2_consist_inode(GFS2_I(jd->jd_inode)); | ||
| 247 | return -EIO; | ||
| 248 | } | ||
| 249 | if (lh.lh_sequence < head->lh_sequence) | ||
| 250 | break; | ||
| 251 | |||
| 252 | *head = lh; | ||
| 253 | } | ||
| 254 | |||
| 255 | return 0; | ||
| 256 | } | ||
| 257 | |||
| 258 | /** | ||
| 259 | * gfs2_find_jhead - find the head of a log | ||
| 260 | * @jd: the journal | ||
| 261 | * @head: the log descriptor for the head of the log is returned here | ||
| 262 | * | ||
| 263 | * Do a binary search of a journal and find the valid log entry with the | ||
| 264 | * highest sequence number. (i.e. the log head) | ||
| 265 | * | ||
| 266 | * Returns: errno | ||
| 267 | */ | ||
| 268 | |||
| 269 | int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) | ||
| 270 | { | ||
| 271 | struct gfs2_log_header_host lh_1, lh_m; | ||
| 272 | u32 blk_1, blk_2, blk_m; | ||
| 273 | int error; | ||
| 274 | |||
| 275 | blk_1 = 0; | ||
| 276 | blk_2 = jd->jd_blocks - 1; | ||
| 277 | |||
| 278 | for (;;) { | ||
| 279 | blk_m = (blk_1 + blk_2) / 2; | ||
| 280 | |||
| 281 | error = find_good_lh(jd, &blk_1, &lh_1); | ||
| 282 | if (error) | ||
| 283 | return error; | ||
| 284 | |||
| 285 | error = find_good_lh(jd, &blk_m, &lh_m); | ||
| 286 | if (error) | ||
| 287 | return error; | ||
| 288 | |||
| 289 | if (blk_1 == blk_m || blk_m == blk_2) | ||
| 290 | break; | ||
| 291 | |||
| 292 | if (lh_1.lh_sequence <= lh_m.lh_sequence) | ||
| 293 | blk_1 = blk_m; | ||
| 294 | else | ||
| 295 | blk_2 = blk_m; | ||
| 296 | } | ||
| 297 | |||
| 298 | error = jhead_scan(jd, &lh_1); | ||
| 299 | if (error) | ||
| 300 | return error; | ||
| 301 | |||
| 302 | *head = lh_1; | ||
| 303 | |||
| 304 | return error; | ||
| 305 | } | ||
| 306 | |||
| 307 | /** | ||
| 185 | * foreach_descriptor - go through the active part of the log | 308 | * foreach_descriptor - go through the active part of the log |
| 186 | * @jd: the journal | 309 | * @jd: the journal |
| 187 | * @start: the first log header in the active region | 310 | * @start: the first log header in the active region |
