"Fossies" - the Fresh Open Source Software Archive

Member "reiserfsprogs-3.6.25/resize_reiserfs/resize_reiserfs.c" (6 Jun 2016, 8584 Bytes) of archive /linux/misc/reiserfsprogs-3.6.25.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "resize_reiserfs.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 3.6.21_vs_3.6.24.

    1 /*
    2  * Copyright 2000-2004 by Hans Reiser, licensing governed by
    3  * reiserfsprogs/README
    4  */
    5 
    6 /*
    7  * Written by Alexander Zarochentcev.
    8  *
    9  * FS resize utility
   10  *
   11  */
   12 
   13 #define _GNU_SOURCE
   14 
   15 #include "resize.h"
   16 #include <limits.h>
   17 
   18 static int opt_banner = 0;
   19 static int opt_skipj = 0;
   20 int opt_force = 0;
   21 int opt_verbose = 1;        /* now "verbose" option is default */
   22 int opt_nowrite = 0;
   23 int opt_safe = 0;
   24 
   25 char *g_progname;
   26 
   27 /* calculate the new fs size (in blocks) from old fs size and the string
   28    representation of new size */
   29 static long long int calc_new_fs_size(unsigned long count,
   30                       unsigned int bs, char *bytes_str)
   31 {
   32     long long int bytes;
   33     long long int blocks;
   34     char *end;
   35     int rel;
   36 
   37     end = bytes_str + strlen(bytes_str) - 1;
   38     rel = bytes_str[0] == '+' || bytes_str[0] == '-';
   39     bytes = strtoll(bytes_str, &bytes_str, 10);
   40 
   41     /* Some error occured while convertion or the specified
   42        string is not valid. */
   43     if (bytes == LONG_LONG_MIN || bytes == LONG_LONG_MAX ||
   44         (bytes_str != end && bytes_str != end + 1))
   45         return -EINVAL;
   46 
   47     switch (*end) {
   48     case 'G':
   49     case 'g':
   50         bytes *= 1024;
   51     case 'M':
   52     case 'm':
   53         bytes *= 1024;
   54     case 'K':
   55     case 'k':
   56         bytes *= 1024;
   57     }
   58 
   59     blocks = bytes / bs;
   60 
   61     return rel ? count + blocks : blocks;
   62 }
   63 
   64 /* print some fs parameters */
   65 static void sb_report(struct reiserfs_super_block *sb1,
   66               struct reiserfs_super_block *sb2)
   67 {
   68     printf("ReiserFS report:\n"
   69            "blocksize             %u\n"
   70            "block count           %u (%u)\n"
   71            "free blocks           %u (%u)\n"
   72            "bitmap block count    %u (%u)\n",
   73            get_sb_block_size(sb1),
   74            get_sb_block_count(sb1), get_sb_block_count(sb2),
   75            get_sb_free_blocks(sb1), get_sb_free_blocks(sb2),
   76            get_sb_bmap_nr(sb1), get_sb_bmap_nr(sb2));
   77 };
   78 
   79 /* conditional bwrite */
   80 static int bwrite_cond(struct buffer_head *bh)
   81 {
   82     if (!opt_nowrite) {
   83         mark_buffer_uptodate(bh, 1);
   84         mark_buffer_dirty(bh);
   85         bwrite(bh);
   86     }
   87     return 0;
   88 }
   89 
   90 /* the first one of the most important functions */
   91 static int expand_fs(reiserfs_filsys_t fs, long long int block_count_new)
   92 {
   93     unsigned int bmap_nr_new, bmap_nr_old;
   94     struct reiserfs_super_block *sb;
   95     unsigned int i;
   96 
   97     reiserfs_reopen(fs, O_RDWR);
   98     if (reiserfs_open_ondisk_bitmap(fs))
   99         reiserfs_exit(1, "cannot open ondisk bitmap");
  100 
  101     sb = fs->fs_ondisk_sb;
  102 
  103     set_sb_fs_state(fs->fs_ondisk_sb, FS_ERROR);
  104 
  105     bwrite_cond(fs->fs_super_bh);
  106 
  107     if (reiserfs_expand_bitmap(fs->fs_bitmap2, block_count_new))
  108         reiserfs_exit(1, "cannot expand bitmap\n");
  109 
  110     /* count bitmap blocks in new fs */
  111     bmap_nr_new = (block_count_new - 1) / (fs->fs_blocksize * 8) + 1;
  112     bmap_nr_old = reiserfs_fs_bmap_nr(fs);
  113 
  114     /* update super block buffer */
  115     set_sb_free_blocks(sb, get_sb_free_blocks(sb) +
  116                (block_count_new - get_sb_block_count(sb)) -
  117                (bmap_nr_new - bmap_nr_old));
  118     set_sb_block_count(sb, block_count_new);
  119 
  120     set_sb_bmap_nr(fs->fs_ondisk_sb,
  121                reiserfs_bmap_over(bmap_nr_new) ? 0 : bmap_nr_new);
  122 
  123     /* mark new bitmap blocks as used */
  124     for (i = bmap_nr_old; i < bmap_nr_new; i++)
  125         reiserfs_bitmap_set_bit(fs->fs_bitmap2,
  126                     i * fs->fs_blocksize * 8);
  127 
  128     /* normally, this is done by reiserfs_bitmap_set_bit, but if we
  129      ** haven't actually added any bitmap blocks, the bitmap won't be dirtied.
  130      **
  131      ** In memory, reiserfsprogs puts zeros for the bits past the end of
  132      ** the old filesystem.  But, on disk that bitmap is full of ones.
  133      ** we explicitly dirty the bitmap here to make sure the zeros get written
  134      ** to disk
  135      */
  136     fs->fs_bitmap2->bm_dirty = 1;
  137 
  138     return 0;
  139 }
  140 
  141 static int resizer_check_fs_size(reiserfs_filsys_t fs, long long int new_size)
  142 {
  143     if (new_size < 0) {
  144         reiserfs_warning(stderr, "\nresizer_reiserfs: the new size "
  145                  "value is wrong.\n\n");
  146         return new_size;
  147     }
  148 
  149     if (new_size == get_sb_block_count(fs->fs_ondisk_sb)) {
  150         reiserfs_warning(stderr, "%s already is of the needed size. "
  151                  "Nothing to be done\n\n", fs->fs_file_name);
  152         return 1;
  153     }
  154 
  155     if (new_size < get_sb_block_count(fs->fs_ondisk_sb)) {
  156         if (misc_device_mounted(fs->fs_file_name) > 0) {
  157             reiserfs_warning(stderr,
  158                      "Can't shrink filesystem on-line.\n\n");
  159             return 1;
  160         }
  161     }
  162 
  163     if (new_size >= get_sb_block_count(fs->fs_ondisk_sb)) {
  164         loff_t offset = (loff_t) new_size * fs->fs_blocksize - 1;
  165 
  166         if (!valid_offset(fs->fs_dev, offset)) {
  167             reiserfs_warning(stderr,
  168                      "%s is of %lu blocks size only with "
  169                      "reiserfs of %u blocks\nsize on it. You are "
  170                      "trying to expand reiserfs up to %lu blocks "
  171                      "size.\nYou probably forgot to expand your "
  172                      "partition size.\n\n",
  173                      fs->fs_file_name,
  174                      count_blocks(fs->fs_file_name,
  175                               fs->fs_blocksize),
  176                      get_sb_block_count(fs->fs_ondisk_sb),
  177                      new_size);
  178             return 1;
  179         }
  180     }
  181 
  182     return 0;
  183 }
  184 
  185 int main(int argc, char *argv[])
  186 {
  187     char *bytes_count_str = NULL;
  188     char *devname;
  189     char *jdevice_name = NULL;
  190     reiserfs_filsys_t fs;
  191     struct reiserfs_super_block *sb;
  192 
  193     int c;
  194     long error;
  195 
  196     struct reiserfs_super_block *sb_old;
  197 
  198     long long int block_count_new;
  199 
  200     g_progname = basename(argv[0]);
  201 
  202     if (argc < 2)
  203         print_usage_and_exit();
  204 
  205     while ((c = getopt(argc, argv, "fvcqks:j:V")) != EOF) {
  206         switch (c) {
  207         case 's':
  208             if (!optarg)
  209                 reiserfs_exit(1,
  210                           "Missing argument to -s option");
  211             bytes_count_str = optarg;
  212             break;
  213         case 'j':
  214             if (!optarg)
  215                 reiserfs_exit(1,
  216                           "Missing argument to -j option");
  217             jdevice_name = optarg;
  218         case 'f':
  219             opt_force = 1;
  220             break;
  221         case 'v':
  222             opt_verbose++;
  223             break;
  224         case 'n':
  225             /* no nowrite option at this moment */
  226             /* opt_nowrite = 1; */
  227             break;
  228         case 'c':
  229             opt_safe = 1;
  230             break;
  231         case 'q':
  232             opt_verbose = 0;
  233             break;
  234         case 'k':
  235             opt_skipj = 1;
  236             break;
  237         case 'V':
  238             opt_banner++;
  239             break;
  240         default:
  241             print_usage_and_exit();
  242         }
  243     }
  244 
  245     print_banner(g_progname);
  246 
  247     if (opt_banner)
  248         exit(0);
  249 
  250     devname = argv[optind];
  251 
  252     fs = reiserfs_open(devname, O_RDONLY, &error, NULL, 1);
  253     if (!fs) {
  254         if (error) {
  255             reiserfs_exit(1, "cannot open '%s': %s",
  256                       devname, error_message(error));
  257         } else {
  258             exit(1);
  259         }
  260     }
  261 
  262     if (reiserfs_open_journal(fs, jdevice_name, O_RDWR | O_LARGEFILE)) {
  263         reiserfs_exit(1, "Failed to open the journal device (%s).",
  264                   jdevice_name);
  265     }
  266 
  267     if (reiserfs_journal_params_check(fs)) {
  268         if (!opt_skipj) {
  269             reiserfs_exit(1,
  270                       "Wrong journal parameters detected on (%s)",
  271                       jdevice_name);
  272         } else {
  273             reiserfs_close_journal(fs);
  274         }
  275     }
  276 
  277     /* forced to continue without journal available/specified */
  278 
  279     if (no_reiserfs_found(fs)) {
  280         reiserfs_exit(1, "no reiserfs found on the device.");
  281     }
  282 
  283     if (!spread_bitmaps(fs)) {
  284         reiserfs_exit(1, "cannot resize reiserfs in old (not spread "
  285                   "bitmap) format.");
  286     }
  287 
  288     sb = fs->fs_ondisk_sb;
  289 
  290     /* If size change was specified by user, calculate it,
  291        otherwise take the whole device. */
  292     block_count_new = bytes_count_str ?
  293         calc_new_fs_size(get_sb_block_count(sb),
  294                  fs->fs_blocksize, bytes_count_str) :
  295         count_blocks(devname, fs->fs_blocksize);
  296 
  297     if (resizer_check_fs_size(fs, block_count_new))
  298         return 1;
  299 
  300     if (misc_device_mounted(devname) > 0) {
  301         reiserfs_close(fs);
  302         error = resize_fs_online(devname, block_count_new);
  303         reiserfs_warning(stderr,
  304                  "\n\nresize_reiserfs: On-line resizing %s.\n\n",
  305                  error ? "failed" : "finished successfully");
  306         return error;
  307     }
  308 
  309     if (!reiserfs_is_fs_consistent(fs)) {
  310         reiserfs_warning(stderr,
  311                  "\n\nresize_reiserfs: run reiserfsck --check "
  312                  "first\n\n");
  313         reiserfs_close(fs);
  314         return 1;
  315     }
  316 
  317     if (get_sb_umount_state(sb) != FS_CLEANLY_UMOUNTED)
  318         /* fixme: shouldn't we check for something like: fsck guarantees: fs is ok */
  319         reiserfs_exit(1, "the file system isn't in valid state.");
  320 
  321     /* Needed to keep idiot compiler from issuing false warning */
  322     sb_old = NULL;
  323 
  324     /* save SB for reporting */
  325     if (opt_verbose) {
  326         sb_old = getmem(SB_SIZE);
  327         memcpy(sb_old, fs->fs_ondisk_sb, SB_SIZE);
  328     }
  329 
  330     error = (block_count_new > get_sb_block_count(fs->fs_ondisk_sb)) ?
  331         expand_fs(fs, block_count_new) : shrink_fs(fs, block_count_new);
  332     if (error) {
  333         reiserfs_warning(stderr,
  334                  "\n\nresize_reiserfs: Resizing failed.\n\n ");
  335         return error;
  336     }
  337 
  338     if (opt_verbose) {
  339         sb_report(fs->fs_ondisk_sb, sb_old);
  340         freemem(sb_old);
  341     }
  342 
  343     set_sb_fs_state(fs->fs_ondisk_sb, FS_CONSISTENT);
  344     bwrite_cond(fs->fs_super_bh);
  345 
  346     if (opt_verbose) {
  347         printf("\nSyncing..");
  348         fflush(stdout);
  349     }
  350     reiserfs_close(fs);
  351     if (opt_verbose)
  352         printf("done\n");
  353 
  354     reiserfs_warning(stderr, "\n\nresize_reiserfs: Resizing finished "
  355              "successfully.\n\n ");
  356 
  357     return 0;
  358 }