Whamcloud - gitweb
LU-17662 osd-zfs: Support for ZFS 2.2.3
[fs/lustre-release.git] / lustre / utils / libmount_utils_ldiskfs.c
index 1ee3612..1721bf9 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  *
  * lustre/utils/mount_utils_ldiskfs.c
  *
@@ -64,6 +63,8 @@
 #include <limits.h>
 #include <ctype.h>
 
+#include <ext2fs/ext2fs.h>
+
 #ifndef BLKGETSIZE64
 #include <linux/fs.h> /* for BLKGETSIZE64 */
 #endif
 
 extern char *progname;
 
+static ext2_filsys backfs;
+static int open_flags = EXT2_FLAG_64BITS | EXT2_FLAG_SKIP_MMP |
+                       EXT2_FLAG_IGNORE_SB_ERRORS | EXT2_FLAG_SUPER_ONLY;
+
 /* keep it less than LL_FID_NAMELEN */
 #define DUMMY_FILE_NAME_LEN             25
 #define EXT3_DIRENT_SIZE                DUMMY_FILE_NAME_LEN
@@ -132,33 +137,6 @@ out:
        return ret;
 }
 
-static int is_feature_enabled(const char *feature, const char *devpath)
-{
-       char cmd[PATH_MAX];
-       FILE *fp;
-       char enabled_features[4096] = "";
-       int ret = 1;
-
-       snprintf(cmd, sizeof(cmd), "%s -c -R features %s 2>&1",
-                DEBUGFS, devpath);
-
-       /* Using popen() instead of run_command() since debugfs does
-        * not return proper error code if command is not supported */
-       fp = popen(cmd, "r");
-       if (!fp) {
-               fprintf(stderr, "%s: %s\n", progname, strerror(errno));
-               return 0;
-       }
-
-       ret = fread(enabled_features, 1, sizeof(enabled_features) - 1, fp);
-       enabled_features[ret] = '\0';
-       pclose(fp);
-
-       if (strstr(enabled_features, feature))
-               return 1;
-       return 0;
-}
-
 /* Write the server config files */
 int ldiskfs_write_ldd(struct mkfs_opts *mop)
 {
@@ -181,20 +159,31 @@ int ldiskfs_write_ldd(struct mkfs_opts *mop)
                dev = mop->mo_loopdev;
 
        /* Multiple mount protection enabled if failover node specified */
-       if (mop->mo_flags & MO_FAILOVER &&
-           !is_feature_enabled("mmp", dev)) {
-               if (is_e2fsprogs_feature_supp("-O mmp")) {
-                       char *command = filepnm;
-
-                       snprintf(command, sizeof(filepnm),
-                                TUNE2FS" -O mmp '%s' >/dev/null 2>&1", dev);
-                       ret = run_command(command, sizeof(filepnm));
-                       if (ret)
-                               fprintf(stderr,
-                                       "%s: Unable to set 'mmp' on %s: %d\n",
-                                       progname, dev, ret);
-               } else {
-                       disp_old_e2fsprogs_msg("mmp", 1);
+       if (mop->mo_flags & MO_FAILOVER) {
+               if (!backfs)
+                       ext2fs_open(dev, open_flags, 0, 0,
+                                   unix_io_manager, &backfs);
+               if (!backfs || !ext2fs_has_feature_mmp(backfs->super)) {
+                       if (is_e2fsprogs_feature_supp("-O mmp")) {
+                               char *command = filepnm;
+
+                               snprintf(command, sizeof(filepnm),
+                                        TUNE2FS" -O mmp '%s' >/dev/null 2>&1",
+                                        dev);
+                               ret = run_command(command, sizeof(filepnm));
+                               if (ret)
+                                       fprintf(stderr,
+                                               "%s: Unable to set 'mmp' "
+                                               "on %s: %d\n",
+                                               progname, dev, ret);
+                       } else {
+                               disp_old_e2fsprogs_msg("mmp", 1);
+                       }
+                       /* avoid stale cache after following operations */
+                       if (backfs) {
+                               ext2fs_close(backfs);
+                               backfs = NULL;
+                       }
                }
        }
 
@@ -271,51 +260,37 @@ static int readcmd(char *cmd, char *buf, int len)
 
 int ldiskfs_read_ldd(char *dev, struct lustre_disk_data *mo_ldd)
 {
-       char tmpdir[] = "/tmp/dirXXXXXX";
+       errcode_t retval;
+       ext2_ino_t ino;
+       ext2_file_t file;
+       unsigned int got;
        char cmd[PATH_MAX];
-       char filepnm[128];
-       FILE *filep;
        int ret = 0;
-       int cmdsz = sizeof(cmd);
-
-       /* Make a temporary directory to hold Lustre data files. */
-       if (!mkdtemp(tmpdir)) {
-               fprintf(stderr, "%s: Can't create temporary directory %s: %s\n",
-                       progname, tmpdir, strerror(errno));
-               return errno;
-       }
 
-       /* TODO: it's worth observing the get_mountdata() function that is
-          in mount_utils.c for getting the mountdata out of the
-          filesystem */
-
-       /* Construct debugfs command line. */
-       snprintf(cmd, cmdsz, "%s -c -R 'dump /%s %s/mountdata' '%s'",
-                DEBUGFS, MOUNT_DATA_FILE, tmpdir, dev);
-
-       ret = run_command(cmd, cmdsz);
-       if (ret)
-               verrprint("%s: Unable to dump %s dir (%d)\n",
-                         progname, MOUNT_CONFIGS_DIR, ret);
-
-       sprintf(filepnm, "%s/mountdata", tmpdir);
-       filep = fopen(filepnm, "r");
-       if (filep) {
-               size_t num_read;
-               vprint("Reading %s\n", MOUNT_DATA_FILE);
-               num_read = fread(mo_ldd, sizeof(*mo_ldd), 1, filep);
-               if (num_read < 1 && ferror(filep)) {
-                       fprintf(stderr, "%s: Unable to read from file %s: %s\n",
-                               progname, filepnm, strerror(errno));
+       if (!backfs) {
+               retval = ext2fs_open(dev, open_flags, 0, 0,
+                                    unix_io_manager, &backfs);
+               if (retval) {
+                       fprintf(stderr, "Unable to open fs on %s\n", dev);
+                       goto read_label;
                }
-               fclose(filep);
        }
-
-       snprintf(cmd, cmdsz, "rm -rf %s", tmpdir);
-       run_command(cmd, cmdsz);
-       if (ret)
-               verrprint("Failed to read old data (%d)\n", ret);
-
+       retval = ext2fs_namei(backfs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+                             MOUNT_DATA_FILE, &ino);
+       if (retval) {
+               fprintf(stderr, "Error while looking up %s\n", MOUNT_DATA_FILE);
+               goto read_label;
+       }
+       retval = ext2fs_file_open(backfs, ino, 0, &file);
+       if (retval) {
+               fprintf(stderr, "Error while opening file %s\n",
+                       MOUNT_DATA_FILE);
+               goto read_label;
+       }
+       retval = ext2fs_file_read(file, mo_ldd, sizeof(*mo_ldd), &got);
+       if (retval || got == 0)
+               fprintf(stderr, "Failed to read file %s\n", MOUNT_DATA_FILE);
+read_label:
        /* As long as we at least have the label, we're good to go */
        snprintf(cmd, sizeof(cmd), E2LABEL" %s", dev);
        ret = readcmd(cmd, mo_ldd->ldd_svname, sizeof(mo_ldd->ldd_svname) - 1);
@@ -364,37 +339,20 @@ static void disp_old_e2fsprogs_msg(const char *feature, int make_backfs)
 /* Check whether the file exists in the device */
 static int file_in_dev(char *file_name, char *dev_name)
 {
-       FILE *fp;
-       char debugfs_cmd[256];
-       unsigned int inode_num;
-       int i;
-
-       /* Construct debugfs command line. */
-       snprintf(debugfs_cmd, sizeof(debugfs_cmd),
-                "%s -c -R 'stat %s' '%s' 2>&1 | egrep '(Inode|unsupported)'",
-                DEBUGFS, file_name, dev_name);
-
-       fp = popen(debugfs_cmd, "r");
-       if (!fp) {
-               fprintf(stderr, "%s: %s\n", progname, strerror(errno));
-               return 0;
-       }
+       ext2_ino_t ino;
+       errcode_t retval;
 
-       if (fscanf(fp, "Inode: %u", &inode_num) == 1) { /* exist */
-               pclose(fp);
-               return 1;
-       }
-       i = fread(debugfs_cmd, 1, sizeof(debugfs_cmd) - 1, fp);
-       if (i) {
-               debugfs_cmd[i] = 0;
-               fprintf(stderr, "%s", debugfs_cmd);
-               if (strstr(debugfs_cmd, "unsupported feature")) {
-                       disp_old_e2fsprogs_msg("an unknown", 0);
-               }
-               pclose(fp);
-               return -1;
+       if (!backfs) {
+               retval = ext2fs_open(dev_name, open_flags, 0, 0,
+                                    unix_io_manager, &backfs);
+               if (retval)
+                       return 0;
        }
-       pclose(fp);
+       retval = ext2fs_namei(backfs, EXT2_ROOT_INO, EXT2_ROOT_INO,
+                             file_name, &ino);
+       if (!retval)
+               return 1;
+
        return 0;
 }
 
@@ -458,7 +416,7 @@ static bool is_e2fsprogs_feature_supp(const char *feature)
 
        close(fd);
 
-       snprintf(cmd, sizeof(cmd), "%s -F %s %s 100 >/dev/null 2>&1",
+       snprintf(cmd, sizeof(cmd), "%s -F %s %s 200 >/dev/null 2>&1",
                 MKE2FS, feature, imgname);
        /* run_command() displays the output of mke2fs when it fails for
         * some feature, so use system() directly */
@@ -514,21 +472,16 @@ static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
        if (blocks > 0xffffffffULL && is_e2fsprogs_feature_supp("-O 64bit"))
                enable_64bit = true;
 
+       append_unique(anchor, user_spec ? "," : " -O ",
+                     "uninit_bg", NULL, maxbuflen);
        if (IS_OST(&mop->mo_ldd)) {
-               append_unique(anchor, user_spec ? "," : " -O ",
-                             "extents", NULL, maxbuflen);
-               append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen);
+               append_unique(anchor, ",", "extents", NULL, maxbuflen);
        } else if (IS_MDT(&mop->mo_ldd)) {
-               append_unique(anchor, user_spec ? "," : " -O ",
-                             "dirdata", NULL, maxbuflen);
-               append_unique(anchor, ",", "uninit_bg", NULL, maxbuflen);
                if (enable_64bit)
                        append_unique(anchor, ",", "extents", NULL, maxbuflen);
                else
                        append_unique(anchor, ",", "^extents", NULL, maxbuflen);
-       } else {
-               append_unique(anchor, user_spec ? "," : " -O ",
-                             "uninit_bg", NULL, maxbuflen);
+               append_unique(anchor, ",", "dirdata", NULL, maxbuflen);
        }
 
        /* Multiple mount protection enabled only if failover node specified */
@@ -543,14 +496,12 @@ static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
        if (is_e2fsprogs_feature_supp("-O dir_nlink"))
                append_unique(anchor, ",", "dir_nlink", NULL, maxbuflen);
 
-       /* The following options are only valid for ext4-based ldiskfs.
-        * If --backfstype=ext3 is specified, do not enable them. */
-       if (mop->mo_ldd.ldd_mount_type == LDD_MT_EXT3)
-               return 0;
-
        /* Enable quota by default */
        if (is_e2fsprogs_feature_supp("-O quota")) {
                append_unique(anchor, ",", "quota", NULL, maxbuflen);
+               /* Enable project quota by default */
+               if (is_e2fsprogs_feature_supp("-O project"))
+                       append_unique(anchor, ",", "project", NULL, maxbuflen);
        } else {
                fatal();
                fprintf(stderr, "\"-O quota\" must be supported by "
@@ -558,27 +509,27 @@ static int enable_default_ext4_features(struct mkfs_opts *mop, char *anchor,
                return EINVAL;
        }
 
-       /* Allow files larger than 2TB.  Also needs LU-16, but not harmful. */
+       /* Allow files larger than 2TB */
        if (is_e2fsprogs_feature_supp("-O huge_file"))
                append_unique(anchor, ",", "huge_file", NULL, maxbuflen);
 
-       if (enable_64bit)
+       if (enable_64bit) {
                append_unique(anchor, ",", "64bit", NULL, maxbuflen);
-
-       if (blocks >= 0x1000000000 && is_e2fsprogs_feature_supp("-O meta_bg"))
-               append_unique(anchor, ",", "meta_bg", NULL, maxbuflen);
-
-       if (enable_64bit || strstr(mop->mo_mkfsopts, "meta_bg"))
                append_unique(anchor, ",", "^resize_inode", NULL, maxbuflen);
+       }
 
        /* Allow xattrs larger than one block, stored in a separate inode */
        if (IS_MDT(&mop->mo_ldd) && is_e2fsprogs_feature_supp("-O ea_inode"))
                append_unique(anchor, ",", "ea_inode", NULL, maxbuflen);
 
-       /* Allow more than 10M directory entries */
-       if (IS_MDT(&mop->mo_ldd) && is_e2fsprogs_feature_supp("-O large_dir"))
+       /* Allow more than 10M entries in a single directory */
+       if (is_e2fsprogs_feature_supp("-O large_dir"))
                append_unique(anchor, ",", "large_dir", NULL, maxbuflen);
 
+       /* Disable fast_commit since it breaks ldiskfs transactions ordering */
+       if (is_e2fsprogs_feature_supp("fast_commit"))
+               append_unique(anchor, ",", "^fast_commit", NULL, maxbuflen);
+
        /* Cluster inode/block bitmaps and inode table for more efficient IO.
         * Align the flex groups on a 1MB boundary for better performance. */
        /* This -O feature needs to go last, since it adds the "-G" option. */
@@ -914,18 +865,34 @@ int ldiskfs_make_lustre(struct mkfs_opts *mop)
                unsigned int group_blocks = mop->mo_blocksize_kb * 8192;
                unsigned int desc_per_block = mop->mo_blocksize_kb * 1024 / 32;
                unsigned int resize_blks;
+               __u64 block_count = mop->mo_device_kb / mop->mo_blocksize_kb;
 
                resize_blks = (1ULL<<32) - desc_per_block*group_blocks;
-               snprintf(buf, sizeof(buf), "%u", resize_blks);
-               append_unique(start, ext_opts ? "," : " -E ",
-                             "resize", buf, maxbuflen);
-               ext_opts = 1;
+               if (resize_blks > block_count) {
+                       snprintf(buf, sizeof(buf), "%u", resize_blks);
+                       append_unique(start, ext_opts ? "," : " -E ",
+                                     "resize", buf, maxbuflen);
+                       ext_opts = 1;
+               }
        }
 
        /* Avoid zeroing out the full journal - speeds up mkfs */
-       if (is_e2fsprogs_feature_supp("-E lazy_journal_init"))
+       if (is_e2fsprogs_feature_supp("-E lazy_journal_init")) {
                append_unique(start, ext_opts ? "," : " -E ",
                              "lazy_journal_init", NULL, maxbuflen);
+               ext_opts = 1;
+       }
+       if (is_e2fsprogs_feature_supp("-E lazy_itable_init=0")) {
+               append_unique(start, ext_opts ? "," : " -E ",
+                           "lazy_itable_init", "0", maxbuflen);
+               ext_opts = 1;
+       }
+       if (is_e2fsprogs_feature_supp("-E packed_meta_blocks")) {
+               append_unique(start, ext_opts ? "," : " -E ",
+                             "packed_meta_blocks", NULL, maxbuflen);
+               ext_opts = 1;
+       }
+
        /* end handle -E mkfs options */
 
        /* Allow reformat of full devices (as opposed to partitions).
@@ -1422,7 +1389,9 @@ int ldiskfs_enable_quota(struct mkfs_opts *mop)
                dev = mop->mo_loopdev;
 
        /* Quota feature is already enabled? */
-       if (is_feature_enabled("quota", dev)) {
+       if (!backfs)
+               ext2fs_open(dev, open_flags, 0, 0, unix_io_manager, &backfs);
+       if (backfs && ext2fs_has_feature_quota(backfs->super)) {
                vprint("Quota feature is already enabled.\n");
                return 0;
        }
@@ -1446,7 +1415,10 @@ int ldiskfs_init(void)
 
 void ldiskfs_fini(void)
 {
-       return;
+       if (backfs) {
+               ext2fs_close(backfs);
+               backfs = NULL;
+       }
 }
 
 #ifndef PLUGIN_DIR