Whamcloud - gitweb
LU-1047 utils: mkfs shouldn't create loopback files in /dev
authorJohann Lombardi <johann@whamcloud.com>
Fri, 27 Jan 2012 21:48:17 +0000 (22:48 +0100)
committerOleg Drokin <green@whamcloud.com>
Thu, 29 Mar 2012 03:42:45 +0000 (23:42 -0400)
When the target device does not exist, mkfs.lustre shouldn't assume
that the user wants to create a loopback file under /dev.

This patch also fixes some error msgs printed by mkfs.lustre:
mkfs.lustre: Unable to create backing store: 2
mkfs.lustre: Unable to truncate backing store: 2

to be instead:
mkfs.lustre: Unable to create backing store: No such file or directory
mkfs.lustre: Unable to truncate backing store: No such file or
             directory

Signed-off-by: Johann Lombardi <johann@whamcloud.com>
Change-Id: I5f4393a47d06e5b7bde7745b38a938dcd2eb7ecd
Reviewed-on: http://review.whamcloud.com/2035
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Tested-by: Hudson
Reviewed-by: Yu Jian <yujian@whamcloud.com>
Tested-by: Maloo <whamcloud.maloo@gmail.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
lustre/utils/mkfs_lustre.c

index 94132b3..94632c8 100644 (file)
@@ -305,21 +305,79 @@ int loop_cleanup(struct mkfs_opts *mop)
         return ret;
 }
 
+/* return canonicalized absolute pathname, even if the target file does not
+ * exist, unlike realpath */
+static char *absolute_path(char *devname)
+{
+        char  buf[PATH_MAX + 1];
+        char *path;
+        char *ptr;
+
+        path = malloc(PATH_MAX + 1);
+        if (path == NULL)
+                return NULL;
+
+        if (devname[0] != '/') {
+                if (getcwd(buf, sizeof(buf) - 1) == NULL)
+                        return NULL;
+                strcat(buf, "/");
+                strcat(buf, devname);
+        } else {
+                strcpy(buf, devname);
+        }
+        /* truncate filename before calling realpath */
+        ptr = strrchr(buf, '/');
+        if (ptr == NULL) {
+                free(path);
+                return NULL;
+        }
+        *ptr = '\0';
+        if (path != realpath(buf, path)) {
+                free(path);
+                return NULL;
+        }
+        /* add the filename back */
+        strcat(path, "/");
+        strcat(path, ptr + 1);
+        return path;
+}
+
 /* Determine if a device is a block device (as opposed to a file) */
 int is_block(char* devname)
 {
         struct stat st;
-        int ret = 0;
+        int         ret = 0;
+        char       *devpath;
+
+        devpath = absolute_path(devname);
+        if (devpath == NULL) {
+                fprintf(stderr, "%s: failed to resolve path to %s\n",
+                        progname, devname);
+                return -1;
+        }
 
         ret = access(devname, F_OK);
-        if (ret != 0)
-                return 0;
-        ret = stat(devname, &st);
         if (ret != 0) {
-                fprintf(stderr, "%s: cannot stat %s\n", progname, devname);
-                return -1;
+                if (strncmp(devpath, "/dev/", 5) == 0) {
+                    /* nobody sane wants to create a loopback file under
+                     * /dev. Let's just report the device doesn't exist */
+                    fprintf(stderr, "%s: %s apparently does not exist\n",
+                            progname, devpath);
+                    ret = -1;
+                    goto out;
+                }
+                ret = 0;
+                goto out;
+        }
+        ret = stat(devpath, &st);
+        if (ret != 0) {
+                fprintf(stderr, "%s: cannot stat %s\n", progname, devpath);
+                goto out;
         }
-        return S_ISBLK(st.st_mode);
+        ret = S_ISBLK(st.st_mode);
+out:
+        free(devpath);
+        return ret;
 }
 
 __u64 get_device_size(char* device)
@@ -359,7 +417,7 @@ __u64 get_device_size(char* device)
 
 int loop_format(struct mkfs_opts *mop)
 {
-        int ret = 0;
+        int fd;
 
         if (mop->mo_device_sz == 0) {
                 fatal();
@@ -368,23 +426,24 @@ int loop_format(struct mkfs_opts *mop)
                 return EINVAL;
         }
 
-        ret = creat(mop->mo_device, S_IRUSR|S_IWUSR);
-        if (ret < 0) {
-                ret = errno;
-                fprintf(stderr, "%s: Unable to create backing store: %d\n",
-                        progname, ret);
-        } else {
-                close(ret);
+        fd = creat(mop->mo_device, S_IRUSR|S_IWUSR);
+        if (fd < 0) {
+                fatal();
+                fprintf(stderr, "%s: Unable to create backing store: %s\n",
+                        progname, strerror(errno));
+                return errno;
         }
 
-        ret = truncate(mop->mo_device, mop->mo_device_sz * 1024);
-        if (ret != 0) {
-                ret = errno;
-                fprintf(stderr, "%s: Unable to truncate backing store: %d\n",
-                        progname, ret);
+        if (ftruncate(fd, mop->mo_device_sz * 1024) != 0) {
+                close(fd);
+                fatal();
+                fprintf(stderr, "%s: Unable to truncate backing store: %s\n",
+                        progname, strerror(errno));
+                return errno;
         }
 
-        return ret;
+        close(fd);
+        return 0;
 }
 
 /* Display the need for the latest e2fsprogs to be installed. make_backfs
@@ -1722,8 +1781,10 @@ int main(int argc, char *const argv[])
 
         /* Are we using a loop device? */
         ret = is_block(mop.mo_device);
-        if (ret < 0)
+        if (ret < 0) {
+                ret = errno;
                 goto out;
+        }
         if (ret == 0)
                 mop.mo_flags |= MO_IS_LOOP;
 
@@ -1873,8 +1934,11 @@ int main(int argc, char *const argv[])
                         ret = errno;
 #ifndef TUNEFS /* mkfs.lustre */
                 /* Reformat the loopback file */
-                if (ret || (mop.mo_flags & MO_FORCEFORMAT))
+                if (ret || (mop.mo_flags & MO_FORCEFORMAT)) {
                         ret = loop_format(&mop);
+                        if (ret)
+                                goto out;
+                }
 #endif
                 if (ret == 0)
                         ret = loop_setup(&mop);