From: Emoly Liu Date: Tue, 10 Sep 2013 07:14:16 +0000 (+0800) Subject: LU-3682 tunefs: prevent tunefs running on a mounted device X-Git-Tag: 2.4.93~28 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=66858bc059362504d201262202549099185e69ba LU-3682 tunefs: prevent tunefs running on a mounted device This patch is to check if the given device is already mounted in the following two situations. 1) Try to get the real path to the given device, in case it is a symbolic link or dm device for instance, and return EEXIST if it is already mounted. 2) If the given file is already associated with a mounted loop device, check_mtab_entry() should return EEXIST to prevent the following loop setup attemp. Signed-off-by: Emoly Liu Change-Id: I57d9dc443d94057014212cb30d04a2f385b50d7b Reviewed-on: http://review.whamcloud.com/7433 Tested-by: Hudson Tested-by: Maloo Reviewed-by: Niu Yawei Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin --- diff --git a/lustre/utils/mkfs_lustre.c b/lustre/utils/mkfs_lustre.c index 646a767..3d6baee 100644 --- a/lustre/utils/mkfs_lustre.c +++ b/lustre/utils/mkfs_lustre.c @@ -270,7 +270,7 @@ static char *convert_hostnames(char *s1) return converted; } -int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, +static int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, char **mountopts) { static struct option long_opt[] = { @@ -522,9 +522,6 @@ int parse_opts(int argc, char *const argv[], struct mkfs_opts *mop, "pool/dataset name not specified.\n"); return EINVAL; } else { - /* The device or pool/filesystem name */ - strscpy(mop->mo_device, argv[optind], sizeof(mop->mo_device)); - /* Followed by optional vdevs */ if (optind < argc - 1) mop->mo_pool_vdevs = (char **) &argv[optind + 1]; @@ -556,12 +553,14 @@ int main(int argc, char *const argv[]) memset(&mop, 0, sizeof(mop)); set_defaults(&mop); - /* device is last arg */ - strscpy(mop.mo_device, argv[argc - 1], sizeof(mop.mo_device)); + /* Try to get the real path to the device */ + ret = get_realpath(argv[argc - 1], &mop.mo_device); + if (ret != 0) + return ret; ret = osd_init(); if (ret) - return ret; + goto out; #ifdef TUNEFS /* For tunefs, we must read in the old values before parsing any @@ -724,8 +723,12 @@ int main(int argc, char *const argv[]) goto out; } - if (check_mtab_entry(mop.mo_device, mop.mo_device, NULL, NULL)) - return(EEXIST); + ret = check_mtab_entry(mop.mo_device, mop.mo_device, NULL, NULL); + if (ret != 0) { + fprintf(stderr, "%s: %s is already mounted\n", + progname, mop.mo_device); + goto out; + } /* Create the loopback file */ if (mop.mo_flags & MO_IS_LOOP) { @@ -798,6 +801,7 @@ int main(int argc, char *const argv[]) out: loop_cleanup(&mop); + free(mop.mo_device); osd_fini(); /* Fix any crazy return values from system() */ diff --git a/lustre/utils/mount_lustre.c b/lustre/utils/mount_lustre.c index cc32fba..3fa1311 100644 --- a/lustre/utils/mount_lustre.c +++ b/lustre/utils/mount_lustre.c @@ -324,7 +324,7 @@ static int clear_update_ondisk(char *source, struct lustre_disk_data *ldd) memset(&mkop, 0, sizeof(mkop)); mkop.mo_ldd = *ldd; mkop.mo_ldd.ldd_flags &= ~LDD_F_UPDATE; - strcpy(mkop.mo_device, source); + mkop.mo_device = strdup(source); ret = osd_prepare_lustre(&mkop, default_mountopts, sizeof(default_mountopts), @@ -500,10 +500,6 @@ static int parse_opts(int argc, char *const argv[], struct mount_opts *mop) {"verbose", 0, 0, 'v'}, {0, 0, 0, 0} }; - char real_path[PATH_MAX] = {'\0'}; - FILE *f; - char path[256], name[256]; - size_t sz; char *ptr; int opt, rc; @@ -544,30 +540,13 @@ static int parse_opts(int argc, char *const argv[], struct mount_opts *mop) usage(stderr); } - mop->mo_usource = argv[optind]; - if (!mop->mo_usource) { + if (argv[optind] == NULL) usage(stderr); - } - /** - * Try to get the real path to the device, in case it is a - * symbolic link for instance - */ - if (realpath(mop->mo_usource, real_path) != NULL) { - ptr = strrchr(real_path, '/'); - if (ptr && strncmp(ptr, "/dm-", 4) == 0 && isdigit(*(ptr + 4))) { - snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptr+1); - if ((f = fopen(path, "r"))) { - /* read "\n" from sysfs */ - if (fgets(name, sizeof(name), f) && (sz = strlen(name)) > 1) { - name[sz - 1] = '\0'; - snprintf(real_path, sizeof(real_path), "/dev/mapper/%s", name); - } - fclose(f); - } - } - mop->mo_usource = strdup(real_path); - } + /* Try to get the real path to the device */ + rc = get_realpath(argv[optind], &mop->mo_usource); + if (rc != 0) + mop->mo_usource = argv[optind]; ptr = strstr(mop->mo_usource, ":/"); if (ptr != NULL) { diff --git a/lustre/utils/mount_utils.c b/lustre/utils/mount_utils.c index e0502fe..cdc1ed6 100644 --- a/lustre/utils/mount_utils.c +++ b/lustre/utils/mount_utils.c @@ -46,6 +46,7 @@ #include #include #include +#include extern char *progname; extern int verbose; @@ -169,27 +170,58 @@ char *strscpy(char *dst, char *src, int buflen) return strscat(dst, src, buflen); } +static int check_losetup(char *device, char *file_path) +{ + struct loop_info64 loop_info; + int fd; + int rc; + + fd = open(device, O_RDONLY); + if (fd < 0) + return errno; + + rc = ioctl(fd, LOOP_GET_STATUS64, (void *)&loop_info); + close(fd); + if (rc < 0) + return errno; + + return strcmp(file_path, (char *)(loop_info.lo_file_name)); +} + int check_mtab_entry(char *spec1, char *spec2, char *mtpt, char *type) { FILE *fp; struct mntent *mnt; + char lo_dev[] = "/dev/loop"; + int lo_dev_len = strlen(lo_dev); + int ret = 0; fp = setmntent(MOUNTED, "r"); if (fp == NULL) return 0; while ((mnt = getmntent(fp)) != NULL) { - if ((strcmp(mnt->mnt_fsname, spec1) == 0 || - strcmp(mnt->mnt_fsname, spec2) == 0) && + char *fsname = mnt->mnt_fsname; + + if ((strcmp(fsname, spec1) == 0 || + strcmp(fsname, spec2) == 0) && (mtpt == NULL || strcmp(mnt->mnt_dir, mtpt) == 0) && (type == NULL || strcmp(mnt->mnt_type, type) == 0)) { - endmntent(fp); - return(EEXIST); + ret = EEXIST; + break; + } + /* Check if the loop device is already mounted */ + if (strncmp(fsname, lo_dev, lo_dev_len) != 0) + continue; + if (check_losetup(fsname, spec1) == 0 || + check_losetup(fsname, spec2) == 0) { + ret = EEXIST; + break; } } endmntent(fp); - return 0; + return ret; } #define PROC_DIR "/proc/" @@ -744,3 +776,40 @@ int file_create(char *path, __u64 size) return 0; } + +/** + * Try to get the real path to the device, in case it is a + * symbolic link or dm device for instance + */ +int get_realpath(char *path, char **device) +{ + FILE *f; + size_t sz; + char *ptr; + char name[256]; + char real_path[PATH_MAX] = {'\0'}; + + if (realpath(path, real_path) == NULL) + return errno; + + ptr = strrchr(real_path, '/'); + if (ptr && strncmp(ptr, "/dm-", 4) == 0 && isdigit(*(ptr + 4))) { + snprintf(path, sizeof(path), "/sys/block/%s/dm/name", ptr+1); + f = fopen(path, "r"); + if (f != NULL) { + /* read "\n" from sysfs */ + if (fgets(name, sizeof(name), f) != NULL) { + sz = strlen(name); + if (sz > 1) { + name[sz - 1] = '\0'; + snprintf(real_path, sizeof(real_path), + "/dev/mapper/%s", name); + } + } + fclose(f); + } + } + *device = strdup(real_path); + + return 0; +} diff --git a/lustre/utils/mount_utils.h b/lustre/utils/mount_utils.h index 7f9cda8..32be5c0 100644 --- a/lustre/utils/mount_utils.h +++ b/lustre/utils/mount_utils.h @@ -71,7 +71,7 @@ extern int failover; /* used to describe the options to format the lustre disk, not persistent */ struct mkfs_opts { struct lustre_disk_data mo_ldd; /* to be written in MOUNT_DATA_FILE */ - char mo_device[128]; /* disk device name */ + char *mo_device; /* disk device name */ char **mo_pool_vdevs; /* list of pool vdevs */ char mo_loopdev[128]; /* in case a loop dev is needed */ char mo_mkfsopts[512]; /* options to the backing-store mkfs */ @@ -121,7 +121,8 @@ int update_mtab_entry(char *spec, char *mtpt, char *type, char *opts, int flags, int freq, int pass); int check_mountfsoptions(char *mountopts, char *wanted_mountopts, int justwarn); void trim_mountfsoptions(char *s); -__u64 get_device_size(char* device); +__u64 get_device_size(char *device); +int get_realpath(char *path, char **device); int is_block(char *devname); void disp_old_e2fsprogs_msg(const char *feature, int make_backfs);