📄 tune.c
字号:
/* * Copyright (c) International Business Machines Corp., 2000-2002 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <config.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <string.h>#include <stdlib.h>#include <stdio.h>#include <time.h>#include <ctype.h>#include "jfs_types.h"#include "jfs_endian.h"#include "jfs_filsys.h"#include "jfs_superblock.h"#include "inode.h"#include "super.h"#include "jfs_version.h"#include "utilsubs.h"#define EXIT(fd, rc) {fclose(fd); exit(rc);}static int J_flag, l_flag, L_flag, U_flag;char *new_label, *new_UUID;char *device;char logdev[255] = { '\0' };FILE *log_fd = NULL;int log_desc = -1;char *OpenMode = "r";extern int LogOpenMode;extern FILE * open_by_label(uuid_t, int, int, char *, int *);extern void display_logsuper(struct logsuper *);extern void display_super(struct superblock *);void tune_usage(void){ printf("\nUsage: jfs_tune [-J options] [-l] [-L vol_label] [-U uuid] [-V] device\n" "\nEmergency help:\n" " -J options Set external journal options.\n" " -l Display superblock\n" " -L vol_label Set volume label.\n" " -U uuid Set UUID.\n" " -V Print version information only.\n"); exit(-1);}/*-------------------------------------------------------------------- * NAME: parse_journal_opts * * FUNCTION: parse journal (-J) options * set log file descriptor (global log_fd) * set log device name (global logdev) * * PARAMETERS: * opts - options string */void parse_journal_opts(const char *opts){ int journal_usage = 0; uuid_t log_uuid; int in_use; LogOpenMode = O_RDONLY; if (strncmp(opts, "device=", 7) == 0) { if (strncmp(opts + 7, "UUID=", 5) == 0) { if (uuid_parse((char *) opts + 7 + 5, log_uuid)) { fputs("\nError: UUID entered in improper format.\n", stderr); exit(-1); } else { log_fd = open_by_label(log_uuid, 0, 1, logdev, &in_use); } } else if (strncmp(opts + 7, "LABEL=", 6) == 0) { log_fd = open_by_label((char *) opts + 7 + 6, 1, 1, logdev, &in_use); } else { strcpy(logdev, ((char *) opts + 7)); if (logdev) log_fd = fopen(logdev, "r"); else journal_usage++; } } else journal_usage++; if (journal_usage) { fprintf(stderr, "\nInvalid journal option(s) specified.\n\n" "Valid options for -J are:\n" "\tdevice=<journal device>\n" "\tdevice=UUID=<UUID of journal device>\n" "\tdevice=LABEL=<label of journal device>\n\n"); exit(1); } return;}/*-------------------------------------------------------------------- * NAME: parse_tune_options * * FUNCTION: parse tune options * * PARAMETERS: * argc - number of passed arguments * argv - string of arguments * * RETURNS: * success: 0 * failure: any other value */static void parse_tune_options(int argc, char *argv[]){ int c; while ((c = getopt(argc, argv, "J:lL:U:V")) != EOF) { switch (c) { case 'J': /* attach external journal device */ parse_journal_opts(optarg); J_flag = 1; OpenMode = "r+"; break; case 'l': /* display superblock */ l_flag = 1; break; case 'L': /* set volume label */ new_label = optarg; L_flag = 1; OpenMode = "r+"; break; case 'U': /* set UUID */ new_UUID = optarg; U_flag = 1; OpenMode = "r+"; break; case 'V': /* print version and exit */ exit(0); break; default: tune_usage(); break; } } if (optind != argc - 1) { printf("\nError: Device not specified or command format error.\n"); tune_usage(); } if (!J_flag && !l_flag && !L_flag && !U_flag) { printf("\nError: No options selected.\n"); tune_usage(); } device = argv[optind]; return;}/*-------------------------------------------------------------------- * NAME: main * * FUNCTION: adjust JFS tunable parameters * * PARAMETERS: * argc - number of passed arguments * argv - string of arguments * * RETURNS: * success: 0 * failure: any other value */int main(int argc, char *argv[]){ FILE *fp = NULL; int rc = 0; int superblock_type; bool mounted = false; struct superblock sb; struct logsuper logsup;#define FS_SUPER_SECONDARY 0#define FS_SUPER_PRIMARY 1#define LOG_SUPER 2 printf("jfs_tune version %s, %s\n", VERSION, JFSUTILS_DATE); parse_tune_options(argc, argv); /* * Check if device is mounted. -l is the only parameter * supported on a mounted device, so if any others are * selected, let the user know. If the device is mounted * and -l was not specified, get out. */ rc = Is_Device_Mounted(device); if (rc) { mounted = true; if (J_flag || L_flag || U_flag) { fprintf(stderr, "\n%s is mounted.\n" "While mounted, the only supported jfs_tune parameter is -l.\n", device); if (!l_flag) { exit(-1); } } } /* Open device */ if (J_flag) fp = fopen_excl(device, "r+"); else fp = fopen(device, OpenMode); if (fp == NULL) { fprintf(stderr, "Error: Cannot open device %s.\n", device); exit(-1); } /* Get and validate primary JFS superblock */ if ((rc = ujfs_get_superblk(fp, &sb, 1)) == 0) { if ((rc = ujfs_validate_super(&sb)) == 0) { superblock_type = FS_SUPER_PRIMARY; } } /* If failure retrieving primary superblock, get/validate secondary superblock */ if (rc) { if ((rc = ujfs_get_superblk(fp, &sb, 0)) == 0) { if ((rc = ujfs_validate_super(&sb)) == 0) { superblock_type = FS_SUPER_SECONDARY; } } } /* If no valid FS superblock, see if we have a log superblock */ if (rc) { if ((rc = ujfs_get_logsuper(fp, &logsup)) == 0) { if ((rc = ujfs_validate_logsuper(&logsup)) == 0) { superblock_type = LOG_SUPER; /* * We know this is an external journal device. * Now check to see if it is attached to a * mounted file system. If so, the only * valid option is -l. */ if (logsup.state == LOGMOUNT) { mounted = true; if (J_flag || L_flag || U_flag) { fprintf(stderr, "\n%s contains an external journal for a mounted filesystem.\n" "While mounted, the only supported jfs_tune parameter is -l.\n", device); if (!l_flag) { EXIT(fp, -1); } } } } } } /* If we couldn't find/read a valid JFS FS or log superblock, warn user and exit */ if (rc) { printf("\nCould not read valid JFS FS or log superblock on device %s.\n", device); EXIT(fp, -1); } /* * Account for bug in mkfs.jfs 1.0.18 and 1.0.19 * that didn't properly set the file system version * number to 2 when using an external journal. */ if (!mounted && (superblock_type < LOG_SUPER) && (sb.s_version < JFS_VERSION) && !(sb.s_flag & JFS_INLINELOG)) { sb.s_version = JFS_VERSION; rc = ujfs_put_superblk(fp, &sb, superblock_type); if (rc) { printf("\nCould not update JFS version number properly on %s.\n", device); EXIT(fp, rc); } } /* * set volume label on unmounted device */ if (L_flag && !mounted) { if (superblock_type < LOG_SUPER) { /* change label in JFS file system superblock */ /* * The superblock in JFS releases before 1.0.18 stores * the label in s_fpack[11]. The superblock in JFS * releases 1.0.18 and greater has s_fpack, but uses * the new field s_label[16] to store the label. * s_label is in an area of the superblock that was * allocated but unused in pre 1.0.18, so if per chance * the user is using an old JFS file system, setting * s_label will not be a problem. */ memset(sb.s_fpack, 0, sizeof (sb.s_fpack)); strncpy(sb.s_fpack, new_label, sizeof (sb.s_fpack)); if (strlen(new_label) > sizeof (sb.s_label)) fprintf(stderr, "Warning: label too long, truncating.\n"); memset(sb.s_label, 0, sizeof (sb.s_label)); strncpy(sb.s_label, new_label, sizeof (sb.s_label)); rc = ujfs_put_superblk(fp, &sb, superblock_type); } else { /* change label in JFS log superblock */ if (strlen(new_label) > sizeof (logsup.label)) fprintf(stderr, "Warning: label too long, truncating.\n"); memset(logsup.label, 0, sizeof (logsup.label)); strncpy(logsup.label, new_label, sizeof (logsup.label)); rc = ujfs_put_logsuper(fp, &logsup); } if (rc) { printf("\nError writing superblock to disk. Label unchanged.\n"); EXIT(fp, rc); } else { printf("Volume label updated successfully.\n"); } } /* * set UUID on umounted device */ if (U_flag && !mounted) { uuid_t *uu; uu = ((superblock_type < LOG_SUPER) ? &sb.s_uuid : &logsup.uuid); if ((strcasecmp(new_UUID, "null") == 0) || (strcasecmp(new_UUID, "clear") == 0)) { uuid_clear(*uu); } else if (strcasecmp(new_UUID, "time") == 0) { uuid_generate_time(*uu); } else if (strcasecmp(new_UUID, "random") == 0) { uuid_generate(*uu); } else if (uuid_parse(new_UUID, *uu)) { fprintf(stderr, "Invalid UUID format.\n"); EXIT(fp, -1); } if (superblock_type < LOG_SUPER) { /* mount(8) won't recognize uuid if jfs_version == 1 */ if (sb.s_version == 1) { sb.s_version = 2; /* Make sure s_label is set. If it's valid, * the first 11 characters will match s_fpack */ if (strncmp(sb.s_fpack, sb.s_label, 11)) { strncpy(sb.s_label, sb.s_fpack, 11); sb.s_label[11] = 0; } } rc = ujfs_put_superblk(fp, &sb, superblock_type); } else { rc = ujfs_put_logsuper(fp, &logsup); } if (rc) { printf("\nError writing superblock to disk. UUID unchanged.\n"); EXIT(fp, rc); } else { printf("UUID updated successfully.\n"); } } /* * attach external journal to JFS file system */ if (J_flag && !mounted) { /* * NOTE: If we ever allow attaching more than one file system to a * single log file, we'll have to change the conditions of the above * 'if' to account for a log file that is in use by one file system * (state LOGMOUNT), but is being attached to by another file system. */ struct stat st; /* make sure device to be attached to is a JFS file system */ if (superblock_type >= LOG_SUPER) { printf("\nError: %s does not contain a JFS file system.\n",device); EXIT(fp, -1); } /* log_fd was set in parse_journal_opts */ if (log_fd == NULL) { printf("\nError: Could not find/open specified external journal device.\n"); EXIT(fp, -1); } /* get valid log superblock */ if ((rc = ujfs_get_logsuper(log_fd, &logsup)) == 0) { if ((rc = ujfs_validate_logsuper(&logsup)) == 0) { if (fstat(fileno(log_fd), &st)) { rc = -1; } else { /* update FS superblock */ sb.s_logdev = st.st_rdev; uuid_copy(sb.s_loguuid, logsup.uuid); sb.s_version = JFS_VERSION; sb.s_flag &= (~JFS_INLINELOG); memset(&sb.s_logpxd, 0, sizeof (pxd_t)); rc = ujfs_put_superblk(fp, &sb, superblock_type); } } } /* If we could't find/read a valid JFS log superblock, let user know */ if (rc) { printf("\nError attaching JFS external journal to JFS FS.\n"); } else { printf("Attached JFS external journal to JFS FS successfully.\n"); } fclose(log_fd); } /* * display superblock */ if (l_flag) { if (superblock_type < LOG_SUPER) { display_super(&sb); } else { display_logsuper(&logsup); } } fclose(fp); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -