diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 139 |
1 files changed, 91 insertions, 48 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index e857f405353b..48a6461d601c 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -463,9 +463,62 @@ u64 gfs2_ri_total(struct gfs2_sbd *sdp) | |||
463 | } | 463 | } |
464 | 464 | ||
465 | /** | 465 | /** |
466 | * gfs2_ri_update - Pull in a new resource index from the disk | 466 | * read_rindex_entry - Pull in a new resource index entry from the disk |
467 | * @gl: The glock covering the rindex inode | 467 | * @gl: The glock covering the rindex inode |
468 | * | 468 | * |
469 | * Returns: 0 on success, error code otherwise | ||
470 | */ | ||
471 | |||
472 | static int read_rindex_entry(struct gfs2_inode *ip, | ||
473 | struct file_ra_state *ra_state) | ||
474 | { | ||
475 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
476 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | ||
477 | char buf[sizeof(struct gfs2_rindex)]; | ||
478 | int error; | ||
479 | struct gfs2_rgrpd *rgd; | ||
480 | |||
481 | error = gfs2_internal_read(ip, ra_state, buf, &pos, | ||
482 | sizeof(struct gfs2_rindex)); | ||
483 | if (!error) | ||
484 | return 0; | ||
485 | if (error != sizeof(struct gfs2_rindex)) { | ||
486 | if (error > 0) | ||
487 | error = -EIO; | ||
488 | return error; | ||
489 | } | ||
490 | |||
491 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | ||
492 | error = -ENOMEM; | ||
493 | if (!rgd) | ||
494 | return error; | ||
495 | |||
496 | mutex_init(&rgd->rd_mutex); | ||
497 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
498 | rgd->rd_sbd = sdp; | ||
499 | |||
500 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
501 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
502 | |||
503 | gfs2_rindex_in(&rgd->rd_ri, buf); | ||
504 | error = compute_bitstructs(rgd); | ||
505 | if (error) | ||
506 | return error; | ||
507 | |||
508 | error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr, | ||
509 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | ||
510 | if (error) | ||
511 | return error; | ||
512 | |||
513 | rgd->rd_gl->gl_object = rgd; | ||
514 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | ||
515 | return error; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * gfs2_ri_update - Pull in a new resource index from the disk | ||
520 | * @ip: pointer to the rindex inode | ||
521 | * | ||
469 | * Returns: 0 on successful update, error code otherwise | 522 | * Returns: 0 on successful update, error code otherwise |
470 | */ | 523 | */ |
471 | 524 | ||
@@ -473,18 +526,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
473 | { | 526 | { |
474 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 527 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
475 | struct inode *inode = &ip->i_inode; | 528 | struct inode *inode = &ip->i_inode; |
476 | struct gfs2_rgrpd *rgd; | ||
477 | char buf[sizeof(struct gfs2_rindex)]; | ||
478 | struct file_ra_state ra_state; | 529 | struct file_ra_state ra_state; |
479 | u64 junk = ip->i_di.di_size; | 530 | u64 junk = ip->i_di.di_size; |
480 | int error; | 531 | int error; |
481 | 532 | ||
482 | /* If someone is holding the rindex file with a glock, they must | 533 | if (do_div(junk, sizeof(struct gfs2_rindex))) { |
483 | be updating it, in which case we may have partial entries. | ||
484 | In this case, we ignore the partials. */ | ||
485 | if (!gfs2_glock_is_held_excl(ip->i_gl) && | ||
486 | !gfs2_glock_is_held_shrd(ip->i_gl) && | ||
487 | do_div(junk, sizeof(struct gfs2_rindex))) { | ||
488 | gfs2_consist_inode(ip); | 534 | gfs2_consist_inode(ip); |
489 | return -EIO; | 535 | return -EIO; |
490 | } | 536 | } |
@@ -493,52 +539,49 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
493 | 539 | ||
494 | file_ra_state_init(&ra_state, inode->i_mapping); | 540 | file_ra_state_init(&ra_state, inode->i_mapping); |
495 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { | 541 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
496 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | 542 | error = read_rindex_entry(ip, &ra_state); |
497 | 543 | if (error) { | |
498 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size) | 544 | clear_rgrpdi(sdp); |
499 | break; | 545 | return error; |
500 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | ||
501 | sizeof(struct gfs2_rindex)); | ||
502 | if (!error) | ||
503 | break; | ||
504 | if (error != sizeof(struct gfs2_rindex)) { | ||
505 | if (error > 0) | ||
506 | error = -EIO; | ||
507 | goto fail; | ||
508 | } | 546 | } |
547 | } | ||
509 | 548 | ||
510 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | 549 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
511 | error = -ENOMEM; | 550 | return 0; |
512 | if (!rgd) | 551 | } |
513 | goto fail; | ||
514 | |||
515 | mutex_init(&rgd->rd_mutex); | ||
516 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
517 | rgd->rd_sbd = sdp; | ||
518 | |||
519 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
520 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
521 | |||
522 | gfs2_rindex_in(&rgd->rd_ri, buf); | ||
523 | error = compute_bitstructs(rgd); | ||
524 | if (error) | ||
525 | goto fail; | ||
526 | 552 | ||
527 | error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr, | 553 | /** |
528 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | 554 | * gfs2_ri_update_special - Pull in a new resource index from the disk |
529 | if (error) | 555 | * |
530 | goto fail; | 556 | * This is a special version that's safe to call from gfs2_inplace_reserve_i. |
557 | * In this case we know that we don't have any resource groups in memory yet. | ||
558 | * | ||
559 | * @ip: pointer to the rindex inode | ||
560 | * | ||
561 | * Returns: 0 on successful update, error code otherwise | ||
562 | */ | ||
563 | static int gfs2_ri_update_special(struct gfs2_inode *ip) | ||
564 | { | ||
565 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
566 | struct inode *inode = &ip->i_inode; | ||
567 | struct file_ra_state ra_state; | ||
568 | int error; | ||
531 | 569 | ||
532 | rgd->rd_gl->gl_object = rgd; | 570 | file_ra_state_init(&ra_state, inode->i_mapping); |
533 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | 571 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
572 | /* Ignore partials */ | ||
573 | if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > | ||
574 | ip->i_di.di_size) | ||
575 | break; | ||
576 | error = read_rindex_entry(ip, &ra_state); | ||
577 | if (error) { | ||
578 | clear_rgrpdi(sdp); | ||
579 | return error; | ||
580 | } | ||
534 | } | 581 | } |
535 | 582 | ||
536 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; | 583 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
537 | return 0; | 584 | return 0; |
538 | |||
539 | fail: | ||
540 | clear_rgrpdi(sdp); | ||
541 | return error; | ||
542 | } | 585 | } |
543 | 586 | ||
544 | /** | 587 | /** |
@@ -1028,7 +1071,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1028 | if (ip != GFS2_I(sdp->sd_rindex)) | 1071 | if (ip != GFS2_I(sdp->sd_rindex)) |
1029 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1072 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); |
1030 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | 1073 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ |
1031 | error = gfs2_ri_update(ip); | 1074 | error = gfs2_ri_update_special(ip); |
1032 | 1075 | ||
1033 | if (error) | 1076 | if (error) |
1034 | return error; | 1077 | return error; |