Whamcloud - gitweb
LU-3682 tunefs: prevent tunefs running on a mounted device 33/7433/7
authorEmoly Liu <emoly.liu@intel.com>
Tue, 10 Sep 2013 07:14:16 +0000 (15:14 +0800)
committerOleg Drokin <oleg.drokin@intel.com>
Fri, 20 Sep 2013 21:29:21 +0000 (21:29 +0000)
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 <emoly.liu@intel.com>
Change-Id: I57d9dc443d94057014212cb30d04a2f385b50d7b
Reviewed-on: http://review.whamcloud.com/7433
Tested-by: Hudson
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Niu Yawei <yawei.niu@intel.com>
Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/utils/mkfs_lustre.c
lustre/utils/mount_lustre.c
lustre/utils/mount_utils.c
lustre/utils/mount_utils.h

index 646a767..3d6baee 100644 (file)
@@ -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() */
index cc32fba..3fa1311 100644 (file)
@@ -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 "<name>\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) {
index e0502fe..cdc1ed6 100644 (file)
@@ -46,6 +46,7 @@
 #include <lustre_ver.h>
 #include <sys/stat.h>
 #include <sys/utsname.h>
+#include <linux/loop.h>
 
 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 "<name>\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;
+}
index 7f9cda8..32be5c0 100644 (file)
@@ -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);