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