diff options
Diffstat (limited to 'fs/gfs2/super.c')
| -rw-r--r-- | fs/gfs2/super.c | 246 |
1 files changed, 4 insertions, 242 deletions
diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index c3ba3d9d0aac..141b781f2fcc 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c | |||
| @@ -34,76 +34,6 @@ | |||
| 34 | #include "util.h" | 34 | #include "util.h" |
| 35 | 35 | ||
| 36 | /** | 36 | /** |
| 37 | * gfs2_jindex_hold - Grab a lock on the jindex | ||
| 38 | * @sdp: The GFS2 superblock | ||
| 39 | * @ji_gh: the holder for the jindex glock | ||
| 40 | * | ||
| 41 | * This is very similar to the gfs2_rindex_hold() function, except that | ||
| 42 | * in general we hold the jindex lock for longer periods of time and | ||
| 43 | * we grab it far less frequently (in general) then the rgrp lock. | ||
| 44 | * | ||
| 45 | * Returns: errno | ||
| 46 | */ | ||
| 47 | |||
| 48 | int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) | ||
| 49 | { | ||
| 50 | struct gfs2_inode *dip = GFS2_I(sdp->sd_jindex); | ||
| 51 | struct qstr name; | ||
| 52 | char buf[20]; | ||
| 53 | struct gfs2_jdesc *jd; | ||
| 54 | int error; | ||
| 55 | |||
| 56 | name.name = buf; | ||
| 57 | |||
| 58 | mutex_lock(&sdp->sd_jindex_mutex); | ||
| 59 | |||
| 60 | for (;;) { | ||
| 61 | error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh); | ||
| 62 | if (error) | ||
| 63 | break; | ||
| 64 | |||
| 65 | name.len = sprintf(buf, "journal%u", sdp->sd_journals); | ||
| 66 | name.hash = gfs2_disk_hash(name.name, name.len); | ||
| 67 | |||
| 68 | error = gfs2_dir_check(sdp->sd_jindex, &name, NULL); | ||
| 69 | if (error == -ENOENT) { | ||
| 70 | error = 0; | ||
| 71 | break; | ||
| 72 | } | ||
| 73 | |||
| 74 | gfs2_glock_dq_uninit(ji_gh); | ||
| 75 | |||
| 76 | if (error) | ||
| 77 | break; | ||
| 78 | |||
| 79 | error = -ENOMEM; | ||
| 80 | jd = kzalloc(sizeof(struct gfs2_jdesc), GFP_KERNEL); | ||
| 81 | if (!jd) | ||
| 82 | break; | ||
| 83 | |||
| 84 | INIT_LIST_HEAD(&jd->extent_list); | ||
| 85 | jd->jd_inode = gfs2_lookupi(sdp->sd_jindex, &name, 1); | ||
| 86 | if (!jd->jd_inode || IS_ERR(jd->jd_inode)) { | ||
| 87 | if (!jd->jd_inode) | ||
| 88 | error = -ENOENT; | ||
| 89 | else | ||
| 90 | error = PTR_ERR(jd->jd_inode); | ||
| 91 | kfree(jd); | ||
| 92 | break; | ||
| 93 | } | ||
| 94 | |||
| 95 | spin_lock(&sdp->sd_jindex_spin); | ||
| 96 | jd->jd_jid = sdp->sd_journals++; | ||
| 97 | list_add_tail(&jd->jd_list, &sdp->sd_jindex_list); | ||
| 98 | spin_unlock(&sdp->sd_jindex_spin); | ||
| 99 | } | ||
| 100 | |||
| 101 | mutex_unlock(&sdp->sd_jindex_mutex); | ||
| 102 | |||
| 103 | return error; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * gfs2_jindex_free - Clear all the journal index information | 37 | * gfs2_jindex_free - Clear all the journal index information |
| 108 | * @sdp: The GFS2 superblock | 38 | * @sdp: The GFS2 superblock |
| 109 | * | 39 | * |
| @@ -166,39 +96,6 @@ struct gfs2_jdesc *gfs2_jdesc_find(struct gfs2_sbd *sdp, unsigned int jid) | |||
| 166 | return jd; | 96 | return jd; |
| 167 | } | 97 | } |
| 168 | 98 | ||
| 169 | void gfs2_jdesc_make_dirty(struct gfs2_sbd *sdp, unsigned int jid) | ||
| 170 | { | ||
| 171 | struct gfs2_jdesc *jd; | ||
| 172 | |||
| 173 | spin_lock(&sdp->sd_jindex_spin); | ||
| 174 | jd = jdesc_find_i(&sdp->sd_jindex_list, jid); | ||
| 175 | if (jd) | ||
| 176 | jd->jd_dirty = 1; | ||
| 177 | spin_unlock(&sdp->sd_jindex_spin); | ||
| 178 | } | ||
| 179 | |||
| 180 | struct gfs2_jdesc *gfs2_jdesc_find_dirty(struct gfs2_sbd *sdp) | ||
| 181 | { | ||
| 182 | struct gfs2_jdesc *jd; | ||
| 183 | int found = 0; | ||
| 184 | |||
| 185 | spin_lock(&sdp->sd_jindex_spin); | ||
| 186 | |||
| 187 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | ||
| 188 | if (jd->jd_dirty) { | ||
| 189 | jd->jd_dirty = 0; | ||
| 190 | found = 1; | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | spin_unlock(&sdp->sd_jindex_spin); | ||
| 195 | |||
| 196 | if (!found) | ||
| 197 | jd = NULL; | ||
| 198 | |||
| 199 | return jd; | ||
| 200 | } | ||
| 201 | |||
| 202 | int gfs2_jdesc_check(struct gfs2_jdesc *jd) | 99 | int gfs2_jdesc_check(struct gfs2_jdesc *jd) |
| 203 | { | 100 | { |
| 204 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); | 101 | struct gfs2_inode *ip = GFS2_I(jd->jd_inode); |
| @@ -206,14 +103,14 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) | |||
| 206 | int ar; | 103 | int ar; |
| 207 | int error; | 104 | int error; |
| 208 | 105 | ||
| 209 | if (ip->i_di.di_size < (8 << 20) || ip->i_di.di_size > (1 << 30) || | 106 | if (ip->i_disksize < (8 << 20) || ip->i_disksize > (1 << 30) || |
| 210 | (ip->i_di.di_size & (sdp->sd_sb.sb_bsize - 1))) { | 107 | (ip->i_disksize & (sdp->sd_sb.sb_bsize - 1))) { |
| 211 | gfs2_consist_inode(ip); | 108 | gfs2_consist_inode(ip); |
| 212 | return -EIO; | 109 | return -EIO; |
| 213 | } | 110 | } |
| 214 | jd->jd_blocks = ip->i_di.di_size >> sdp->sd_sb.sb_bsize_shift; | 111 | jd->jd_blocks = ip->i_disksize >> sdp->sd_sb.sb_bsize_shift; |
| 215 | 112 | ||
| 216 | error = gfs2_write_alloc_required(ip, 0, ip->i_di.di_size, &ar); | 113 | error = gfs2_write_alloc_required(ip, 0, ip->i_disksize, &ar); |
| 217 | if (!error && ar) { | 114 | if (!error && ar) { |
| 218 | gfs2_consist_inode(ip); | 115 | gfs2_consist_inode(ip); |
| 219 | error = -EIO; | 116 | error = -EIO; |
| @@ -423,137 +320,6 @@ out: | |||
| 423 | return error; | 320 | return error; |
| 424 | } | 321 | } |
| 425 | 322 | ||
| 426 | /** | ||
| 427 | * gfs2_statfs_i - Do a statfs | ||
| 428 | * @sdp: the filesystem | ||
| 429 | * @sg: the sg structure | ||
| 430 | * | ||
| 431 | * Returns: errno | ||
| 432 | */ | ||
| 433 | |||
| 434 | int gfs2_statfs_i(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
| 435 | { | ||
| 436 | struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; | ||
| 437 | struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; | ||
| 438 | |||
| 439 | spin_lock(&sdp->sd_statfs_spin); | ||
| 440 | |||
| 441 | *sc = *m_sc; | ||
| 442 | sc->sc_total += l_sc->sc_total; | ||
| 443 | sc->sc_free += l_sc->sc_free; | ||
| 444 | sc->sc_dinodes += l_sc->sc_dinodes; | ||
| 445 | |||
| 446 | spin_unlock(&sdp->sd_statfs_spin); | ||
| 447 | |||
| 448 | if (sc->sc_free < 0) | ||
| 449 | sc->sc_free = 0; | ||
| 450 | if (sc->sc_free > sc->sc_total) | ||
| 451 | sc->sc_free = sc->sc_total; | ||
| 452 | if (sc->sc_dinodes < 0) | ||
| 453 | sc->sc_dinodes = 0; | ||
| 454 | |||
| 455 | return 0; | ||
| 456 | } | ||
| 457 | |||
| 458 | /** | ||
| 459 | * statfs_fill - fill in the sg for a given RG | ||
| 460 | * @rgd: the RG | ||
| 461 | * @sc: the sc structure | ||
| 462 | * | ||
| 463 | * Returns: 0 on success, -ESTALE if the LVB is invalid | ||
| 464 | */ | ||
| 465 | |||
| 466 | static int statfs_slow_fill(struct gfs2_rgrpd *rgd, | ||
| 467 | struct gfs2_statfs_change_host *sc) | ||
| 468 | { | ||
| 469 | gfs2_rgrp_verify(rgd); | ||
| 470 | sc->sc_total += rgd->rd_data; | ||
| 471 | sc->sc_free += rgd->rd_rg.rg_free; | ||
| 472 | sc->sc_dinodes += rgd->rd_rg.rg_dinodes; | ||
| 473 | return 0; | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * gfs2_statfs_slow - Stat a filesystem using asynchronous locking | ||
| 478 | * @sdp: the filesystem | ||
| 479 | * @sc: the sc info that will be returned | ||
| 480 | * | ||
| 481 | * Any error (other than a signal) will cause this routine to fall back | ||
| 482 | * to the synchronous version. | ||
| 483 | * | ||
| 484 | * FIXME: This really shouldn't busy wait like this. | ||
| 485 | * | ||
| 486 | * Returns: errno | ||
| 487 | */ | ||
| 488 | |||
| 489 | int gfs2_statfs_slow(struct gfs2_sbd *sdp, struct gfs2_statfs_change_host *sc) | ||
| 490 | { | ||
| 491 | struct gfs2_holder ri_gh; | ||
| 492 | struct gfs2_rgrpd *rgd_next; | ||
| 493 | struct gfs2_holder *gha, *gh; | ||
| 494 | unsigned int slots = 64; | ||
| 495 | unsigned int x; | ||
| 496 | int done; | ||
| 497 | int error = 0, err; | ||
| 498 | |||
| 499 | memset(sc, 0, sizeof(struct gfs2_statfs_change_host)); | ||
| 500 | gha = kcalloc(slots, sizeof(struct gfs2_holder), GFP_KERNEL); | ||
| 501 | if (!gha) | ||
| 502 | return -ENOMEM; | ||
| 503 | |||
| 504 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
| 505 | if (error) | ||
| 506 | goto out; | ||
| 507 | |||
| 508 | rgd_next = gfs2_rgrpd_get_first(sdp); | ||
| 509 | |||
| 510 | for (;;) { | ||
| 511 | done = 1; | ||
| 512 | |||
| 513 | for (x = 0; x < slots; x++) { | ||
| 514 | gh = gha + x; | ||
| 515 | |||
| 516 | if (gh->gh_gl && gfs2_glock_poll(gh)) { | ||
| 517 | err = gfs2_glock_wait(gh); | ||
| 518 | if (err) { | ||
| 519 | gfs2_holder_uninit(gh); | ||
| 520 | error = err; | ||
| 521 | } else { | ||
| 522 | if (!error) | ||
| 523 | error = statfs_slow_fill( | ||
| 524 | gh->gh_gl->gl_object, sc); | ||
| 525 | gfs2_glock_dq_uninit(gh); | ||
| 526 | } | ||
| 527 | } | ||
| 528 | |||
| 529 | if (gh->gh_gl) | ||
| 530 | done = 0; | ||
| 531 | else if (rgd_next && !error) { | ||
| 532 | error = gfs2_glock_nq_init(rgd_next->rd_gl, | ||
| 533 | LM_ST_SHARED, | ||
| 534 | GL_ASYNC, | ||
| 535 | gh); | ||
| 536 | rgd_next = gfs2_rgrpd_get_next(rgd_next); | ||
| 537 | done = 0; | ||
| 538 | } | ||
| 539 | |||
| 540 | if (signal_pending(current)) | ||
| 541 | error = -ERESTARTSYS; | ||
| 542 | } | ||
| 543 | |||
| 544 | if (done) | ||
| 545 | break; | ||
| 546 | |||
| 547 | yield(); | ||
| 548 | } | ||
| 549 | |||
| 550 | gfs2_glock_dq_uninit(&ri_gh); | ||
| 551 | |||
| 552 | out: | ||
| 553 | kfree(gha); | ||
| 554 | return error; | ||
| 555 | } | ||
| 556 | |||
| 557 | struct lfcc { | 323 | struct lfcc { |
| 558 | struct list_head list; | 324 | struct list_head list; |
| 559 | struct gfs2_holder gh; | 325 | struct gfs2_holder gh; |
| @@ -580,10 +346,6 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp, | |||
| 580 | struct gfs2_log_header_host lh; | 346 | struct gfs2_log_header_host lh; |
| 581 | int error; | 347 | int error; |
| 582 | 348 | ||
| 583 | error = gfs2_jindex_hold(sdp, &ji_gh); | ||
| 584 | if (error) | ||
| 585 | return error; | ||
| 586 | |||
| 587 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { | 349 | list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { |
| 588 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); | 350 | lfcc = kmalloc(sizeof(struct lfcc), GFP_KERNEL); |
| 589 | if (!lfcc) { | 351 | if (!lfcc) { |
