|
Packit |
6ef888 |
#include "clusterautoconfig.h"
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
#include <stdio.h>
|
|
Packit |
6ef888 |
#include <stdlib.h>
|
|
Packit |
6ef888 |
#include <string.h>
|
|
Packit |
6ef888 |
#include <stdint.h>
|
|
Packit |
6ef888 |
#include <inttypes.h>
|
|
Packit |
6ef888 |
#include <sys/types.h>
|
|
Packit |
6ef888 |
#include <dirent.h>
|
|
Packit |
6ef888 |
#include <sys/stat.h>
|
|
Packit |
6ef888 |
#include <sys/ioctl.h>
|
|
Packit |
6ef888 |
#include <sys/vfs.h>
|
|
Packit |
6ef888 |
#include <sys/mount.h>
|
|
Packit |
6ef888 |
#include <fcntl.h>
|
|
Packit |
6ef888 |
#include <unistd.h>
|
|
Packit |
6ef888 |
#include <time.h>
|
|
Packit |
6ef888 |
#include <errno.h>
|
|
Packit |
6ef888 |
#include <stdarg.h>
|
|
Packit |
6ef888 |
#include <libintl.h>
|
|
Packit |
6ef888 |
#include <locale.h>
|
|
Packit |
6ef888 |
#define _(String) gettext(String)
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
#include <linux/types.h>
|
|
Packit |
6ef888 |
#include <linux/fiemap.h>
|
|
Packit |
6ef888 |
#include <linux/fs.h>
|
|
Packit |
6ef888 |
#include "libgfs2.h"
|
|
Packit |
6ef888 |
#include "gfs2_mkfs.h"
|
|
Packit |
6ef888 |
#include "metafs.h"
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
#define RANDOM(values) ((values) * (random() / (RAND_MAX + 1.0)))
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
struct jadd_opts {
|
|
Packit |
6ef888 |
char *path;
|
|
Packit |
6ef888 |
char *new_inode;
|
|
Packit |
6ef888 |
char *per_node;
|
|
Packit |
6ef888 |
char *jindex;
|
|
Packit |
6ef888 |
unsigned orig_journals;
|
|
Packit |
6ef888 |
unsigned journals;
|
|
Packit |
6ef888 |
unsigned quiet:1;
|
|
Packit |
6ef888 |
unsigned debug:1;
|
|
Packit |
6ef888 |
};
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
#define JA_FL_SET 0
|
|
Packit |
6ef888 |
#define JA_FL_CLEAR 1
|
|
Packit Service |
395ff1 |
static void set_flags(int fd, int op, uint32_t flags)
|
|
Packit |
6ef888 |
{
|
|
Packit Service |
395ff1 |
int err;
|
|
Packit |
6ef888 |
uint32_t val;
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
err = ioctl(fd, FS_IOC_GETFLAGS, &val;;
|
|
Packit Service |
395ff1 |
if (err) {
|
|
Packit |
6ef888 |
perror("GETFLAGS");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
if (op == JA_FL_SET)
|
|
Packit |
6ef888 |
val |= flags;
|
|
Packit |
6ef888 |
else if (op == JA_FL_CLEAR)
|
|
Packit |
6ef888 |
val &= ~flags;
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
err = ioctl(fd, FS_IOC_SETFLAGS, &val;;
|
|
Packit Service |
395ff1 |
if (err) {
|
|
Packit |
6ef888 |
perror("SETFLAGS");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static int rename2system(struct jadd_opts *opts, const char *new_dir, const char *new_name)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
char *newpath;
|
|
Packit |
6ef888 |
int ret;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
if (asprintf(&newpath, "%s/%s", new_dir, new_name) < 0) {
|
|
Packit |
6ef888 |
perror(_("Failed to allocate new path"));
|
|
Packit |
6ef888 |
return -1;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
ret = rename(opts->new_inode, newpath);
|
|
Packit |
6ef888 |
free(newpath);
|
|
Packit |
6ef888 |
return ret;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static int build_paths(const char *metafs_path, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
int i = 0;
|
|
Packit |
6ef888 |
struct {
|
|
Packit |
6ef888 |
char **path;
|
|
Packit |
6ef888 |
const char *tail;
|
|
Packit |
6ef888 |
} p[] = {
|
|
Packit |
6ef888 |
{ &opts->new_inode, "new_inode" },
|
|
Packit |
6ef888 |
{ &opts->per_node, "per_node" },
|
|
Packit |
6ef888 |
{ &opts->jindex, "jindex" },
|
|
Packit |
6ef888 |
{ NULL, NULL}
|
|
Packit |
6ef888 |
};
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
while (p[i].path != NULL) {
|
|
Packit |
6ef888 |
if (asprintf(p[i].path, "%s/%s", metafs_path, p[i].tail) < 0) {
|
|
Packit |
6ef888 |
while (i > 0)
|
|
Packit |
6ef888 |
free(*p[--i].path);
|
|
Packit |
6ef888 |
return 1;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
if (opts->debug)
|
|
Packit |
6ef888 |
printf("%d: %s\n", i, *p[i].path);
|
|
Packit |
6ef888 |
i++;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
return 0;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
/**
|
|
Packit |
6ef888 |
* print_usage - print out usage information
|
|
Packit |
6ef888 |
* @prog_name: The name of this program
|
|
Packit |
6ef888 |
*/
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static void print_usage(const char *prog_name)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
int i;
|
|
Packit |
6ef888 |
const char *option, *param, *desc;
|
|
Packit |
6ef888 |
const char *options[] = {
|
|
Packit |
6ef888 |
/* Translators: This is a usage string printed with --help.
|
|
Packit |
6ef888 |
<size> and <number> here are the commandline parameters,
|
|
Packit |
6ef888 |
e.g. gfs2_jadd -j <number> /dev/sda */
|
|
Packit |
6ef888 |
"-c", "<size>", _("Size of quota change file, in megabytes"),
|
|
Packit |
6ef888 |
"-D", NULL, _("Enable debugging code"),
|
|
Packit |
6ef888 |
"-h", NULL, _("Display this help, then exit"),
|
|
Packit |
6ef888 |
"-J", "<size>", _("Size of journals, in megabytes"),
|
|
Packit |
6ef888 |
"-j", "<number>", _("Number of journals"),
|
|
Packit |
6ef888 |
"-q", NULL, _("Don't print anything"),
|
|
Packit |
6ef888 |
"-V", NULL, _("Display version information, then exit"),
|
|
Packit |
6ef888 |
NULL, NULL, NULL /* Must be kept at the end */
|
|
Packit |
6ef888 |
};
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
printf("%s\n", _("Usage:"));
|
|
Packit |
6ef888 |
printf("%s [%s] <%s>\n\n", prog_name, _("options"), _("device"));
|
|
Packit |
6ef888 |
printf(_("Adds journals to a GFS2 file system."));
|
|
Packit |
6ef888 |
printf("\n\n%s\n", _("Options:"));
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
for (i = 0; options[i] != NULL; i += 3) {
|
|
Packit |
6ef888 |
option = options[i];
|
|
Packit |
6ef888 |
param = options[i+1];
|
|
Packit |
6ef888 |
desc = options[i+2];
|
|
Packit |
6ef888 |
printf("%3s %-15s %s\n", option, param ? param : "", desc);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
/**
|
|
Packit |
6ef888 |
* decode_arguments - decode command line arguments and fill in the struct gfs2_sbd
|
|
Packit |
6ef888 |
* @argc:
|
|
Packit |
6ef888 |
* @argv:
|
|
Packit |
6ef888 |
* @sdp: the decoded command line arguments
|
|
Packit |
6ef888 |
*
|
|
Packit |
6ef888 |
*/
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
int cont = TRUE;
|
|
Packit |
6ef888 |
int optchar;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
while (cont) {
|
|
Packit |
6ef888 |
optchar = getopt(argc, argv, "c:DhJ:j:qu:V");
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
switch (optchar) {
|
|
Packit |
6ef888 |
case 'c':
|
|
Packit |
6ef888 |
sdp->qcsize = atoi(optarg);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'D':
|
|
Packit |
6ef888 |
opts->debug = 1;
|
|
Packit |
6ef888 |
lgfs2_set_debug(1);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'h':
|
|
Packit |
6ef888 |
print_usage(argv[0]);
|
|
Packit |
6ef888 |
exit(0);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'J':
|
|
Packit |
6ef888 |
sdp->jsize = atoi(optarg);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'j':
|
|
Packit |
6ef888 |
opts->journals = atoi(optarg);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'q':
|
|
Packit |
6ef888 |
opts->quiet = 1;
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case 'V':
|
|
Packit |
6ef888 |
printf("gfs2_jadd %s (built %s %s)\n", VERSION,
|
|
Packit |
6ef888 |
__DATE__, __TIME__);
|
|
Packit |
6ef888 |
printf(REDHAT_COPYRIGHT "\n");
|
|
Packit |
6ef888 |
exit(0);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case ':':
|
|
Packit |
6ef888 |
case '?':
|
|
Packit |
6ef888 |
fprintf(stderr, _("Please use '-h' for help.\n"));
|
|
Packit |
6ef888 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
case EOF:
|
|
Packit |
6ef888 |
cont = FALSE;
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
default:
|
|
Packit |
6ef888 |
die( _("Invalid option: %c\n"), optchar);
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
};
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
if (optind < argc) {
|
|
Packit |
6ef888 |
opts->path = argv[optind];
|
|
Packit |
6ef888 |
optind++;
|
|
Packit |
6ef888 |
} else
|
|
Packit |
6ef888 |
die( _("no path specified (try -h for help)\n"));
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
if (optind < argc)
|
|
Packit |
6ef888 |
die( _("Unrecognized argument: %s\n"), argv[optind]);
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
if (opts->debug) {
|
|
Packit |
6ef888 |
printf( _("Command line arguments:\n"));
|
|
Packit |
6ef888 |
printf(" qcsize = %u\n", sdp->qcsize);
|
|
Packit |
6ef888 |
printf(" jsize = %u\n", sdp->jsize);
|
|
Packit |
6ef888 |
printf(" journals = %u\n", sdp->md.journals);
|
|
Packit |
6ef888 |
printf(" quiet = %u\n", opts->quiet);
|
|
Packit |
6ef888 |
printf(" path = %s\n", opts->path);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static void verify_arguments(struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
if (!opts->journals)
|
|
Packit |
6ef888 |
die( _("no journals specified\n"));
|
|
Packit |
6ef888 |
if (sdp->jsize < 32 || sdp->jsize > 1024)
|
|
Packit |
6ef888 |
die( _("bad journal size\n"));
|
|
Packit |
6ef888 |
if (!sdp->qcsize || sdp->qcsize > 64)
|
|
Packit |
6ef888 |
die( _("bad quota change size\n"));
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static void print_results(struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
if (opts->debug)
|
|
Packit |
6ef888 |
printf("\n");
|
|
Packit |
6ef888 |
else if (opts->quiet)
|
|
Packit |
6ef888 |
return;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
printf( _("Filesystem: %s\n"), opts->path);
|
|
Packit |
6ef888 |
printf( _("Old journals: %u\n"), opts->orig_journals);
|
|
Packit |
6ef888 |
printf( _("New journals: %u\n"), opts->journals);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
static int create_new_inode(struct jadd_opts *opts, uint64_t *addr)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
char *name = opts->new_inode;
|
|
Packit Service |
395ff1 |
int fd;
|
|
Packit Service |
395ff1 |
int error;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
for (;;) {
|
|
Packit |
6ef888 |
fd = open(name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC, 0600);
|
|
Packit |
6ef888 |
if (fd >= 0)
|
|
Packit |
6ef888 |
break;
|
|
Packit |
6ef888 |
if (errno == EEXIST) {
|
|
Packit Service |
395ff1 |
error = unlink(name);
|
|
Packit Service |
395ff1 |
if (error){
|
|
Packit |
6ef888 |
perror("unlink");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit Service |
395ff1 |
} else{
|
|
Packit Service |
395ff1 |
perror("create");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
if (addr != NULL) {
|
|
Packit |
6ef888 |
struct stat st;
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
fstat(fd, &st);
|
|
Packit |
6ef888 |
*addr = st.st_ino;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
return fd;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void add_ir(struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit Service |
395ff1 |
int fd;
|
|
Packit |
6ef888 |
char new_name[256];
|
|
Packit Service |
395ff1 |
int error;
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
fd = create_new_inode(opts, NULL);
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
{
|
|
Packit Service |
395ff1 |
struct gfs2_inum_range ir;
|
|
Packit |
03c5d0 |
|
|
Packit Service |
395ff1 |
set_flags(fd, JA_FL_SET, FS_JOURNAL_DATA_FL);
|
|
Packit Service |
395ff1 |
memset(&ir, 0, sizeof(struct gfs2_inum_range));
|
|
Packit Service |
395ff1 |
if (write(fd, (void*)&ir, sizeof(struct gfs2_inum_range)) !=
|
|
Packit Service |
395ff1 |
sizeof(struct gfs2_inum_range)) {
|
|
Packit Service |
395ff1 |
perror("add_ir");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
close(fd);
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
sprintf(new_name, "inum_range%u", opts->journals);
|
|
Packit |
6ef888 |
error = rename2system(opts, opts->per_node, new_name);
|
|
Packit Service |
395ff1 |
if (error < 0 && errno != EEXIST){
|
|
Packit |
6ef888 |
perror("add_ir rename2system");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void add_sc(struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit Service |
395ff1 |
int fd;
|
|
Packit |
6ef888 |
char new_name[256];
|
|
Packit Service |
395ff1 |
int error;
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
fd = create_new_inode(opts, NULL);
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
{
|
|
Packit Service |
395ff1 |
struct gfs2_statfs_change sc;
|
|
Packit Service |
395ff1 |
set_flags(fd, JA_FL_SET, FS_JOURNAL_DATA_FL);
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
memset(&sc, 0, sizeof(struct gfs2_statfs_change));
|
|
Packit Service |
395ff1 |
if (write(fd, (void*)&sc, sizeof(struct gfs2_statfs_change)) !=
|
|
Packit Service |
395ff1 |
sizeof(struct gfs2_statfs_change)) {
|
|
Packit Service |
395ff1 |
perror("add_sc");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
close(fd);
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
sprintf(new_name, "statfs_change%u", opts->journals);
|
|
Packit |
6ef888 |
error = rename2system(opts, opts->per_node, new_name);
|
|
Packit |
6ef888 |
if (error < 0 && errno != EEXIST){
|
|
Packit |
6ef888 |
perror("add_sc rename2system");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void add_qc(struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit Service |
395ff1 |
int fd;
|
|
Packit Service |
395ff1 |
char new_name[256];
|
|
Packit Service |
395ff1 |
int error;
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
fd = create_new_inode(opts, NULL);
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
{
|
|
Packit Service |
395ff1 |
char buf[sdp->bsize];
|
|
Packit Service |
395ff1 |
unsigned int blocks =
|
|
Packit Service |
395ff1 |
sdp->qcsize << (20 - sdp->sd_sb.sb_bsize_shift);
|
|
Packit Service |
395ff1 |
unsigned int x;
|
|
Packit Service |
395ff1 |
struct gfs2_meta_header mh;
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL);
|
|
Packit Service |
395ff1 |
memset(buf, 0, sdp->bsize);
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
for (x=0; x
|
|
Packit Service |
395ff1 |
if (write(fd, buf, sdp->bsize) != sdp->bsize) {
|
|
Packit Service |
395ff1 |
perror("add_qc");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
lseek(fd, 0, SEEK_SET);
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
memset(&mh, 0, sizeof(struct gfs2_meta_header));
|
|
Packit Service |
395ff1 |
mh.mh_magic = GFS2_MAGIC;
|
|
Packit Service |
395ff1 |
mh.mh_type = GFS2_METATYPE_QC;
|
|
Packit Service |
395ff1 |
mh.mh_format = GFS2_FORMAT_QC;
|
|
Packit Service |
395ff1 |
gfs2_meta_header_out(&mh, buf);
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
for (x=0; x
|
|
Packit Service |
395ff1 |
if (write(fd, buf, sdp->bsize) != sdp->bsize) {
|
|
Packit Service |
395ff1 |
perror("add_qc");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
error = fsync(fd);
|
|
Packit Service |
395ff1 |
if (error){
|
|
Packit |
6ef888 |
perror("add_qc fsync");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
close(fd);
|
|
Packit Service |
395ff1 |
|
|
Packit |
6ef888 |
sprintf(new_name, "quota_change%u", opts->journals);
|
|
Packit |
6ef888 |
error = rename2system(opts, opts->per_node, new_name);
|
|
Packit |
6ef888 |
if (error < 0 && errno != EEXIST){
|
|
Packit |
6ef888 |
perror("add_qc rename2system");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void gather_info(struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
struct statfs statbuf;
|
|
Packit |
6ef888 |
if (statfs(opts->path, &statbuf) < 0) {
|
|
Packit |
6ef888 |
perror(opts->path);
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
sdp->bsize = statbuf.f_bsize;
|
|
Packit Service |
af18b4 |
sdp->blks_total = statbuf.f_blocks;
|
|
Packit Service |
af18b4 |
sdp->blks_alloced = sdp->blks_total - statbuf.f_bfree;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void find_current_journals(struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
struct dirent *dp;
|
|
Packit |
6ef888 |
DIR *dirp;
|
|
Packit |
6ef888 |
unsigned existing_journals = 0;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
dirp = opendir(opts->jindex);
|
|
Packit |
6ef888 |
if (!dirp) {
|
|
Packit |
6ef888 |
perror("jindex");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
while (dirp) {
|
|
Packit |
6ef888 |
if ((dp = readdir(dirp)) != NULL) {
|
|
Packit |
6ef888 |
if (strncmp(dp->d_name, "journal", 7) == 0)
|
|
Packit |
6ef888 |
existing_journals++;
|
|
Packit |
6ef888 |
} else
|
|
Packit Service |
395ff1 |
goto close;
|
|
Packit |
6ef888 |
}
|
|
Packit Service |
395ff1 |
close:
|
|
Packit Service |
395ff1 |
closedir(dirp);
|
|
Packit |
6ef888 |
if (existing_journals == 0) {
|
|
Packit Service |
395ff1 |
die( _("No journals found. Did you run mkfs.gfs2 correctly?\n"));
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
opts->orig_journals = existing_journals;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
#ifdef GFS2_HAS_LH_V2
|
|
Packit |
6ef888 |
static uint64_t find_block_address(int fd, off_t offset, unsigned bsize)
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
struct {
|
|
Packit |
6ef888 |
struct fiemap fm;
|
|
Packit |
6ef888 |
struct fiemap_extent fe;
|
|
Packit |
6ef888 |
} fme;
|
|
Packit |
6ef888 |
int ret;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
fme.fm.fm_start = offset;
|
|
Packit |
6ef888 |
fme.fm.fm_length = 1;
|
|
Packit |
6ef888 |
fme.fm.fm_flags = FIEMAP_FLAG_SYNC;
|
|
Packit |
6ef888 |
fme.fm.fm_extent_count = 1;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
ret = ioctl(fd, FS_IOC_FIEMAP, &fme.fm);
|
|
Packit |
6ef888 |
if (ret != 0 || fme.fm.fm_mapped_extents != 1) {
|
|
Packit |
6ef888 |
fprintf(stderr, "Failed to find log header block address\n");
|
|
Packit |
6ef888 |
return 0;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
return fme.fe.fe_physical / bsize;
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
#endif
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
static void add_j(struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit |
6ef888 |
{
|
|
Packit Service |
395ff1 |
int fd;
|
|
Packit Service |
395ff1 |
char new_name[256];
|
|
Packit Service |
395ff1 |
int error;
|
|
Packit Service |
395ff1 |
uint64_t addr;
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
fd = create_new_inode(opts, &addr);
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
{
|
|
Packit Service |
395ff1 |
char buf[sdp->bsize];
|
|
Packit Service |
395ff1 |
unsigned int blocks =
|
|
Packit Service |
395ff1 |
sdp->jsize << (20 - sdp->sd_sb.sb_bsize_shift);
|
|
Packit Service |
395ff1 |
unsigned int x;
|
|
Packit Service |
395ff1 |
struct gfs2_log_header lh;
|
|
Packit Service |
395ff1 |
uint64_t seq = RANDOM(blocks);
|
|
Packit Service |
395ff1 |
off_t off = 0;
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
set_flags(fd, JA_FL_CLEAR, FS_JOURNAL_DATA_FL);
|
|
Packit Service |
395ff1 |
memset(buf, 0, sdp->bsize);
|
|
Packit Service |
395ff1 |
for (x=0; x
|
|
Packit Service |
395ff1 |
if (write(fd, buf, sdp->bsize) != sdp->bsize) {
|
|
Packit Service |
395ff1 |
perror("add_j");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
lseek(fd, 0, SEEK_SET);
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
memset(&lh, 0, sizeof(struct gfs2_log_header));
|
|
Packit Service |
395ff1 |
lh.lh_header.mh_magic = GFS2_MAGIC;
|
|
Packit Service |
395ff1 |
lh.lh_header.mh_type = GFS2_METATYPE_LH;
|
|
Packit Service |
395ff1 |
lh.lh_header.mh_format = GFS2_FORMAT_LH;
|
|
Packit Service |
395ff1 |
lh.lh_flags = GFS2_LOG_HEAD_UNMOUNT;
|
|
Packit |
6ef888 |
#ifdef GFS2_HAS_LH_V2
|
|
Packit Service |
395ff1 |
lh.lh_flags |= GFS2_LOG_HEAD_USERSPACE;
|
|
Packit Service |
395ff1 |
lh.lh_jinode = addr;
|
|
Packit |
6ef888 |
#endif
|
|
Packit Service |
395ff1 |
for (x=0; x
|
|
Packit Service |
395ff1 |
uint32_t hash;
|
|
Packit Service |
395ff1 |
|
|
Packit Service |
395ff1 |
lh.lh_sequence = seq;
|
|
Packit Service |
395ff1 |
lh.lh_blkno = x;
|
|
Packit Service |
395ff1 |
gfs2_log_header_out(&lh, buf);
|
|
Packit Service |
395ff1 |
hash = lgfs2_log_header_hash(buf);
|
|
Packit Service |
395ff1 |
((struct gfs2_log_header *)buf)->lh_hash = cpu_to_be32(hash);
|
|
Packit |
03c5d0 |
#ifdef GFS2_HAS_LH_V2
|
|
Packit Service |
395ff1 |
((struct gfs2_log_header *)buf)->lh_addr = cpu_to_be64(
|
|
Packit Service |
395ff1 |
find_block_address(fd, off, sdp->bsize));
|
|
Packit Service |
395ff1 |
hash = lgfs2_log_header_crc(buf, sdp->bsize);
|
|
Packit Service |
395ff1 |
((struct gfs2_log_header *)buf)->lh_crc = cpu_to_be32(hash);
|
|
Packit |
03c5d0 |
#endif
|
|
Packit Service |
395ff1 |
if (write(fd, buf, sdp->bsize) != sdp->bsize) {
|
|
Packit Service |
395ff1 |
perror("add_j");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
if (++seq == blocks)
|
|
Packit Service |
395ff1 |
seq = 0;
|
|
Packit Service |
395ff1 |
off += sdp->bsize;
|
|
Packit Service |
395ff1 |
}
|
|
Packit |
03c5d0 |
|
|
Packit Service |
395ff1 |
error = fsync(fd);
|
|
Packit Service |
395ff1 |
if (error){
|
|
Packit |
6ef888 |
perror("add_j fsync");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
close(fd);
|
|
Packit Service |
395ff1 |
|
|
Packit |
6ef888 |
sprintf(new_name, "journal%u", opts->journals);
|
|
Packit |
6ef888 |
error = rename2system(opts, opts->jindex, new_name);
|
|
Packit |
6ef888 |
if (error < 0 && errno != EEXIST){
|
|
Packit |
6ef888 |
perror("add_j rename2system");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
39c9a9 |
}
|
|
Packit |
39c9a9 |
}
|
|
Packit |
39c9a9 |
|
|
Packit Service |
af18b4 |
static int check_fit(struct gfs2_sbd *sdp, struct jadd_opts *opts)
|
|
Packit Service |
af18b4 |
{
|
|
Packit Service |
af18b4 |
/* Compute how much space we'll need for the new journals
|
|
Packit Service |
af18b4 |
* Number of blocks needed per added journal:
|
|
Packit Service |
af18b4 |
* 1 block for the ir inode
|
|
Packit Service |
af18b4 |
* 1 block for the sc inode
|
|
Packit Service |
af18b4 |
* for sizes of the qc and journal inodes, use lgfs2_space_for_data()
|
|
Packit Service |
af18b4 |
* to calculate.
|
|
Packit Service |
af18b4 |
*/
|
|
Packit Service |
af18b4 |
uint64_t blks_per_j, total_blks;
|
|
Packit Service |
af18b4 |
|
|
Packit Service |
af18b4 |
blks_per_j = 1 + 1 +
|
|
Packit Service |
af18b4 |
lgfs2_space_for_data(sdp, sdp->bsize, sdp->qcsize << 20) +
|
|
Packit Service |
af18b4 |
lgfs2_space_for_data(sdp, sdp->bsize, sdp->jsize << 20);
|
|
Packit Service |
af18b4 |
total_blks = opts->journals * blks_per_j;
|
|
Packit Service |
af18b4 |
|
|
Packit Service |
af18b4 |
if (total_blks > (sdp->blks_total - sdp->blks_alloced)) {
|
|
Packit Service |
af18b4 |
printf( _("\nInsufficient space on the device to add %u %uMB "
|
|
Packit Service |
af18b4 |
"journals (%uMB QC size)\n\n"),
|
|
Packit Service |
af18b4 |
opts->journals, sdp->jsize, sdp->qcsize);
|
|
Packit Service |
af18b4 |
printf( _("Required space : %*lu blks (%lu blks per "
|
|
Packit Service |
af18b4 |
"journal)\n"), 10, total_blks, blks_per_j);
|
|
Packit Service |
af18b4 |
printf( _("Available space : %*lu blks\n\n"), 10,
|
|
Packit Service |
af18b4 |
sdp->blks_total - sdp->blks_alloced);
|
|
Packit Service |
af18b4 |
errno = ENOSPC;
|
|
Packit Service |
af18b4 |
return 1;
|
|
Packit Service |
af18b4 |
}
|
|
Packit Service |
af18b4 |
return 0;
|
|
Packit Service |
af18b4 |
}
|
|
Packit Service |
af18b4 |
|
|
Packit |
6ef888 |
int main(int argc, char *argv[])
|
|
Packit |
6ef888 |
{
|
|
Packit |
6ef888 |
struct jadd_opts opts = {0};
|
|
Packit |
6ef888 |
struct gfs2_sbd sbd, *sdp = &sbd;
|
|
Packit |
6ef888 |
struct metafs mfs = {0};
|
|
Packit |
6ef888 |
struct mntent *mnt;
|
|
Packit Service |
af18b4 |
unsigned int total, ret = 0;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
setlocale(LC_ALL, "");
|
|
Packit |
6ef888 |
textdomain("gfs2-utils");
|
|
Packit |
6ef888 |
srandom(time(NULL) ^ getpid());
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
memset(sdp, 0, sizeof(struct gfs2_sbd));
|
|
Packit |
6ef888 |
sdp->jsize = GFS2_DEFAULT_JSIZE;
|
|
Packit |
6ef888 |
sdp->qcsize = GFS2_DEFAULT_QCSIZE;
|
|
Packit |
6ef888 |
opts.journals = 1;
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
decode_arguments(argc, argv, sdp, &opts);
|
|
Packit |
6ef888 |
verify_arguments(sdp, &opts);
|
|
Packit |
6ef888 |
|
|
Packit |
6ef888 |
sbd.path_fd = lgfs2_open_mnt_dir(opts.path, O_RDONLY|O_CLOEXEC, &mnt;;
|
|
Packit |
6ef888 |
if (sbd.path_fd < 0) {
|
|
Packit Service |
395ff1 |
fprintf(stderr, _("Error looking up mount '%s': %s\n"), opts.path, strerror(errno));
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
if (mnt == NULL) {
|
|
Packit Service |
395ff1 |
fprintf(stderr, _("%s: not a mounted gfs2 file system\n"), opts.path);
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit Service |
395ff1 |
gather_info(sdp, &opts);
|
|
Packit |
6ef888 |
mfs.context = copy_context_opt(mnt);
|
|
Packit Service |
395ff1 |
if (mount_gfs2_meta(&mfs, mnt->mnt_dir, opts.debug)) {
|
|
Packit |
6ef888 |
perror("GFS2 metafs");
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
if (build_paths(mfs.path, &opts)) {
|
|
Packit |
6ef888 |
perror(_("Failed to build paths"));
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
395ff1 |
if (compute_constants(sdp)) {
|
|
Packit |
6ef888 |
perror(_("Failed to compute file system constants"));
|
|
Packit Service |
395ff1 |
exit(EXIT_FAILURE);
|
|
Packit |
39c9a9 |
}
|
|
Packit Service |
395ff1 |
find_current_journals(&opts);
|
|
Packit |
39c9a9 |
|
|
Packit Service |
af18b4 |
ret = check_fit(sdp, &opts);
|
|
Packit Service |
af18b4 |
if (ret) {
|
|
Packit Service |
af18b4 |
perror(_("Failed to add journals"));
|
|
Packit Service |
af18b4 |
goto out;
|
|
Packit Service |
af18b4 |
}
|
|
Packit Service |
af18b4 |
|
|
Packit |
6ef888 |
total = opts.orig_journals + opts.journals;
|
|
Packit |
6ef888 |
for (opts.journals = opts.orig_journals;
|
|
Packit |
6ef888 |
opts.journals < total;
|
|
Packit |
6ef888 |
opts.journals++) {
|
|
Packit |
6ef888 |
if (metafs_interrupted) {
|
|
Packit Service |
395ff1 |
cleanup_metafs(&mfs;;
|
|
Packit Service |
395ff1 |
exit(130);
|
|
Packit |
6ef888 |
}
|
|
Packit Service |
395ff1 |
add_ir(&opts);
|
|
Packit Service |
395ff1 |
add_sc(&opts);
|
|
Packit Service |
395ff1 |
add_qc(sdp, &opts);
|
|
Packit Service |
395ff1 |
add_j(sdp, &opts);
|
|
Packit |
6ef888 |
}
|
|
Packit |
6ef888 |
|
|
Packit Service |
af18b4 |
out:
|
|
Packit |
6ef888 |
free(opts.new_inode);
|
|
Packit |
6ef888 |
free(opts.per_node);
|
|
Packit |
6ef888 |
free(opts.jindex);
|
|
Packit |
03c5d0 |
close(sdp->path_fd);
|
|
Packit Service |
395ff1 |
cleanup_metafs(&mfs;;
|
|
Packit Service |
395ff1 |
sync();
|
|
Packit |
39c9a9 |
|
|
Packit Service |
af18b4 |
if (!ret)
|
|
Packit Service |
af18b4 |
print_results(&opts);
|
|
Packit Service |
af18b4 |
|
|
Packit Service |
af18b4 |
return ret;
|
|
Packit |
6ef888 |
}
|