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 | { |