diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 377 |
1 files changed, 281 insertions, 96 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 1727f5012efe..e4e040625153 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. | 2 | * Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved. |
3 | * Copyright (C) 2004-2006 Red Hat, Inc. All rights reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. |
4 | * | 4 | * |
5 | * This copyrighted material is made available to anyone wishing to use, | 5 | * This copyrighted material is made available to anyone wishing to use, |
6 | * modify, copy, or redistribute it subject to the terms and conditions | 6 | * modify, copy, or redistribute it subject to the terms and conditions |
@@ -28,6 +28,7 @@ | |||
28 | #include "ops_file.h" | 28 | #include "ops_file.h" |
29 | #include "util.h" | 29 | #include "util.h" |
30 | #include "log.h" | 30 | #include "log.h" |
31 | #include "inode.h" | ||
31 | 32 | ||
32 | #define BFITNOENT ((u32)~0) | 33 | #define BFITNOENT ((u32)~0) |
33 | 34 | ||
@@ -50,6 +51,9 @@ static const char valid_change[16] = { | |||
50 | 1, 0, 0, 0 | 51 | 1, 0, 0, 0 |
51 | }; | 52 | }; |
52 | 53 | ||
54 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | ||
55 | unsigned char old_state, unsigned char new_state); | ||
56 | |||
53 | /** | 57 | /** |
54 | * gfs2_setbit - Set a bit in the bitmaps | 58 | * gfs2_setbit - Set a bit in the bitmaps |
55 | * @buffer: the buffer that holds the bitmaps | 59 | * @buffer: the buffer that holds the bitmaps |
@@ -204,7 +208,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
204 | { | 208 | { |
205 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 209 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
206 | struct gfs2_bitmap *bi = NULL; | 210 | struct gfs2_bitmap *bi = NULL; |
207 | u32 length = rgd->rd_ri.ri_length; | 211 | u32 length = rgd->rd_length; |
208 | u32 count[4], tmp; | 212 | u32 count[4], tmp; |
209 | int buf, x; | 213 | int buf, x; |
210 | 214 | ||
@@ -227,7 +231,7 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
227 | return; | 231 | return; |
228 | } | 232 | } |
229 | 233 | ||
230 | tmp = rgd->rd_ri.ri_data - | 234 | tmp = rgd->rd_data - |
231 | rgd->rd_rg.rg_free - | 235 | rgd->rd_rg.rg_free - |
232 | rgd->rd_rg.rg_dinodes; | 236 | rgd->rd_rg.rg_dinodes; |
233 | if (count[1] + count[2] != tmp) { | 237 | if (count[1] + count[2] != tmp) { |
@@ -253,10 +257,10 @@ void gfs2_rgrp_verify(struct gfs2_rgrpd *rgd) | |||
253 | 257 | ||
254 | } | 258 | } |
255 | 259 | ||
256 | static inline int rgrp_contains_block(struct gfs2_rindex_host *ri, u64 block) | 260 | static inline int rgrp_contains_block(struct gfs2_rgrpd *rgd, u64 block) |
257 | { | 261 | { |
258 | u64 first = ri->ri_data0; | 262 | u64 first = rgd->rd_data0; |
259 | u64 last = first + ri->ri_data; | 263 | u64 last = first + rgd->rd_data; |
260 | return first <= block && block < last; | 264 | return first <= block && block < last; |
261 | } | 265 | } |
262 | 266 | ||
@@ -275,7 +279,7 @@ struct gfs2_rgrpd *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, u64 blk) | |||
275 | spin_lock(&sdp->sd_rindex_spin); | 279 | spin_lock(&sdp->sd_rindex_spin); |
276 | 280 | ||
277 | list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) { | 281 | list_for_each_entry(rgd, &sdp->sd_rindex_mru_list, rd_list_mru) { |
278 | if (rgrp_contains_block(&rgd->rd_ri, blk)) { | 282 | if (rgrp_contains_block(rgd, blk)) { |
279 | list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | 283 | list_move(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); |
280 | spin_unlock(&sdp->sd_rindex_spin); | 284 | spin_unlock(&sdp->sd_rindex_spin); |
281 | return rgd; | 285 | return rgd; |
@@ -354,6 +358,15 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) | |||
354 | mutex_unlock(&sdp->sd_rindex_mutex); | 358 | mutex_unlock(&sdp->sd_rindex_mutex); |
355 | } | 359 | } |
356 | 360 | ||
361 | static void gfs2_rindex_print(const struct gfs2_rgrpd *rgd) | ||
362 | { | ||
363 | printk(KERN_INFO " ri_addr = %llu\n", (unsigned long long)rgd->rd_addr); | ||
364 | printk(KERN_INFO " ri_length = %u\n", rgd->rd_length); | ||
365 | printk(KERN_INFO " ri_data0 = %llu\n", (unsigned long long)rgd->rd_data0); | ||
366 | printk(KERN_INFO " ri_data = %u\n", rgd->rd_data); | ||
367 | printk(KERN_INFO " ri_bitbytes = %u\n", rgd->rd_bitbytes); | ||
368 | } | ||
369 | |||
357 | /** | 370 | /** |
358 | * gfs2_compute_bitstructs - Compute the bitmap sizes | 371 | * gfs2_compute_bitstructs - Compute the bitmap sizes |
359 | * @rgd: The resource group descriptor | 372 | * @rgd: The resource group descriptor |
@@ -367,7 +380,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
367 | { | 380 | { |
368 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 381 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
369 | struct gfs2_bitmap *bi; | 382 | struct gfs2_bitmap *bi; |
370 | u32 length = rgd->rd_ri.ri_length; /* # blocks in hdr & bitmap */ | 383 | u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */ |
371 | u32 bytes_left, bytes; | 384 | u32 bytes_left, bytes; |
372 | int x; | 385 | int x; |
373 | 386 | ||
@@ -378,7 +391,7 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
378 | if (!rgd->rd_bits) | 391 | if (!rgd->rd_bits) |
379 | return -ENOMEM; | 392 | return -ENOMEM; |
380 | 393 | ||
381 | bytes_left = rgd->rd_ri.ri_bitbytes; | 394 | bytes_left = rgd->rd_bitbytes; |
382 | 395 | ||
383 | for (x = 0; x < length; x++) { | 396 | for (x = 0; x < length; x++) { |
384 | bi = rgd->rd_bits + x; | 397 | bi = rgd->rd_bits + x; |
@@ -399,14 +412,14 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
399 | } else if (x + 1 == length) { | 412 | } else if (x + 1 == length) { |
400 | bytes = bytes_left; | 413 | bytes = bytes_left; |
401 | bi->bi_offset = sizeof(struct gfs2_meta_header); | 414 | bi->bi_offset = sizeof(struct gfs2_meta_header); |
402 | bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; | 415 | bi->bi_start = rgd->rd_bitbytes - bytes_left; |
403 | bi->bi_len = bytes; | 416 | bi->bi_len = bytes; |
404 | /* other blocks */ | 417 | /* other blocks */ |
405 | } else { | 418 | } else { |
406 | bytes = sdp->sd_sb.sb_bsize - | 419 | bytes = sdp->sd_sb.sb_bsize - |
407 | sizeof(struct gfs2_meta_header); | 420 | sizeof(struct gfs2_meta_header); |
408 | bi->bi_offset = sizeof(struct gfs2_meta_header); | 421 | bi->bi_offset = sizeof(struct gfs2_meta_header); |
409 | bi->bi_start = rgd->rd_ri.ri_bitbytes - bytes_left; | 422 | bi->bi_start = rgd->rd_bitbytes - bytes_left; |
410 | bi->bi_len = bytes; | 423 | bi->bi_len = bytes; |
411 | } | 424 | } |
412 | 425 | ||
@@ -418,9 +431,9 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
418 | return -EIO; | 431 | return -EIO; |
419 | } | 432 | } |
420 | bi = rgd->rd_bits + (length - 1); | 433 | bi = rgd->rd_bits + (length - 1); |
421 | if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_ri.ri_data) { | 434 | if ((bi->bi_start + bi->bi_len) * GFS2_NBBY != rgd->rd_data) { |
422 | if (gfs2_consist_rgrpd(rgd)) { | 435 | if (gfs2_consist_rgrpd(rgd)) { |
423 | gfs2_rindex_print(&rgd->rd_ri); | 436 | gfs2_rindex_print(rgd); |
424 | fs_err(sdp, "start=%u len=%u offset=%u\n", | 437 | fs_err(sdp, "start=%u len=%u offset=%u\n", |
425 | bi->bi_start, bi->bi_len, bi->bi_offset); | 438 | bi->bi_start, bi->bi_len, bi->bi_offset); |
426 | } | 439 | } |
@@ -431,9 +444,104 @@ static int compute_bitstructs(struct gfs2_rgrpd *rgd) | |||
431 | } | 444 | } |
432 | 445 | ||
433 | /** | 446 | /** |
434 | * gfs2_ri_update - Pull in a new resource index from the disk | 447 | * gfs2_ri_total - Total up the file system space, according to the rindex. |
448 | * | ||
449 | */ | ||
450 | u64 gfs2_ri_total(struct gfs2_sbd *sdp) | ||
451 | { | ||
452 | u64 total_data = 0; | ||
453 | struct inode *inode = sdp->sd_rindex; | ||
454 | struct gfs2_inode *ip = GFS2_I(inode); | ||
455 | char buf[sizeof(struct gfs2_rindex)]; | ||
456 | struct file_ra_state ra_state; | ||
457 | int error, rgrps; | ||
458 | |||
459 | mutex_lock(&sdp->sd_rindex_mutex); | ||
460 | file_ra_state_init(&ra_state, inode->i_mapping); | ||
461 | for (rgrps = 0;; rgrps++) { | ||
462 | loff_t pos = rgrps * sizeof(struct gfs2_rindex); | ||
463 | |||
464 | if (pos + sizeof(struct gfs2_rindex) >= ip->i_di.di_size) | ||
465 | break; | ||
466 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | ||
467 | sizeof(struct gfs2_rindex)); | ||
468 | if (error != sizeof(struct gfs2_rindex)) | ||
469 | break; | ||
470 | total_data += be32_to_cpu(((struct gfs2_rindex *)buf)->ri_data); | ||
471 | } | ||
472 | mutex_unlock(&sdp->sd_rindex_mutex); | ||
473 | return total_data; | ||
474 | } | ||
475 | |||
476 | static void gfs2_rindex_in(struct gfs2_rgrpd *rgd, const void *buf) | ||
477 | { | ||
478 | const struct gfs2_rindex *str = buf; | ||
479 | |||
480 | rgd->rd_addr = be64_to_cpu(str->ri_addr); | ||
481 | rgd->rd_length = be32_to_cpu(str->ri_length); | ||
482 | rgd->rd_data0 = be64_to_cpu(str->ri_data0); | ||
483 | rgd->rd_data = be32_to_cpu(str->ri_data); | ||
484 | rgd->rd_bitbytes = be32_to_cpu(str->ri_bitbytes); | ||
485 | } | ||
486 | |||
487 | /** | ||
488 | * read_rindex_entry - Pull in a new resource index entry from the disk | ||
435 | * @gl: The glock covering the rindex inode | 489 | * @gl: The glock covering the rindex inode |
436 | * | 490 | * |
491 | * Returns: 0 on success, error code otherwise | ||
492 | */ | ||
493 | |||
494 | static int read_rindex_entry(struct gfs2_inode *ip, | ||
495 | struct file_ra_state *ra_state) | ||
496 | { | ||
497 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
498 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | ||
499 | char buf[sizeof(struct gfs2_rindex)]; | ||
500 | int error; | ||
501 | struct gfs2_rgrpd *rgd; | ||
502 | |||
503 | error = gfs2_internal_read(ip, ra_state, buf, &pos, | ||
504 | sizeof(struct gfs2_rindex)); | ||
505 | if (!error) | ||
506 | return 0; | ||
507 | if (error != sizeof(struct gfs2_rindex)) { | ||
508 | if (error > 0) | ||
509 | error = -EIO; | ||
510 | return error; | ||
511 | } | ||
512 | |||
513 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | ||
514 | error = -ENOMEM; | ||
515 | if (!rgd) | ||
516 | return error; | ||
517 | |||
518 | mutex_init(&rgd->rd_mutex); | ||
519 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
520 | rgd->rd_sbd = sdp; | ||
521 | |||
522 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
523 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
524 | |||
525 | gfs2_rindex_in(rgd, buf); | ||
526 | error = compute_bitstructs(rgd); | ||
527 | if (error) | ||
528 | return error; | ||
529 | |||
530 | error = gfs2_glock_get(sdp, rgd->rd_addr, | ||
531 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | ||
532 | if (error) | ||
533 | return error; | ||
534 | |||
535 | rgd->rd_gl->gl_object = rgd; | ||
536 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | ||
537 | rgd->rd_flags |= GFS2_RDF_CHECK; | ||
538 | return error; | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * gfs2_ri_update - Pull in a new resource index from the disk | ||
543 | * @ip: pointer to the rindex inode | ||
544 | * | ||
437 | * Returns: 0 on successful update, error code otherwise | 545 | * Returns: 0 on successful update, error code otherwise |
438 | */ | 546 | */ |
439 | 547 | ||
@@ -441,13 +549,11 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
441 | { | 549 | { |
442 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 550 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
443 | struct inode *inode = &ip->i_inode; | 551 | struct inode *inode = &ip->i_inode; |
444 | struct gfs2_rgrpd *rgd; | ||
445 | char buf[sizeof(struct gfs2_rindex)]; | ||
446 | struct file_ra_state ra_state; | 552 | struct file_ra_state ra_state; |
447 | u64 junk = ip->i_di.di_size; | 553 | u64 rgrp_count = ip->i_di.di_size; |
448 | int error; | 554 | int error; |
449 | 555 | ||
450 | if (do_div(junk, sizeof(struct gfs2_rindex))) { | 556 | if (do_div(rgrp_count, sizeof(struct gfs2_rindex))) { |
451 | gfs2_consist_inode(ip); | 557 | gfs2_consist_inode(ip); |
452 | return -EIO; | 558 | return -EIO; |
453 | } | 559 | } |
@@ -455,50 +561,50 @@ static int gfs2_ri_update(struct gfs2_inode *ip) | |||
455 | clear_rgrpdi(sdp); | 561 | clear_rgrpdi(sdp); |
456 | 562 | ||
457 | file_ra_state_init(&ra_state, inode->i_mapping); | 563 | file_ra_state_init(&ra_state, inode->i_mapping); |
458 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { | 564 | for (sdp->sd_rgrps = 0; sdp->sd_rgrps < rgrp_count; sdp->sd_rgrps++) { |
459 | loff_t pos = sdp->sd_rgrps * sizeof(struct gfs2_rindex); | 565 | error = read_rindex_entry(ip, &ra_state); |
460 | error = gfs2_internal_read(ip, &ra_state, buf, &pos, | 566 | if (error) { |
461 | sizeof(struct gfs2_rindex)); | 567 | clear_rgrpdi(sdp); |
462 | if (!error) | 568 | return error; |
463 | break; | ||
464 | if (error != sizeof(struct gfs2_rindex)) { | ||
465 | if (error > 0) | ||
466 | error = -EIO; | ||
467 | goto fail; | ||
468 | } | 569 | } |
570 | } | ||
469 | 571 | ||
470 | rgd = kzalloc(sizeof(struct gfs2_rgrpd), GFP_NOFS); | 572 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
471 | error = -ENOMEM; | 573 | return 0; |
472 | if (!rgd) | 574 | } |
473 | goto fail; | ||
474 | |||
475 | mutex_init(&rgd->rd_mutex); | ||
476 | lops_init_le(&rgd->rd_le, &gfs2_rg_lops); | ||
477 | rgd->rd_sbd = sdp; | ||
478 | |||
479 | list_add_tail(&rgd->rd_list, &sdp->sd_rindex_list); | ||
480 | list_add_tail(&rgd->rd_list_mru, &sdp->sd_rindex_mru_list); | ||
481 | |||
482 | gfs2_rindex_in(&rgd->rd_ri, buf); | ||
483 | error = compute_bitstructs(rgd); | ||
484 | if (error) | ||
485 | goto fail; | ||
486 | 575 | ||
487 | error = gfs2_glock_get(sdp, rgd->rd_ri.ri_addr, | 576 | /** |
488 | &gfs2_rgrp_glops, CREATE, &rgd->rd_gl); | 577 | * gfs2_ri_update_special - Pull in a new resource index from the disk |
489 | if (error) | 578 | * |
490 | goto fail; | 579 | * This is a special version that's safe to call from gfs2_inplace_reserve_i. |
580 | * In this case we know that we don't have any resource groups in memory yet. | ||
581 | * | ||
582 | * @ip: pointer to the rindex inode | ||
583 | * | ||
584 | * Returns: 0 on successful update, error code otherwise | ||
585 | */ | ||
586 | static int gfs2_ri_update_special(struct gfs2_inode *ip) | ||
587 | { | ||
588 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | ||
589 | struct inode *inode = &ip->i_inode; | ||
590 | struct file_ra_state ra_state; | ||
591 | int error; | ||
491 | 592 | ||
492 | rgd->rd_gl->gl_object = rgd; | 593 | file_ra_state_init(&ra_state, inode->i_mapping); |
493 | rgd->rd_rg_vn = rgd->rd_gl->gl_vn - 1; | 594 | for (sdp->sd_rgrps = 0;; sdp->sd_rgrps++) { |
595 | /* Ignore partials */ | ||
596 | if ((sdp->sd_rgrps + 1) * sizeof(struct gfs2_rindex) > | ||
597 | ip->i_di.di_size) | ||
598 | break; | ||
599 | error = read_rindex_entry(ip, &ra_state); | ||
600 | if (error) { | ||
601 | clear_rgrpdi(sdp); | ||
602 | return error; | ||
603 | } | ||
494 | } | 604 | } |
495 | 605 | ||
496 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; | 606 | sdp->sd_rindex_vn = ip->i_gl->gl_vn; |
497 | return 0; | 607 | return 0; |
498 | |||
499 | fail: | ||
500 | clear_rgrpdi(sdp); | ||
501 | return error; | ||
502 | } | 608 | } |
503 | 609 | ||
504 | /** | 610 | /** |
@@ -543,6 +649,28 @@ int gfs2_rindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ri_gh) | |||
543 | return error; | 649 | return error; |
544 | } | 650 | } |
545 | 651 | ||
652 | static void gfs2_rgrp_in(struct gfs2_rgrp_host *rg, const void *buf) | ||
653 | { | ||
654 | const struct gfs2_rgrp *str = buf; | ||
655 | |||
656 | rg->rg_flags = be32_to_cpu(str->rg_flags); | ||
657 | rg->rg_free = be32_to_cpu(str->rg_free); | ||
658 | rg->rg_dinodes = be32_to_cpu(str->rg_dinodes); | ||
659 | rg->rg_igeneration = be64_to_cpu(str->rg_igeneration); | ||
660 | } | ||
661 | |||
662 | static void gfs2_rgrp_out(const struct gfs2_rgrp_host *rg, void *buf) | ||
663 | { | ||
664 | struct gfs2_rgrp *str = buf; | ||
665 | |||
666 | str->rg_flags = cpu_to_be32(rg->rg_flags); | ||
667 | str->rg_free = cpu_to_be32(rg->rg_free); | ||
668 | str->rg_dinodes = cpu_to_be32(rg->rg_dinodes); | ||
669 | str->__pad = cpu_to_be32(0); | ||
670 | str->rg_igeneration = cpu_to_be64(rg->rg_igeneration); | ||
671 | memset(&str->rg_reserved, 0, sizeof(str->rg_reserved)); | ||
672 | } | ||
673 | |||
546 | /** | 674 | /** |
547 | * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps | 675 | * gfs2_rgrp_bh_get - Read in a RG's header and bitmaps |
548 | * @rgd: the struct gfs2_rgrpd describing the RG to read in | 676 | * @rgd: the struct gfs2_rgrpd describing the RG to read in |
@@ -557,7 +685,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
557 | { | 685 | { |
558 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 686 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
559 | struct gfs2_glock *gl = rgd->rd_gl; | 687 | struct gfs2_glock *gl = rgd->rd_gl; |
560 | unsigned int length = rgd->rd_ri.ri_length; | 688 | unsigned int length = rgd->rd_length; |
561 | struct gfs2_bitmap *bi; | 689 | struct gfs2_bitmap *bi; |
562 | unsigned int x, y; | 690 | unsigned int x, y; |
563 | int error; | 691 | int error; |
@@ -575,7 +703,7 @@ int gfs2_rgrp_bh_get(struct gfs2_rgrpd *rgd) | |||
575 | 703 | ||
576 | for (x = 0; x < length; x++) { | 704 | for (x = 0; x < length; x++) { |
577 | bi = rgd->rd_bits + x; | 705 | bi = rgd->rd_bits + x; |
578 | error = gfs2_meta_read(gl, rgd->rd_ri.ri_addr + x, 0, &bi->bi_bh); | 706 | error = gfs2_meta_read(gl, rgd->rd_addr + x, 0, &bi->bi_bh); |
579 | if (error) | 707 | if (error) |
580 | goto fail; | 708 | goto fail; |
581 | } | 709 | } |
@@ -637,7 +765,7 @@ void gfs2_rgrp_bh_hold(struct gfs2_rgrpd *rgd) | |||
637 | void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) | 765 | void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) |
638 | { | 766 | { |
639 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 767 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
640 | int x, length = rgd->rd_ri.ri_length; | 768 | int x, length = rgd->rd_length; |
641 | 769 | ||
642 | spin_lock(&sdp->sd_rindex_spin); | 770 | spin_lock(&sdp->sd_rindex_spin); |
643 | gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count); | 771 | gfs2_assert_warn(rgd->rd_sbd, rgd->rd_bh_count); |
@@ -660,7 +788,7 @@ void gfs2_rgrp_bh_put(struct gfs2_rgrpd *rgd) | |||
660 | void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) | 788 | void gfs2_rgrp_repolish_clones(struct gfs2_rgrpd *rgd) |
661 | { | 789 | { |
662 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 790 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
663 | unsigned int length = rgd->rd_ri.ri_length; | 791 | unsigned int length = rgd->rd_length; |
664 | unsigned int x; | 792 | unsigned int x; |
665 | 793 | ||
666 | for (x = 0; x < length; x++) { | 794 | for (x = 0; x < length; x++) { |
@@ -722,6 +850,38 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
722 | } | 850 | } |
723 | 851 | ||
724 | /** | 852 | /** |
853 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes | ||
854 | * @rgd: The rgrp | ||
855 | * | ||
856 | * Returns: The inode, if one has been found | ||
857 | */ | ||
858 | |||
859 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked) | ||
860 | { | ||
861 | struct inode *inode; | ||
862 | u32 goal = 0; | ||
863 | u64 no_addr; | ||
864 | |||
865 | for(;;) { | ||
866 | goal = rgblk_search(rgd, goal, GFS2_BLKST_UNLINKED, | ||
867 | GFS2_BLKST_UNLINKED); | ||
868 | if (goal == 0) | ||
869 | return 0; | ||
870 | no_addr = goal + rgd->rd_data0; | ||
871 | if (no_addr <= *last_unlinked) | ||
872 | continue; | ||
873 | *last_unlinked = no_addr; | ||
874 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | ||
875 | no_addr, -1); | ||
876 | if (!IS_ERR(inode)) | ||
877 | return inode; | ||
878 | } | ||
879 | |||
880 | rgd->rd_flags &= ~GFS2_RDF_CHECK; | ||
881 | return NULL; | ||
882 | } | ||
883 | |||
884 | /** | ||
725 | * recent_rgrp_first - get first RG from "recent" list | 885 | * recent_rgrp_first - get first RG from "recent" list |
726 | * @sdp: The GFS2 superblock | 886 | * @sdp: The GFS2 superblock |
727 | * @rglast: address of the rgrp used last | 887 | * @rglast: address of the rgrp used last |
@@ -743,7 +903,7 @@ static struct gfs2_rgrpd *recent_rgrp_first(struct gfs2_sbd *sdp, | |||
743 | goto first; | 903 | goto first; |
744 | 904 | ||
745 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { | 905 | list_for_each_entry(rgd, &sdp->sd_rindex_recent_list, rd_recent) { |
746 | if (rgd->rd_ri.ri_addr == rglast) | 906 | if (rgd->rd_addr == rglast) |
747 | goto out; | 907 | goto out; |
748 | } | 908 | } |
749 | 909 | ||
@@ -882,8 +1042,9 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) | |||
882 | * Returns: errno | 1042 | * Returns: errno |
883 | */ | 1043 | */ |
884 | 1044 | ||
885 | static int get_local_rgrp(struct gfs2_inode *ip) | 1045 | static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) |
886 | { | 1046 | { |
1047 | struct inode *inode = NULL; | ||
887 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1048 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
888 | struct gfs2_rgrpd *rgd, *begin = NULL; | 1049 | struct gfs2_rgrpd *rgd, *begin = NULL; |
889 | struct gfs2_alloc *al = &ip->i_alloc; | 1050 | struct gfs2_alloc *al = &ip->i_alloc; |
@@ -903,7 +1064,11 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
903 | case 0: | 1064 | case 0: |
904 | if (try_rgrp_fit(rgd, al)) | 1065 | if (try_rgrp_fit(rgd, al)) |
905 | goto out; | 1066 | goto out; |
1067 | if (rgd->rd_flags & GFS2_RDF_CHECK) | ||
1068 | inode = try_rgrp_unlink(rgd, last_unlinked); | ||
906 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1069 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1070 | if (inode) | ||
1071 | return inode; | ||
907 | rgd = recent_rgrp_next(rgd, 1); | 1072 | rgd = recent_rgrp_next(rgd, 1); |
908 | break; | 1073 | break; |
909 | 1074 | ||
@@ -912,7 +1077,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
912 | break; | 1077 | break; |
913 | 1078 | ||
914 | default: | 1079 | default: |
915 | return error; | 1080 | return ERR_PTR(error); |
916 | } | 1081 | } |
917 | } | 1082 | } |
918 | 1083 | ||
@@ -927,7 +1092,11 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
927 | case 0: | 1092 | case 0: |
928 | if (try_rgrp_fit(rgd, al)) | 1093 | if (try_rgrp_fit(rgd, al)) |
929 | goto out; | 1094 | goto out; |
1095 | if (rgd->rd_flags & GFS2_RDF_CHECK) | ||
1096 | inode = try_rgrp_unlink(rgd, last_unlinked); | ||
930 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1097 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1098 | if (inode) | ||
1099 | return inode; | ||
931 | break; | 1100 | break; |
932 | 1101 | ||
933 | case GLR_TRYFAILED: | 1102 | case GLR_TRYFAILED: |
@@ -935,7 +1104,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
935 | break; | 1104 | break; |
936 | 1105 | ||
937 | default: | 1106 | default: |
938 | return error; | 1107 | return ERR_PTR(error); |
939 | } | 1108 | } |
940 | 1109 | ||
941 | rgd = gfs2_rgrpd_get_next(rgd); | 1110 | rgd = gfs2_rgrpd_get_next(rgd); |
@@ -944,7 +1113,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
944 | 1113 | ||
945 | if (rgd == begin) { | 1114 | if (rgd == begin) { |
946 | if (++loops >= 3) | 1115 | if (++loops >= 3) |
947 | return -ENOSPC; | 1116 | return ERR_PTR(-ENOSPC); |
948 | if (!skipped) | 1117 | if (!skipped) |
949 | loops++; | 1118 | loops++; |
950 | flags = 0; | 1119 | flags = 0; |
@@ -954,7 +1123,7 @@ static int get_local_rgrp(struct gfs2_inode *ip) | |||
954 | } | 1123 | } |
955 | 1124 | ||
956 | out: | 1125 | out: |
957 | ip->i_last_rg_alloc = rgd->rd_ri.ri_addr; | 1126 | ip->i_last_rg_alloc = rgd->rd_addr; |
958 | 1127 | ||
959 | if (begin) { | 1128 | if (begin) { |
960 | recent_rgrp_add(rgd); | 1129 | recent_rgrp_add(rgd); |
@@ -964,7 +1133,7 @@ out: | |||
964 | forward_rgrp_set(sdp, rgd); | 1133 | forward_rgrp_set(sdp, rgd); |
965 | } | 1134 | } |
966 | 1135 | ||
967 | return 0; | 1136 | return NULL; |
968 | } | 1137 | } |
969 | 1138 | ||
970 | /** | 1139 | /** |
@@ -978,19 +1147,33 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
978 | { | 1147 | { |
979 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1148 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
980 | struct gfs2_alloc *al = &ip->i_alloc; | 1149 | struct gfs2_alloc *al = &ip->i_alloc; |
981 | int error; | 1150 | struct inode *inode; |
1151 | int error = 0; | ||
1152 | u64 last_unlinked = 0; | ||
982 | 1153 | ||
983 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1154 | if (gfs2_assert_warn(sdp, al->al_requested)) |
984 | return -EINVAL; | 1155 | return -EINVAL; |
985 | 1156 | ||
986 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1157 | try_again: |
1158 | /* We need to hold the rindex unless the inode we're using is | ||
1159 | the rindex itself, in which case it's already held. */ | ||
1160 | if (ip != GFS2_I(sdp->sd_rindex)) | ||
1161 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | ||
1162 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | ||
1163 | error = gfs2_ri_update_special(ip); | ||
1164 | |||
987 | if (error) | 1165 | if (error) |
988 | return error; | 1166 | return error; |
989 | 1167 | ||
990 | error = get_local_rgrp(ip); | 1168 | inode = get_local_rgrp(ip, &last_unlinked); |
991 | if (error) { | 1169 | if (inode) { |
992 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1170 | if (ip != GFS2_I(sdp->sd_rindex)) |
993 | return error; | 1171 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1172 | if (IS_ERR(inode)) | ||
1173 | return PTR_ERR(inode); | ||
1174 | iput(inode); | ||
1175 | gfs2_log_flush(sdp, NULL); | ||
1176 | goto try_again; | ||
994 | } | 1177 | } |
995 | 1178 | ||
996 | al->al_file = file; | 1179 | al->al_file = file; |
@@ -1019,7 +1202,8 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1019 | 1202 | ||
1020 | al->al_rgd = NULL; | 1203 | al->al_rgd = NULL; |
1021 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1204 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1022 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1205 | if (ip != GFS2_I(sdp->sd_rindex)) |
1206 | gfs2_glock_dq_uninit(&al->al_ri_gh); | ||
1023 | } | 1207 | } |
1024 | 1208 | ||
1025 | /** | 1209 | /** |
@@ -1037,8 +1221,8 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1037 | unsigned int buf; | 1221 | unsigned int buf; |
1038 | unsigned char type; | 1222 | unsigned char type; |
1039 | 1223 | ||
1040 | length = rgd->rd_ri.ri_length; | 1224 | length = rgd->rd_length; |
1041 | rgrp_block = block - rgd->rd_ri.ri_data0; | 1225 | rgrp_block = block - rgd->rd_data0; |
1042 | 1226 | ||
1043 | for (buf = 0; buf < length; buf++) { | 1227 | for (buf = 0; buf < length; buf++) { |
1044 | bi = rgd->rd_bits + buf; | 1228 | bi = rgd->rd_bits + buf; |
@@ -1077,10 +1261,10 @@ unsigned char gfs2_get_block_type(struct gfs2_rgrpd *rgd, u64 block) | |||
1077 | */ | 1261 | */ |
1078 | 1262 | ||
1079 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | 1263 | static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, |
1080 | unsigned char old_state, unsigned char new_state) | 1264 | unsigned char old_state, unsigned char new_state) |
1081 | { | 1265 | { |
1082 | struct gfs2_bitmap *bi = NULL; | 1266 | struct gfs2_bitmap *bi = NULL; |
1083 | u32 length = rgd->rd_ri.ri_length; | 1267 | u32 length = rgd->rd_length; |
1084 | u32 blk = 0; | 1268 | u32 blk = 0; |
1085 | unsigned int buf, x; | 1269 | unsigned int buf, x; |
1086 | 1270 | ||
@@ -1118,17 +1302,18 @@ static u32 rgblk_search(struct gfs2_rgrpd *rgd, u32 goal, | |||
1118 | goal = 0; | 1302 | goal = 0; |
1119 | } | 1303 | } |
1120 | 1304 | ||
1121 | if (gfs2_assert_withdraw(rgd->rd_sbd, x <= length)) | 1305 | if (old_state != new_state) { |
1122 | blk = 0; | 1306 | gfs2_assert_withdraw(rgd->rd_sbd, blk != BFITNOENT); |
1123 | 1307 | ||
1124 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); | 1308 | gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1); |
1125 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, | 1309 | gfs2_setbit(rgd, bi->bi_bh->b_data + bi->bi_offset, |
1126 | bi->bi_len, blk, new_state); | ||
1127 | if (bi->bi_clone) | ||
1128 | gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, | ||
1129 | bi->bi_len, blk, new_state); | 1310 | bi->bi_len, blk, new_state); |
1311 | if (bi->bi_clone) | ||
1312 | gfs2_setbit(rgd, bi->bi_clone + bi->bi_offset, | ||
1313 | bi->bi_len, blk, new_state); | ||
1314 | } | ||
1130 | 1315 | ||
1131 | return bi->bi_start * GFS2_NBBY + blk; | 1316 | return (blk == BFITNOENT) ? 0 : (bi->bi_start * GFS2_NBBY) + blk; |
1132 | } | 1317 | } |
1133 | 1318 | ||
1134 | /** | 1319 | /** |
@@ -1156,9 +1341,9 @@ static struct gfs2_rgrpd *rgblk_free(struct gfs2_sbd *sdp, u64 bstart, | |||
1156 | return NULL; | 1341 | return NULL; |
1157 | } | 1342 | } |
1158 | 1343 | ||
1159 | length = rgd->rd_ri.ri_length; | 1344 | length = rgd->rd_length; |
1160 | 1345 | ||
1161 | rgrp_blk = bstart - rgd->rd_ri.ri_data0; | 1346 | rgrp_blk = bstart - rgd->rd_data0; |
1162 | 1347 | ||
1163 | while (blen--) { | 1348 | while (blen--) { |
1164 | for (buf = 0; buf < length; buf++) { | 1349 | for (buf = 0; buf < length; buf++) { |
@@ -1202,15 +1387,15 @@ u64 gfs2_alloc_data(struct gfs2_inode *ip) | |||
1202 | u32 goal, blk; | 1387 | u32 goal, blk; |
1203 | u64 block; | 1388 | u64 block; |
1204 | 1389 | ||
1205 | if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_data)) | 1390 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_data)) |
1206 | goal = ip->i_di.di_goal_data - rgd->rd_ri.ri_data0; | 1391 | goal = ip->i_di.di_goal_data - rgd->rd_data0; |
1207 | else | 1392 | else |
1208 | goal = rgd->rd_last_alloc_data; | 1393 | goal = rgd->rd_last_alloc_data; |
1209 | 1394 | ||
1210 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | 1395 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); |
1211 | rgd->rd_last_alloc_data = blk; | 1396 | rgd->rd_last_alloc_data = blk; |
1212 | 1397 | ||
1213 | block = rgd->rd_ri.ri_data0 + blk; | 1398 | block = rgd->rd_data0 + blk; |
1214 | ip->i_di.di_goal_data = block; | 1399 | ip->i_di.di_goal_data = block; |
1215 | 1400 | ||
1216 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1401 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
@@ -1246,15 +1431,15 @@ u64 gfs2_alloc_meta(struct gfs2_inode *ip) | |||
1246 | u32 goal, blk; | 1431 | u32 goal, blk; |
1247 | u64 block; | 1432 | u64 block; |
1248 | 1433 | ||
1249 | if (rgrp_contains_block(&rgd->rd_ri, ip->i_di.di_goal_meta)) | 1434 | if (rgrp_contains_block(rgd, ip->i_di.di_goal_meta)) |
1250 | goal = ip->i_di.di_goal_meta - rgd->rd_ri.ri_data0; | 1435 | goal = ip->i_di.di_goal_meta - rgd->rd_data0; |
1251 | else | 1436 | else |
1252 | goal = rgd->rd_last_alloc_meta; | 1437 | goal = rgd->rd_last_alloc_meta; |
1253 | 1438 | ||
1254 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); | 1439 | blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, GFS2_BLKST_USED); |
1255 | rgd->rd_last_alloc_meta = blk; | 1440 | rgd->rd_last_alloc_meta = blk; |
1256 | 1441 | ||
1257 | block = rgd->rd_ri.ri_data0 + blk; | 1442 | block = rgd->rd_data0 + blk; |
1258 | ip->i_di.di_goal_meta = block; | 1443 | ip->i_di.di_goal_meta = block; |
1259 | 1444 | ||
1260 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1445 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
@@ -1296,7 +1481,7 @@ u64 gfs2_alloc_di(struct gfs2_inode *dip, u64 *generation) | |||
1296 | 1481 | ||
1297 | rgd->rd_last_alloc_meta = blk; | 1482 | rgd->rd_last_alloc_meta = blk; |
1298 | 1483 | ||
1299 | block = rgd->rd_ri.ri_data0 + blk; | 1484 | block = rgd->rd_data0 + blk; |
1300 | 1485 | ||
1301 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); | 1486 | gfs2_assert_withdraw(sdp, rgd->rd_rg.rg_free); |
1302 | rgd->rd_rg.rg_free--; | 1487 | rgd->rd_rg.rg_free--; |
@@ -1379,7 +1564,7 @@ void gfs2_unlink_di(struct inode *inode) | |||
1379 | struct gfs2_inode *ip = GFS2_I(inode); | 1564 | struct gfs2_inode *ip = GFS2_I(inode); |
1380 | struct gfs2_sbd *sdp = GFS2_SB(inode); | 1565 | struct gfs2_sbd *sdp = GFS2_SB(inode); |
1381 | struct gfs2_rgrpd *rgd; | 1566 | struct gfs2_rgrpd *rgd; |
1382 | u64 blkno = ip->i_num.no_addr; | 1567 | u64 blkno = ip->i_no_addr; |
1383 | 1568 | ||
1384 | rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); | 1569 | rgd = rgblk_free(sdp, blkno, 1, GFS2_BLKST_UNLINKED); |
1385 | if (!rgd) | 1570 | if (!rgd) |
@@ -1414,9 +1599,9 @@ static void gfs2_free_uninit_di(struct gfs2_rgrpd *rgd, u64 blkno) | |||
1414 | 1599 | ||
1415 | void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) | 1600 | void gfs2_free_di(struct gfs2_rgrpd *rgd, struct gfs2_inode *ip) |
1416 | { | 1601 | { |
1417 | gfs2_free_uninit_di(rgd, ip->i_num.no_addr); | 1602 | gfs2_free_uninit_di(rgd, ip->i_no_addr); |
1418 | gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); | 1603 | gfs2_quota_change(ip, -1, ip->i_inode.i_uid, ip->i_inode.i_gid); |
1419 | gfs2_meta_wipe(ip, ip->i_num.no_addr, 1); | 1604 | gfs2_meta_wipe(ip, ip->i_no_addr, 1); |
1420 | } | 1605 | } |
1421 | 1606 | ||
1422 | /** | 1607 | /** |