resize.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /* 
  2.  * Copyright 2000-2002 by Hans Reiser, licensing governed by reiserfs/README
  3.  */
  4.  
  5. /* 
  6.  * Written by Alexander Zarochentcev.
  7.  *
  8.  * The kernel part of the (on-line) reiserfs resizer.
  9.  */
  10. #include <linux/kernel.h>
  11. #include <linux/vmalloc.h>
  12. #include <linux/locks.h>
  13. #include <linux/string.h>
  14. #include <linux/errno.h>
  15. #include <linux/reiserfs_fs.h>
  16. #include <linux/reiserfs_fs_sb.h>
  17. int reiserfs_resize (struct super_block * s, unsigned long block_count_new)
  18. {
  19. struct reiserfs_super_block * sb;
  20.         struct reiserfs_bitmap_info *bitmap;
  21. struct buffer_head * bh;
  22. struct reiserfs_transaction_handle th;
  23. unsigned int bmap_nr_new, bmap_nr;
  24. unsigned int block_r_new, block_r;
  25. struct reiserfs_list_bitmap * jb;
  26. struct reiserfs_list_bitmap jbitmap[JOURNAL_NUM_BITMAPS];
  27. unsigned long int block_count, free_blocks;
  28. int i;
  29. int copy_size ;
  30. sb = SB_DISK_SUPER_BLOCK(s);
  31. if (SB_BLOCK_COUNT(s) >= block_count_new) {
  32. printk("can't shrink filesystem on-linen");
  33. return -EINVAL;
  34. }
  35. /* check the device size */
  36. bh = sb_bread(s, block_count_new - 1);
  37. if (!bh) {
  38. printk("reiserfs_resize: can't read last blockn");
  39. return -EINVAL;
  40. }
  41. bforget(bh);
  42. /* old disk layout detection; those partitions can be mounted, but
  43.  * cannot be resized */
  44. if (SB_BUFFER_WITH_SB(s)->b_blocknr * SB_BUFFER_WITH_SB(s)->b_size 
  45. != REISERFS_DISK_OFFSET_IN_BYTES ) {
  46. printk("reiserfs_resize: unable to resize a reiserfs without distributed bitmap (fs version < 3.5.12)n");
  47. return -ENOTSUPP;
  48. }
  49.        
  50. /* count used bits in last bitmap block */
  51. block_r = SB_BLOCK_COUNT(s) -
  52.         (SB_BMAP_NR(s) - 1) * s->s_blocksize * 8;
  53. /* count bitmap blocks in new fs */
  54. bmap_nr_new = block_count_new / ( s->s_blocksize * 8 );
  55. block_r_new = block_count_new - bmap_nr_new * s->s_blocksize * 8;
  56. if (block_r_new) 
  57. bmap_nr_new++;
  58. else
  59. block_r_new = s->s_blocksize * 8;
  60. /* save old values */
  61. block_count = SB_BLOCK_COUNT(s);
  62. bmap_nr     = SB_BMAP_NR(s);
  63. /* resizing of reiserfs bitmaps (journal and real), if needed */
  64. if (bmap_nr_new > bmap_nr) {     
  65.     /* reallocate journal bitmaps */
  66.     if (reiserfs_allocate_list_bitmaps(s, jbitmap, bmap_nr_new) < 0) {
  67. printk("reiserfs_resize: unable to allocate memory for journal bitmapsn");
  68. unlock_super(s) ;
  69. return -ENOMEM ;
  70.     }
  71.     /* the new journal bitmaps are zero filled, now we copy in the bitmap
  72.     ** node pointers from the old journal bitmap structs, and then
  73.     ** transfer the new data structures into the journal struct.
  74.     **
  75.     ** using the copy_size var below allows this code to work for
  76.     ** both shrinking and expanding the FS.
  77.     */
  78.     copy_size = bmap_nr_new < bmap_nr ? bmap_nr_new : bmap_nr ;
  79.     copy_size = copy_size * sizeof(struct reiserfs_list_bitmap_node *) ;
  80.     for (i = 0 ; i < JOURNAL_NUM_BITMAPS ; i++) {
  81. struct reiserfs_bitmap_node **node_tmp ;
  82. jb = SB_JOURNAL(s)->j_list_bitmap + i ;
  83. memcpy(jbitmap[i].bitmaps, jb->bitmaps, copy_size) ;
  84. /* just in case vfree schedules on us, copy the new
  85. ** pointer into the journal struct before freeing the 
  86. ** old one
  87. */
  88. node_tmp = jb->bitmaps ;
  89. jb->bitmaps = jbitmap[i].bitmaps ;
  90. vfree(node_tmp) ;
  91.     }
  92.     /* allocate additional bitmap blocks, reallocate array of bitmap
  93.      * block pointers */
  94.     bitmap = vmalloc(sizeof(struct reiserfs_bitmap_info) * bmap_nr_new);
  95.     if (!bitmap) {
  96. printk("reiserfs_resize: unable to allocate memory.n");
  97. return -ENOMEM;
  98.     }
  99.     for (i = 0; i < bmap_nr; i++)
  100. bitmap[i] = SB_AP_BITMAP(s)[i];
  101.     for (i = bmap_nr; i < bmap_nr_new; i++) {
  102. bitmap[i].bh = sb_getblk(s, i * s->s_blocksize * 8);
  103. memset(bitmap[i].bh->b_data, 0, sb->s_blocksize);
  104. reiserfs_test_and_set_le_bit(0, bitmap[i].bh->b_data);
  105. mark_buffer_dirty(bitmap[i].bh) ;
  106. mark_buffer_uptodate(bitmap[i].bh, 1);
  107. ll_rw_block(WRITE, 1, &bitmap[i].bh);
  108. wait_on_buffer(bitmap[i].bh);
  109. bitmap[i].first_zero_hint=1;
  110. bitmap[i].free_count = s->s_blocksize * 8 - 1;
  111.     }
  112.     /* free old bitmap blocks array */
  113.     vfree(SB_AP_BITMAP(s)); 
  114.    
  115.     SB_AP_BITMAP(s) = bitmap;
  116. }
  117. /* begin transaction */
  118. journal_begin(&th, s, 10);
  119. /* correct last bitmap blocks in old and new disk layout */
  120. reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr - 1].bh, 1);
  121. for (i = block_r; i < s->s_blocksize * 8; i++)
  122.     reiserfs_test_and_clear_le_bit(i, 
  123.    SB_AP_BITMAP(s)[bmap_nr - 1].bh->b_data);
  124. SB_AP_BITMAP(s)[bmap_nr - 1].free_count += s->s_blocksize * 8 - block_r;
  125. if ( !SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint)
  126.     SB_AP_BITMAP(s)[bmap_nr - 1].first_zero_hint = block_r;
  127. journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr - 1].bh);
  128. reiserfs_prepare_for_journal(s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh, 1);
  129. for (i = block_r_new; i < s->s_blocksize * 8; i++)
  130.     reiserfs_test_and_set_le_bit(i,
  131.  SB_AP_BITMAP(s)[bmap_nr_new - 1].bh->b_data);
  132. journal_mark_dirty(&th, s, SB_AP_BITMAP(s)[bmap_nr_new - 1].bh);
  133. SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count -= s->s_blocksize * 8 - block_r_new;
  134. /* Extreme case where last bitmap is the only valid block in itself. */
  135. if ( !SB_AP_BITMAP(s)[bmap_nr_new - 1].free_count )
  136.     SB_AP_BITMAP(s)[bmap_nr_new - 1].first_zero_hint = 0;
  137.   /* update super */
  138. reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1) ;
  139. free_blocks = SB_FREE_BLOCKS(s);
  140. PUT_SB_FREE_BLOCKS(s, free_blocks + (block_count_new - block_count - (bmap_nr_new - bmap_nr)));
  141. PUT_SB_BLOCK_COUNT(s, block_count_new);
  142. PUT_SB_BMAP_NR(s, bmap_nr_new);
  143. s->s_dirt = 1;
  144. journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s));
  145. SB_JOURNAL(s)->j_must_wait = 1;
  146. journal_end(&th, s, 10);
  147. return 0;
  148. }