LCOV - code coverage report
Current view: top level - mkfs - main_jadd.c (source / functions) Hit Total Coverage
Test: gfs2-utils.info Lines: 0 369 0.0 %
Date: 2023-09-27 13:48:55 Functions: 0 17 0.0 %

          Line data    Source code
       1             : #include "clusterautoconfig.h"
       2             : 
       3             : #include <stdio.h>
       4             : #include <stdlib.h>
       5             : #include <string.h>
       6             : #include <stdint.h>
       7             : #include <inttypes.h>
       8             : #include <sys/types.h>
       9             : #include <dirent.h>
      10             : #include <sys/stat.h>
      11             : #include <sys/ioctl.h>
      12             : #include <sys/vfs.h>
      13             : #include <sys/mount.h>
      14             : #include <fcntl.h>
      15             : #include <unistd.h>
      16             : #include <time.h>
      17             : #include <errno.h>
      18             : #include <stdarg.h>
      19             : #include <libintl.h>
      20             : #include <locale.h>
      21             : #define _(String) gettext(String)
      22             : 
      23             : #include <linux/fiemap.h>
      24             : #include "libgfs2.h"
      25             : #include "gfs2_mkfs.h"
      26             : #include "metafs.h"
      27             : 
      28             : struct jadd_opts {
      29             :         char *path;
      30             :         char *new_inode;
      31             :         char *per_node;
      32             :         char *jindex;
      33             :         unsigned orig_journals;
      34             :         unsigned journals;
      35             :         unsigned quiet:1;
      36             :         unsigned debug:1;
      37             : };
      38             : 
      39             : #define JA_FL_SET   0
      40             : #define JA_FL_CLEAR 1
      41           0 : static int set_flags(int fd, int op, uint32_t flags)
      42             : {
      43             :         uint32_t val;
      44             : 
      45           0 :         if (ioctl(fd, FS_IOC_GETFLAGS, &val)) {
      46           0 :                 perror("GETFLAGS");
      47           0 :                 return -1;
      48             :         }
      49             : 
      50           0 :         if (op == JA_FL_SET)
      51           0 :                 val |= flags;
      52           0 :         else if (op == JA_FL_CLEAR)
      53           0 :                 val &= ~flags;
      54             : 
      55           0 :         if (ioctl(fd, FS_IOC_SETFLAGS, &val)) {
      56           0 :                 perror("SETFLAGS");
      57           0 :                 return -1;
      58             :         }
      59           0 :         return 0;
      60             : }
      61             : 
      62           0 : static int rename2system(struct jadd_opts *opts, const char *new_dir, const char *new_name)
      63             : {
      64             :         char *newpath;
      65             :         int ret;
      66             : 
      67           0 :         if (asprintf(&newpath, "%s/%s", new_dir, new_name) < 0) {
      68           0 :                 perror(_("Failed to allocate new path"));
      69           0 :                 return -1;
      70             :         }
      71             : 
      72           0 :         ret = rename(opts->new_inode, newpath);
      73           0 :         free(newpath);
      74           0 :         return ret;
      75             : }
      76             : 
      77           0 : static int build_paths(const char *metafs_path, struct jadd_opts *opts)
      78             : {
      79           0 :         int i = 0;
      80             :         struct {
      81             :                 char **path;
      82             :                 const char *tail;
      83           0 :         } p[] = {
      84           0 :                 { &opts->new_inode, "new_inode" },
      85           0 :                 { &opts->per_node, "per_node" },
      86           0 :                 { &opts->jindex, "jindex" },
      87             :                 { NULL, NULL}
      88             :         };
      89             : 
      90           0 :         while (p[i].path != NULL) {
      91           0 :                 if (asprintf(p[i].path, "%s/%s", metafs_path, p[i].tail) < 0) {
      92           0 :                         while (i > 0)
      93           0 :                                 free(*p[--i].path);
      94           0 :                         return 1;
      95             :                 }
      96           0 :                 if (opts->debug)
      97           0 :                         printf("%d: %s\n", i, *p[i].path);
      98           0 :                 i++;
      99             :         }
     100           0 :         return 0;
     101             : }
     102             : 
     103             : /**
     104             :  * print_usage - print out usage information
     105             :  * @prog_name: The name of this program
     106             :  */
     107             : 
     108           0 : static void print_usage(const char *prog_name)
     109             : {
     110             :         int i;
     111             :         const char *option, *param, *desc;
     112           0 :         const char *options[] = {
     113             :                 /* Translators: This is a usage string printed with --help.
     114             :                    <size> and <number> here are the commandline parameters,
     115             :                    e.g. gfs2_jadd -j <number> /dev/sda */
     116           0 :                 "-c", "<size>",   _("Size of quota change file, in megabytes"),
     117           0 :                 "-D", NULL,       _("Enable debugging code"),
     118           0 :                 "-h", NULL,       _("Display this help, then exit"),
     119           0 :                 "-J", "<size>",   _("Size of journals, in megabytes"),
     120           0 :                 "-j", "<number>", _("Number of journals"),
     121           0 :                 "-q", NULL,       _("Don't print anything"),
     122           0 :                 "-V", NULL,       _("Display version information, then exit"),
     123             :                 NULL, NULL, NULL /* Must be kept at the end */
     124             :         };
     125             : 
     126           0 :         printf("%s\n", _("Usage:"));
     127           0 :         printf("%s [%s] <%s>\n\n", prog_name, _("options"), _("device"));
     128           0 :         printf(_("Adds journals to a GFS2 file system."));
     129           0 :         printf("\n\n%s\n", _("Options:"));
     130             : 
     131           0 :         for (i = 0; options[i] != NULL; i += 3) {
     132           0 :                 option = options[i];
     133           0 :                 param = options[i+1];
     134           0 :                 desc = options[i+2];
     135           0 :                 printf("%3s %-15s %s\n", option, param ? param : "", desc);
     136             :         }
     137           0 : }
     138             : 
     139             : /**
     140             :  * Decode command line arguments and fill in the struct lgfs2_sbd
     141             :  * @argc:
     142             :  * @argv:
     143             :  * @sdp: the decoded command line arguments
     144             :  */
     145           0 : static int decode_arguments(int argc, char *argv[], struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     146             : {
     147           0 :         int cont = 1;
     148             :         int optchar;
     149             : 
     150           0 :         while (cont) {
     151           0 :                 optchar = getopt(argc, argv, "c:DhJ:j:qu:V");
     152             : 
     153           0 :                 switch (optchar) {
     154           0 :                 case 'c':
     155           0 :                         sdp->qcsize = atoi(optarg);
     156           0 :                         break;
     157           0 :                 case 'D':
     158           0 :                         opts->debug = 1;
     159           0 :                         break;
     160           0 :                 case 'h':
     161           0 :                         print_usage(argv[0]);
     162           0 :                         return 1;
     163           0 :                 case 'J':
     164           0 :                         sdp->jsize = atoi(optarg);
     165           0 :                         break;
     166           0 :                 case 'j':
     167           0 :                         opts->journals = atoi(optarg);
     168           0 :                         break;
     169           0 :                 case 'q':
     170           0 :                         opts->quiet = 1;
     171           0 :                         break;
     172           0 :                 case 'V':
     173           0 :                         printf("gfs2_jadd %s (built %s %s)\n", VERSION,
     174             :                                __DATE__, __TIME__);
     175           0 :                         printf(REDHAT_COPYRIGHT "\n");
     176           0 :                         return 1;
     177           0 :                 case ':':
     178             :                 case '?':
     179           0 :                         fprintf(stderr, _("Please use '-h' for help.\n"));
     180           0 :                         return -1;
     181           0 :                 case EOF:
     182           0 :                         cont = 0;
     183           0 :                         break;
     184           0 :                 default:
     185           0 :                         fprintf(stderr, _("Invalid option: %c\n"), optchar);
     186           0 :                         return -1;
     187             :                 };
     188             :         }
     189             : 
     190           0 :         if (optind < argc) {
     191           0 :                 opts->path = argv[optind];
     192           0 :                 optind++;
     193             :         } else {
     194           0 :                 fprintf(stderr, _("no path specified (try -h for help)\n"));
     195           0 :                 return -1;
     196             :         }
     197           0 :         if (optind < argc) {
     198           0 :                 fprintf(stderr, _("Unrecognized argument: %s\n"), argv[optind]);
     199           0 :                 return -1;
     200             :         }
     201           0 :         if (opts->debug) {
     202           0 :                 printf( _("Command line arguments:\n"));
     203           0 :                 printf("  qcsize = %u\n", sdp->qcsize);
     204           0 :                 printf("  jsize = %u\n", sdp->jsize);
     205           0 :                 printf("  journals = %u\n", sdp->md.journals);
     206           0 :                 printf("  quiet = %u\n", opts->quiet);
     207           0 :                 printf("  path = %s\n", opts->path);
     208             :         }
     209           0 :         return 0;
     210             : }
     211             : 
     212           0 : static int verify_arguments(struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     213             : {
     214           0 :         if (!opts->journals) {
     215           0 :                 fprintf(stderr, _("no journals specified\n"));
     216           0 :                 return -1;
     217             :         }
     218           0 :         if (sdp->jsize < 32 || sdp->jsize > 1024) {
     219           0 :                 fprintf(stderr, _("bad journal size\n"));
     220           0 :                 return -1;
     221             :         }
     222           0 :         if (!sdp->qcsize || sdp->qcsize > 64) {
     223           0 :                 fprintf(stderr, _("bad quota change size\n"));
     224           0 :                 return -1;
     225             :         }
     226           0 :         return 0;
     227             : }
     228             : 
     229           0 : static void print_results(struct jadd_opts *opts)
     230             : {
     231           0 :         if (opts->debug)
     232           0 :                 printf("\n");
     233           0 :         else if (opts->quiet)
     234           0 :                 return;
     235             : 
     236           0 :         printf( _("Filesystem: %s\n"), opts->path);
     237           0 :         printf( _("Old journals: %u\n"), opts->orig_journals);
     238           0 :         printf( _("New journals: %u\n"), opts->journals);
     239             : }
     240             : 
     241           0 : static int create_new_inode(struct jadd_opts *opts, uint64_t *addr)
     242             : {
     243           0 :         char *name = opts->new_inode;
     244             :         int fd;
     245             : 
     246             :         for (;;) {
     247           0 :                 fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
     248           0 :                 if (fd >= 0)
     249           0 :                         break;
     250           0 :                 if (errno == EEXIST) {
     251           0 :                         if (unlink(name)) {
     252           0 :                                 perror("unlink");
     253           0 :                                 return -1;
     254             :                         }
     255           0 :                         continue;
     256             :                 }
     257           0 :                 perror("create");
     258           0 :                 return -1;
     259             :         }
     260             : 
     261           0 :         if (addr != NULL) {
     262             :                 struct stat st;
     263             : 
     264           0 :                 if (fstat(fd, &st) == -1) {
     265           0 :                         perror("fstat");
     266           0 :                         close(fd);
     267           0 :                         return -1;
     268             :                 }
     269           0 :                 *addr = st.st_ino;
     270             :         }
     271             : 
     272           0 :         return fd;
     273             : }
     274             : 
     275           0 : static int add_ir(struct jadd_opts *opts)
     276             : {
     277           0 :         int fd, error = 0;
     278             :         char new_name[256];
     279             :         struct gfs2_inum_range ir;
     280             : 
     281           0 :         if ((fd = create_new_inode(opts, NULL)) < 0)
     282           0 :                 return fd;
     283             : 
     284           0 :         if ((error = set_flags(fd, JA_FL_SET, FS_JOURNAL_DATA_FL)))
     285           0 :                 goto close_fd;
     286             : 
     287           0 :         memset(&ir, 0, sizeof(struct gfs2_inum_range));
     288           0 :         if (write(fd, (void*)&ir, sizeof(struct gfs2_inum_range)) !=
     289             :             sizeof(struct gfs2_inum_range)) {
     290           0 :                 perror("add_ir write");
     291           0 :                 error = -1;
     292           0 :                 goto close_fd;
     293             :         }
     294             : 
     295           0 :         if ((error = fsync(fd))) {
     296           0 :                 perror("add_ir fsync");
     297           0 :                 goto close_fd;
     298             :         }
     299             : 
     300             : 
     301           0 :         sprintf(new_name, "inum_range%u", opts->journals);
     302           0 :         error = rename2system(opts, opts->per_node, new_name);
     303           0 :         if (error < 0 && errno != EEXIST) {
     304           0 :                 perror("add_ir rename2system");
     305           0 :                 goto close_fd;
     306             :         }
     307           0 : close_fd:
     308           0 :         return close(fd) || error;
     309             : }
     310             : 
     311           0 : static int add_sc(struct jadd_opts *opts)
     312             : {
     313           0 :         int fd, error = 0;
     314             :         char new_name[256];
     315             :         struct gfs2_statfs_change sc;
     316             : 
     317           0 :         if ((fd = create_new_inode(opts, NULL)) < 0)
     318           0 :                 return fd;
     319             : 
     320           0 :         if ((error = set_flags(fd, JA_FL_SET, FS_JOURNAL_DATA_FL)))
     321           0 :                 goto close_fd;
     322             : 
     323           0 :         memset(&sc, 0, sizeof(struct gfs2_statfs_change));
     324           0 :         if (write(fd, (void*)&sc, sizeof(struct gfs2_statfs_change)) !=
     325             :             sizeof(struct gfs2_statfs_change)) {
     326           0 :                 perror("add_sc write");
     327           0 :                 error = -1;
     328           0 :                 goto close_fd;
     329             :         }
     330             : 
     331           0 :         if ((error = fsync(fd))) {
     332           0 :                 perror("add_sc fsync");
     333           0 :                 goto close_fd;
     334             :         }
     335             : 
     336           0 :         sprintf(new_name, "statfs_change%u", opts->journals);
     337           0 :         error = rename2system(opts, opts->per_node, new_name);
     338           0 :         if (error < 0 && errno != EEXIST){
     339           0 :                 perror("add_sc rename2system");
     340           0 :                 goto close_fd;
     341             :         }
     342           0 : close_fd:
     343           0 :         return close(fd) || error;
     344             : }
     345             : 
     346           0 : static int add_qc(struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     347             : {
     348           0 :         int fd, error = 0;
     349             :         char new_name[256], *buf;
     350           0 :         unsigned int blocks =
     351           0 :                 sdp->qcsize << (20 - sdp->sd_bsize_shift);
     352             :         unsigned int x;
     353             :         struct gfs2_meta_header mh;
     354             : 
     355           0 :         buf = calloc(1, sdp->sd_bsize);
     356           0 :         if (buf == NULL)
     357           0 :                 return -1;
     358             : 
     359           0 :         if ((fd = create_new_inode(opts, NULL)) < 0) {
     360           0 :                 free(buf);
     361           0 :                 return fd;
     362             :         }
     363           0 :         if ((error = set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL)))
     364           0 :                 goto close_fd;
     365             : 
     366           0 :         memset(buf, 0, sdp->sd_bsize);
     367           0 :         for (x=0; x<blocks; x++) {
     368           0 :                 if (write(fd, buf, sdp->sd_bsize) != sdp->sd_bsize) {
     369           0 :                         perror("add_qc write");
     370           0 :                         error = -1;
     371           0 :                         goto close_fd;
     372             :                 }
     373             :         }
     374             : 
     375           0 :         if ((error = lseek(fd, 0, SEEK_SET)) < 0) {
     376           0 :                 perror("add_qc lseek");
     377           0 :                 goto close_fd;
     378             :         }
     379             : 
     380           0 :         memset(&mh, 0, sizeof(struct gfs2_meta_header));
     381           0 :         mh.mh_magic = cpu_to_be32(GFS2_MAGIC);
     382           0 :         mh.mh_type = cpu_to_be32(GFS2_METATYPE_QC);
     383           0 :         mh.mh_format = cpu_to_be32(GFS2_FORMAT_QC);
     384           0 :         memcpy(buf, &mh, sizeof(mh));
     385             : 
     386           0 :         for (x=0; x<blocks; x++) {
     387           0 :                 if (write(fd, buf, sdp->sd_bsize) != sdp->sd_bsize) {
     388           0 :                         perror("add_qc write");
     389           0 :                         error = 1;
     390           0 :                         goto close_fd;
     391             :                 }
     392           0 :                 if ((error = fsync(fd))) {
     393           0 :                         perror("add_qc fsync");
     394           0 :                         goto close_fd;
     395             :                 }
     396             :         }
     397             : 
     398           0 :         sprintf(new_name, "quota_change%u", opts->journals);
     399           0 :         error = rename2system(opts, opts->per_node, new_name);
     400           0 :         if (error < 0 && errno != EEXIST){
     401           0 :                 perror("add_qc rename2system");
     402           0 :                 goto close_fd;
     403             :         }
     404           0 : close_fd:
     405           0 :         free(buf);
     406           0 :         return close(fd) || error;
     407             : }
     408             : 
     409           0 : static int gather_info(struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     410             : {
     411             :         struct statfs statbuf;
     412             : 
     413           0 :         if (statfs(opts->path, &statbuf) < 0) {
     414           0 :                 perror(opts->path);
     415           0 :                 return -1;
     416             :         }
     417             : 
     418           0 :         sdp->sd_bsize = statbuf.f_bsize;
     419           0 :         sdp->blks_total = statbuf.f_blocks;
     420           0 :         sdp->blks_alloced = sdp->blks_total - statbuf.f_bfree;
     421             : 
     422           0 :         return 0;
     423             : }
     424             : 
     425           0 : static int find_current_journals(struct jadd_opts *opts)
     426             : {
     427             :         struct dirent *dp;
     428             :         DIR *dirp;
     429           0 :         unsigned existing_journals = 0;
     430           0 :         int ret = 0;
     431             : 
     432           0 :         dirp = opendir(opts->jindex);
     433           0 :         if (!dirp) {
     434           0 :                 perror("jindex");
     435           0 :                 ret = -1;
     436           0 :                 goto out;
     437             :         }
     438           0 :         while (dirp) {
     439           0 :                 if ((dp = readdir(dirp)) != NULL) {
     440           0 :                         if (strncmp(dp->d_name, "journal", 7) == 0)
     441           0 :                                 existing_journals++;
     442             :                 } else
     443           0 :                         goto close_fd;
     444             :         }
     445           0 : close_fd:
     446           0 :         if ((ret = closedir(dirp)))
     447           0 :                 goto out;
     448             : 
     449           0 :         if (existing_journals == 0) {
     450           0 :                 errno = EINVAL;
     451           0 :                 perror("No journals found. Did you run mkfs.gfs2 correctly?\n");
     452           0 :                 ret = -1;
     453           0 :                 goto out;
     454             :         }
     455             : 
     456           0 :         opts->orig_journals = existing_journals;
     457           0 : out:
     458           0 :         return ret;
     459             : }
     460             : 
     461           0 : static uint64_t find_block_address(int fd, off_t offset, unsigned bsize)
     462             : {
     463             :         struct {
     464             :                 struct fiemap fm;
     465             :                 struct fiemap_extent fe;
     466           0 :         } fme = {0};
     467             :         int ret;
     468             : 
     469           0 :         fme.fm.fm_start = offset;
     470           0 :         fme.fm.fm_length = 1;
     471           0 :         fme.fm.fm_flags = FIEMAP_FLAG_SYNC;
     472           0 :         fme.fm.fm_extent_count = 1;
     473             : 
     474           0 :         ret = ioctl(fd, FS_IOC_FIEMAP, &fme.fm);
     475           0 :         if (ret != 0 || fme.fm.fm_mapped_extents != 1) {
     476           0 :                 fprintf(stderr, "Failed to find log header block address\n");
     477           0 :                 return 0;
     478             :         }
     479           0 :         return fme.fe.fe_physical / bsize;
     480             : }
     481             : 
     482           0 : static int alloc_new_journal(int fd, unsigned bytes)
     483             : {
     484             : #define ALLOC_BUF_SIZE (4 << 20)
     485           0 :         unsigned left = bytes;
     486             :         int error;
     487             :         char *buf;
     488             : 
     489           0 :         error = fallocate(fd, 0, 0, bytes);
     490           0 :         if (error == 0)
     491           0 :                return 0;
     492           0 :         if (errno != EOPNOTSUPP)
     493           0 :                 goto out_errno;
     494             : 
     495             :         /* No fallocate support, fall back to writes */
     496           0 :         buf = calloc(1, ALLOC_BUF_SIZE);
     497           0 :         if (buf == NULL)
     498           0 :                 goto out_errno;
     499             : 
     500           0 :         while (left > 0) {
     501           0 :                 unsigned sz = ALLOC_BUF_SIZE;
     502             : 
     503           0 :                 if (left < ALLOC_BUF_SIZE)
     504           0 :                         sz = left;
     505             : 
     506           0 :                 if (pwrite(fd, buf, sz, bytes - left) != sz) {
     507           0 :                         free(buf);
     508           0 :                         goto out_errno;
     509             :                 }
     510           0 :                 left -= sz;
     511             :         }
     512           0 :         free(buf);
     513           0 :         return 0;
     514           0 : out_errno:
     515           0 :         perror("Failed to allocate space for new journal");
     516           0 :         return -1;
     517             : }
     518             : 
     519           0 : static int add_j(struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     520             : {
     521           0 :         int fd, error = 0;
     522             :         char new_name[256], *buf;
     523           0 :         uint32_t x, blocks = sdp->jsize << (20 - sdp->sd_bsize_shift);
     524             :         struct gfs2_log_header *lh;
     525             :         /* Not a security sensitive use of random() */
     526             :         /* coverity[dont_call:SUPPRESS] */
     527           0 :         uint64_t seq = blocks * (random() / (RAND_MAX + 1.0));
     528           0 :         uint64_t addr = 0;
     529           0 :         off_t off = 0;
     530             : 
     531           0 :         buf = calloc(1, sdp->sd_bsize);
     532           0 :         if (buf == NULL)
     533           0 :                 return -1;
     534             : 
     535           0 :         if ((fd = create_new_inode(opts, &addr)) < 0) {
     536           0 :                 free(buf);
     537           0 :                 return fd;
     538             :         }
     539           0 :         if ((error = set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL)))
     540           0 :                 goto close_fd;
     541             : 
     542           0 :         error = alloc_new_journal(fd, sdp->jsize << 20);
     543           0 :         if (error != 0)
     544           0 :                 goto close_fd;
     545             : 
     546           0 :         error = fsync(fd);
     547           0 :         if (error != 0) {
     548           0 :                 perror("Failed to sync journal metadata");
     549           0 :                 goto close_fd;
     550             :         }
     551           0 :         if ((error = lseek(fd, 0, SEEK_SET)) < 0) {
     552           0 :                 perror("add_j lseek");
     553           0 :                 goto close_fd;
     554             :         }
     555             : 
     556           0 :         lh = (void *)buf;
     557           0 :         lh->lh_header.mh_magic = cpu_to_be32(GFS2_MAGIC);
     558           0 :         lh->lh_header.mh_type = cpu_to_be32(GFS2_METATYPE_LH);
     559           0 :         lh->lh_header.mh_format = cpu_to_be32(GFS2_FORMAT_LH);
     560           0 :         lh->lh_flags = cpu_to_be32(GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_USERSPACE);
     561           0 :         lh->lh_jinode = cpu_to_be64(addr);
     562             : 
     563           0 :         for (x=0; x<blocks; x++) {
     564             :                 uint32_t hash;
     565           0 :                 uint64_t blk_addr = 0;
     566           0 :                 lh->lh_sequence = cpu_to_be64(seq);
     567           0 :                 lh->lh_blkno = cpu_to_be32(x);
     568           0 :                 hash = lgfs2_log_header_hash(buf);
     569           0 :                 lh->lh_hash = cpu_to_be32(hash);
     570           0 :                 if (!(blk_addr = find_block_address(fd, off, sdp->sd_bsize))) {
     571           0 :                         error = -1;
     572           0 :                         goto close_fd;
     573             :                 }
     574           0 :                 lh->lh_addr = cpu_to_be64(blk_addr);
     575           0 :                 hash = lgfs2_log_header_crc(buf, sdp->sd_bsize);
     576           0 :                 lh->lh_crc = cpu_to_be32(hash);
     577           0 :                 if (write(fd, buf, sdp->sd_bsize) != sdp->sd_bsize) {
     578           0 :                         perror("add_j write");
     579           0 :                         error = -1;
     580           0 :                         goto close_fd;
     581             :                 }
     582           0 :                 lh->lh_crc = 0;
     583           0 :                 lh->lh_hash = 0;
     584             : 
     585           0 :                 if (++seq == blocks)
     586           0 :                         seq = 0;
     587           0 :                 off += sdp->sd_bsize;
     588             : 
     589             :         }
     590           0 :         error = fsync(fd);
     591           0 :         if (error != 0) {
     592           0 :                 perror("Failed to sync journal metadata");
     593           0 :                 goto close_fd;
     594             :         }
     595           0 :         sprintf(new_name, "journal%u", opts->journals);
     596           0 :         error = rename2system(opts, opts->jindex, new_name);
     597           0 :         if (error < 0 && errno != EEXIST){
     598           0 :                 perror("add_j rename2system");
     599           0 :                 goto close_fd;
     600             :         }
     601           0 : close_fd:
     602           0 :         free(buf);
     603           0 :         return close(fd) || error;
     604             : }
     605             : 
     606           0 : static int check_fit(struct lgfs2_sbd *sdp, struct jadd_opts *opts)
     607             : {
     608             :         /* Compute how much space we'll need for the new journals
     609             :          * Number of blocks needed per added journal:
     610             :          * 1 block for the ir inode
     611             :          * 1 block for the sc inode
     612             :          * for sizes of the qc and journal inodes, use lgfs2_space_for_data()
     613             :          * to calculate.
     614             :          */
     615             :         uint64_t blks_per_j, total_blks;
     616             : 
     617           0 :         blks_per_j = 1 + 1 +
     618           0 :                 lgfs2_space_for_data(sdp, sdp->sd_bsize, sdp->qcsize << 20) +
     619           0 :                 lgfs2_space_for_data(sdp, sdp->sd_bsize, sdp->jsize << 20);
     620           0 :         total_blks = opts->journals * blks_per_j;
     621             : 
     622           0 :         if (total_blks > (sdp->blks_total - sdp->blks_alloced)) {
     623           0 :                 printf( _("\nInsufficient space on the device to add %u %uMB "
     624             :                           "journals (%uMB QC size)\n\n"),
     625             :                         opts->journals, sdp->jsize, sdp->qcsize);
     626           0 :                 printf( _("Required space  : %*"PRIu64" blocks (%"PRIu64" blocks per "
     627             :                           "journal)\n"), 10, total_blks, blks_per_j);
     628           0 :                 printf( _("Available space : %*"PRIu64" blocks\n\n"), 10,
     629           0 :                         sdp->blks_total - sdp->blks_alloced);
     630           0 :                 errno = ENOSPC;
     631           0 :                 return -1;
     632             :         }
     633           0 :         return 0;
     634             : }
     635             : 
     636             : #ifndef UNITTESTS
     637             : int main(int argc, char *argv[])
     638             : {
     639             :         struct jadd_opts opts = {0};
     640             :         struct lgfs2_sbd sbd, *sdp = &sbd;
     641             :         struct metafs mfs = {0};
     642             :         struct mntent *mnt;
     643             :         unsigned int total, ret = 0;
     644             : 
     645             :         setlocale(LC_ALL, "");
     646             :         textdomain("gfs2-utils");
     647             :         srandom(time(NULL) ^ getpid());
     648             : 
     649             :         memset(sdp, 0, sizeof(struct lgfs2_sbd));
     650             :         sdp->jsize = LGFS2_DEFAULT_JSIZE;
     651             :         sdp->qcsize = LGFS2_DEFAULT_QCSIZE;
     652             :         opts.journals = 1;
     653             : 
     654             :         ret = decode_arguments(argc, argv, sdp, &opts);
     655             :         if (ret == 1)
     656             :                 exit(0);
     657             :         if (ret != 0)
     658             :                 exit(1);
     659             :         if (verify_arguments(sdp, &opts) != 0)
     660             :                 exit(1);
     661             : 
     662             :         sbd.path_fd = lgfs2_open_mnt_dir(opts.path, O_RDONLY|O_CLOEXEC, &mnt);
     663             :         if (sbd.path_fd < 0) {
     664             :                 fprintf(stderr, "Error looking up mount '%s': %s\n",
     665             :                         opts.path, strerror(errno));
     666             :                 ret = -1;
     667             :                 goto out;
     668             :         }
     669             :         if (mnt == NULL) {
     670             :                 fprintf(stderr, "%s: not a mounted gfs2 file system\n", opts.path);
     671             :                 ret = -1;
     672             :                 goto close_sb;
     673             :         }
     674             : 
     675             :         if ((ret = gather_info(sdp, &opts)))
     676             :                 goto close_sb;
     677             : 
     678             :         mfs.context = copy_context_opt(mnt);
     679             :         if ((ret = mount_gfs2_meta(&mfs, mnt->mnt_dir, opts.debug))) {
     680             :                 perror("GFS2 metafs");
     681             :                 goto close_sb;
     682             :         }
     683             : 
     684             :         if ((ret = build_paths(mfs.path, &opts))) {
     685             :                 perror(_("Failed to build paths"));
     686             :                 goto umount_meta;
     687             :         }
     688             : 
     689             :         if ((ret = lgfs2_compute_constants(sdp))) {
     690             :                 perror(_("Failed to compute file system constants"));
     691             :                 goto free_paths;
     692             :         }
     693             : 
     694             :         if ((ret = find_current_journals(&opts)))
     695             :                 goto free_paths;
     696             : 
     697             :         if ((ret = check_fit(sdp, &opts))) {
     698             :                 perror(_("Failed to add journals"));
     699             :                 goto free_paths;
     700             :         }
     701             : 
     702             :         total = opts.orig_journals + opts.journals;
     703             :         for (opts.journals = opts.orig_journals;
     704             :              opts.journals < total;
     705             :              opts.journals++) {
     706             :                 if (metafs_interrupted) {
     707             :                         errno = 130;
     708             :                         goto free_paths;
     709             :                 }
     710             :                 if ((ret = add_ir(&opts)))
     711             :                         goto free_paths;
     712             :                 if ((ret = add_sc(&opts)))
     713             :                         goto free_paths;
     714             :                 if ((ret = add_qc(sdp, &opts)))
     715             :                         goto free_paths;
     716             :                 if ((ret = add_j(sdp, &opts)))
     717             :                         goto free_paths;
     718             :         }
     719             : 
     720             : free_paths:
     721             :         free(opts.new_inode);
     722             :         free(opts.per_node);
     723             :         free(opts.jindex);
     724             : umount_meta:
     725             :         sync();
     726             :         cleanup_metafs(&mfs);
     727             : close_sb:
     728             :         close(sdp->path_fd);
     729             : out:
     730             :         if (!ret)
     731             :                 print_results(&opts);
     732             : 
     733             :         return ret;
     734             : }
     735             : #endif /* UNITTESTS */

Generated by: LCOV version 1.14