diff options
Diffstat (limited to 'fs/gfs2/lops.c')
| -rw-r--r-- | fs/gfs2/lops.c | 190 |
1 files changed, 6 insertions, 184 deletions
diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 94dcab655bc0..2295042bc625 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c | |||
| @@ -17,9 +17,7 @@ | |||
| 17 | #include <linux/bio.h> | 17 | #include <linux/bio.h> |
| 18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
| 19 | #include <linux/list_sort.h> | 19 | #include <linux/list_sort.h> |
| 20 | #include <linux/blkdev.h> | ||
| 21 | 20 | ||
| 22 | #include "bmap.h" | ||
| 23 | #include "dir.h" | 21 | #include "dir.h" |
| 24 | #include "gfs2.h" | 22 | #include "gfs2.h" |
| 25 | #include "incore.h" | 23 | #include "incore.h" |
| @@ -195,6 +193,7 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec, | |||
| 195 | /** | 193 | /** |
| 196 | * gfs2_end_log_write - end of i/o to the log | 194 | * gfs2_end_log_write - end of i/o to the log |
| 197 | * @bio: The bio | 195 | * @bio: The bio |
| 196 | * @error: Status of i/o request | ||
| 198 | * | 197 | * |
| 199 | * Each bio_vec contains either data from the pagecache or data | 198 | * Each bio_vec contains either data from the pagecache or data |
| 200 | * relating to the log itself. Here we iterate over the bio_vec | 199 | * relating to the log itself. Here we iterate over the bio_vec |
| @@ -231,19 +230,20 @@ static void gfs2_end_log_write(struct bio *bio) | |||
| 231 | /** | 230 | /** |
| 232 | * gfs2_log_submit_bio - Submit any pending log bio | 231 | * gfs2_log_submit_bio - Submit any pending log bio |
| 233 | * @biop: Address of the bio pointer | 232 | * @biop: Address of the bio pointer |
| 234 | * @opf: REQ_OP | op_flags | 233 | * @op: REQ_OP |
| 234 | * @op_flags: req_flag_bits | ||
| 235 | * | 235 | * |
| 236 | * Submit any pending part-built or full bio to the block device. If | 236 | * Submit any pending part-built or full bio to the block device. If |
| 237 | * there is no pending bio, then this is a no-op. | 237 | * there is no pending bio, then this is a no-op. |
| 238 | */ | 238 | */ |
| 239 | 239 | ||
| 240 | void gfs2_log_submit_bio(struct bio **biop, int opf) | 240 | void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags) |
| 241 | { | 241 | { |
| 242 | struct bio *bio = *biop; | 242 | struct bio *bio = *biop; |
| 243 | if (bio) { | 243 | if (bio) { |
| 244 | struct gfs2_sbd *sdp = bio->bi_private; | 244 | struct gfs2_sbd *sdp = bio->bi_private; |
| 245 | atomic_inc(&sdp->sd_log_in_flight); | 245 | atomic_inc(&sdp->sd_log_in_flight); |
| 246 | bio->bi_opf = opf; | 246 | bio_set_op_attrs(bio, op, op_flags); |
| 247 | submit_bio(bio); | 247 | submit_bio(bio); |
| 248 | *biop = NULL; | 248 | *biop = NULL; |
| 249 | } | 249 | } |
| @@ -304,7 +304,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno, | |||
| 304 | nblk >>= sdp->sd_fsb2bb_shift; | 304 | nblk >>= sdp->sd_fsb2bb_shift; |
| 305 | if (blkno == nblk && !flush) | 305 | if (blkno == nblk && !flush) |
| 306 | return bio; | 306 | return bio; |
| 307 | gfs2_log_submit_bio(biop, op); | 307 | gfs2_log_submit_bio(biop, op, 0); |
| 308 | } | 308 | } |
| 309 | 309 | ||
| 310 | *biop = gfs2_log_alloc_bio(sdp, blkno, end_io); | 310 | *biop = gfs2_log_alloc_bio(sdp, blkno, end_io); |
| @@ -375,184 +375,6 @@ void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page) | |||
| 375 | gfs2_log_bmap(sdp)); | 375 | gfs2_log_bmap(sdp)); |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | /** | ||
| 379 | * gfs2_end_log_read - end I/O callback for reads from the log | ||
| 380 | * @bio: The bio | ||
| 381 | * | ||
| 382 | * Simply unlock the pages in the bio. The main thread will wait on them and | ||
| 383 | * process them in order as necessary. | ||
| 384 | */ | ||
| 385 | |||
| 386 | static void gfs2_end_log_read(struct bio *bio) | ||
| 387 | { | ||
| 388 | struct page *page; | ||
| 389 | struct bio_vec *bvec; | ||
| 390 | int i; | ||
| 391 | |||
| 392 | bio_for_each_segment_all(bvec, bio, i) { | ||
| 393 | page = bvec->bv_page; | ||
| 394 | if (bio->bi_status) { | ||
| 395 | int err = blk_status_to_errno(bio->bi_status); | ||
| 396 | |||
| 397 | SetPageError(page); | ||
| 398 | mapping_set_error(page->mapping, err); | ||
| 399 | } | ||
| 400 | unlock_page(page); | ||
| 401 | } | ||
| 402 | |||
| 403 | bio_put(bio); | ||
| 404 | } | ||
| 405 | |||
| 406 | /** | ||
| 407 | * gfs2_jhead_pg_srch - Look for the journal head in a given page. | ||
| 408 | * @jd: The journal descriptor | ||
| 409 | * @page: The page to look in | ||
| 410 | * | ||
| 411 | * Returns: 1 if found, 0 otherwise. | ||
| 412 | */ | ||
| 413 | |||
| 414 | static bool gfs2_jhead_pg_srch(struct gfs2_jdesc *jd, | ||
| 415 | struct gfs2_log_header_host *head, | ||
| 416 | struct page *page) | ||
| 417 | { | ||
| 418 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); | ||
| 419 | struct gfs2_log_header_host uninitialized_var(lh); | ||
| 420 | void *kaddr = kmap_atomic(page); | ||
| 421 | unsigned int offset; | ||
| 422 | bool ret = false; | ||
| 423 | |||
| 424 | for (offset = 0; offset < PAGE_SIZE; offset += sdp->sd_sb.sb_bsize) { | ||
| 425 | if (!__get_log_header(sdp, kaddr + offset, 0, &lh)) { | ||
| 426 | if (lh.lh_sequence > head->lh_sequence) | ||
| 427 | *head = lh; | ||
| 428 | else { | ||
| 429 | ret = true; | ||
| 430 | break; | ||
| 431 | } | ||
| 432 | } | ||
| 433 | } | ||
| 434 | kunmap_atomic(kaddr); | ||
| 435 | return ret; | ||
| 436 | } | ||
| 437 | |||
| 438 | /** | ||
| 439 | * gfs2_jhead_process_page - Search/cleanup a page | ||
| 440 | * @jd: The journal descriptor | ||
| 441 | * @index: Index of the page to look into | ||
| 442 | * @done: If set, perform only cleanup, else search and set if found. | ||
| 443 | * | ||
| 444 | * Find the page with 'index' in the journal's mapping. Search the page for | ||
| 445 | * the journal head if requested (cleanup == false). Release refs on the | ||
| 446 | * page so the page cache can reclaim it (put_page() twice). We grabbed a | ||
| 447 | * reference on this page two times, first when we did a find_or_create_page() | ||
| 448 | * to obtain the page to add it to the bio and second when we do a | ||
| 449 | * find_get_page() here to get the page to wait on while I/O on it is being | ||
| 450 | * completed. | ||
| 451 | * This function is also used to free up a page we might've grabbed but not | ||
| 452 | * used. Maybe we added it to a bio, but not submitted it for I/O. Or we | ||
| 453 | * submitted the I/O, but we already found the jhead so we only need to drop | ||
| 454 | * our references to the page. | ||
| 455 | */ | ||
| 456 | |||
| 457 | static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index, | ||
| 458 | struct gfs2_log_header_host *head, | ||
| 459 | bool *done) | ||
| 460 | { | ||
| 461 | struct page *page; | ||
| 462 | |||
| 463 | page = find_get_page(jd->jd_inode->i_mapping, index); | ||
| 464 | wait_on_page_locked(page); | ||
| 465 | |||
| 466 | if (PageError(page)) | ||
| 467 | *done = true; | ||
| 468 | |||
| 469 | if (!*done) | ||
| 470 | *done = gfs2_jhead_pg_srch(jd, head, page); | ||
| 471 | |||
| 472 | put_page(page); /* Once for find_get_page */ | ||
| 473 | put_page(page); /* Once more for find_or_create_page */ | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * gfs2_find_jhead - find the head of a log | ||
| 478 | * @jd: The journal descriptor | ||
| 479 | * @head: The log descriptor for the head of the log is returned here | ||
| 480 | * | ||
| 481 | * Do a search of a journal by reading it in large chunks using bios and find | ||
| 482 | * the valid log entry with the highest sequence number. (i.e. the log head) | ||
| 483 | * | ||
| 484 | * Returns: 0 on success, errno otherwise | ||
| 485 | */ | ||
| 486 | |||
| 487 | int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head) | ||
| 488 | { | ||
| 489 | struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); | ||
| 490 | struct address_space *mapping = jd->jd_inode->i_mapping; | ||
| 491 | struct gfs2_journal_extent *je; | ||
| 492 | u32 block, read_idx = 0, submit_idx = 0, index = 0; | ||
| 493 | int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift; | ||
| 494 | int blocks_per_page = 1 << shift, sz, ret = 0; | ||
| 495 | struct bio *bio = NULL; | ||
| 496 | struct page *page; | ||
| 497 | bool done = false; | ||
| 498 | errseq_t since; | ||
| 499 | |||
| 500 | memset(head, 0, sizeof(*head)); | ||
| 501 | if (list_empty(&jd->extent_list)) | ||
| 502 | gfs2_map_journal_extents(sdp, jd); | ||
| 503 | |||
| 504 | since = filemap_sample_wb_err(mapping); | ||
| 505 | list_for_each_entry(je, &jd->extent_list, list) { | ||
| 506 | for (block = 0; block < je->blocks; block += blocks_per_page) { | ||
| 507 | index = (je->lblock + block) >> shift; | ||
| 508 | |||
| 509 | page = find_or_create_page(mapping, index, GFP_NOFS); | ||
| 510 | if (!page) { | ||
| 511 | ret = -ENOMEM; | ||
| 512 | done = true; | ||
| 513 | goto out; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (bio) { | ||
| 517 | sz = bio_add_page(bio, page, PAGE_SIZE, 0); | ||
| 518 | if (sz == PAGE_SIZE) | ||
| 519 | goto page_added; | ||
| 520 | submit_idx = index; | ||
| 521 | submit_bio(bio); | ||
| 522 | bio = NULL; | ||
| 523 | } | ||
| 524 | |||
| 525 | bio = gfs2_log_alloc_bio(sdp, | ||
| 526 | je->dblock + (index << shift), | ||
| 527 | gfs2_end_log_read); | ||
| 528 | bio->bi_opf = REQ_OP_READ; | ||
| 529 | sz = bio_add_page(bio, page, PAGE_SIZE, 0); | ||
| 530 | gfs2_assert_warn(sdp, sz == PAGE_SIZE); | ||
| 531 | |||
| 532 | page_added: | ||
| 533 | if (submit_idx <= read_idx + BIO_MAX_PAGES) { | ||
| 534 | /* Keep at least one bio in flight */ | ||
| 535 | continue; | ||
| 536 | } | ||
| 537 | |||
| 538 | gfs2_jhead_process_page(jd, read_idx++, head, &done); | ||
| 539 | if (done) | ||
| 540 | goto out; /* found */ | ||
| 541 | } | ||
| 542 | } | ||
| 543 | |||
| 544 | out: | ||
| 545 | if (bio) | ||
| 546 | submit_bio(bio); | ||
| 547 | while (read_idx <= index) | ||
| 548 | gfs2_jhead_process_page(jd, read_idx++, head, &done); | ||
| 549 | |||
| 550 | if (!ret) | ||
| 551 | ret = filemap_check_wb_err(mapping, since); | ||
| 552 | |||
| 553 | return ret; | ||
| 554 | } | ||
| 555 | |||
| 556 | static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type, | 378 | static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type, |
| 557 | u32 ld_length, u32 ld_data1) | 379 | u32 ld_length, u32 ld_data1) |
| 558 | { | 380 | { |
