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 */
|