Whamcloud - gitweb
LU-14521 flr: delete mirror without volatile file
[fs/lustre-release.git] / lustre / utils / lfs.c
index 78615c9..2ad1dc0 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/lfs.c
  *
@@ -508,14 +507,12 @@ command_t cmdlist[] = {
         "     [[!] --mirror-count|-N [+-]<n>]\n"
         "     [[!] --mirror-state <[^]state>]\n"
         "     [[!] --mdt-count|-T [+-]<stripes>]\n"
-        "     [[!] --mdt-hash|-H <hashtype>\n"
+        "     [[!] --mdt-hash|-H <[^][blm],[^]fnv_1a_64,all_char,crush,...>\n"
         "     [[!] --mdt-index|-m <uuid|index,...>]\n"
         "\t !: used before an option indicates 'NOT' requested attribute\n"
         "\t -: used before a value indicates less than requested value\n"
         "\t +: used before a value indicates more than requested value\n"
-        "\thashtype:   hash type of the striped directory.\n"
-        "\t            fnv_1a_64 FNV-1a hash algorithm\n"
-        "\t            all_char  sum of characters % MDT_COUNT\n"},
+        "\t ^: used before a flag indicates to exclude it\n"},
        {"check", lfs_check, 0,
         "Display the status of MGTs, MDTs or OSTs (as specified in the command)\n"
         "or all the servers (MGTs, MDTs and OSTs).\n"
@@ -925,14 +922,13 @@ out:
 static int migrate_copy_data(int fd_src, int fd_dst, int (*check_file)(int))
 {
        struct llapi_layout *layout;
-       size_t   buf_size = 4 * 1024 * 1024;
-       void    *buf = NULL;
-       ssize_t  rsize = -1;
-       ssize_t  wsize = 0;
-       size_t   rpos = 0;
-       size_t   wpos = 0;
-       off_t    bufoff = 0;
-       int      rc;
+       size_t buf_size = 4 * 1024 * 1024;
+       void *buf = NULL;
+       off_t pos = 0;
+       off_t data_end = 0;
+       size_t page_size = sysconf(_SC_PAGESIZE);
+       bool sparse;
+       int rc;
 
        layout = llapi_layout_get_by_fd(fd_src, 0);
        if (layout) {
@@ -946,43 +942,76 @@ static int migrate_copy_data(int fd_src, int fd_dst, int (*check_file)(int))
        }
 
        /* Use a page-aligned buffer for direct I/O */
-       rc = posix_memalign(&buf, getpagesize(), buf_size);
+       rc = posix_memalign(&buf, page_size, buf_size);
        if (rc != 0)
                return -rc;
 
+       sparse = llapi_file_is_sparse(fd_src);
+       if (sparse) {
+               rc = ftruncate(fd_dst, pos);
+               if (rc < 0) {
+                       rc = -errno;
+                       return rc;
+               }
+       }
+
        while (1) {
-               /*
-                * read new data only if we have written all
-                * previously read data
-                */
-               if (wpos == rpos) {
-                       if (check_file) {
-                               rc = check_file(fd_src);
+               off_t data_off;
+               size_t to_read, to_write;
+               ssize_t rsize;
+
+               if (sparse && pos >= data_end) {
+                       size_t data_size;
+
+                       data_off = llapi_data_seek(fd_src, pos, &data_size);
+                       if (data_off < 0) {
+                               /* Non-fatal, switch to full copy */
+                               sparse = false;
+                               continue;
+                       }
+                       /* hole at the end of file, truncate up to it */
+                       if (!data_size) {
+                               rc = ftruncate(fd_dst, data_off);
                                if (rc < 0)
                                        goto out;
                        }
+                       pos = data_off & ~(page_size - 1);
+                       data_end = data_off + data_size;
+                       to_read = ((data_end - pos - 1) | (page_size - 1)) + 1;
+                       to_read = MIN(to_read, buf_size);
+               } else {
+                       to_read = buf_size;
+               }
 
-                       rsize = read(fd_src, buf, buf_size);
-                       if (rsize < 0) {
-                               rc = -errno;
+               if (check_file) {
+                       rc = check_file(fd_src);
+                       if (rc < 0)
                                goto out;
-                       }
-
-                       rpos += rsize;
-                       bufoff = 0;
                }
 
-               /* eof ? */
+               rsize = pread(fd_src, buf, to_read, pos);
+               if (rsize < 0) {
+                       rc = -errno;
+                       goto out;
+               }
+               /* EOF */
                if (rsize == 0)
                        break;
 
-               wsize = write(fd_dst, buf + bufoff, rpos - wpos);
-               if (wsize < 0) {
-                       rc = -errno;
-                       break;
+               to_write = rsize;
+               while (to_write > 0) {
+                       ssize_t written;
+
+                       written = pwrite(fd_dst, buf, to_write, pos);
+                       if (written < 0) {
+                               rc = -errno;
+                               goto out;
+                       }
+                       pos += written;
+                       to_write -= written;
                }
-               wpos += wsize;
-               bufoff += wsize;
+               if (rc || rsize < to_read)
+                       break;
        }
 
        rc = fsync(fd_dst);
@@ -1456,6 +1485,65 @@ out_free:
        return rc;
 }
 
+static int mdthash_input(char *string, __u32 *inflags,
+                        __u32 *exflags, __u32 *type)
+{
+       char *name;
+       struct mhf_list {
+               char *name;
+               __u32 flag;
+       } mhflist[] = {
+               {"migrating", LMV_HASH_FLAG_MIGRATION},
+               {"badtype", LMV_HASH_FLAG_BAD_TYPE},
+               {"lostlmv", LMV_HASH_FLAG_LOST_LMV},
+       };
+
+       if (string == NULL)
+               return -EINVAL;
+
+       *inflags = 0;
+       *exflags = 0;
+       *type = 0;
+       for (name = strtok(string, ","); name; name = strtok(NULL, ",")) {
+               bool found = false;
+               int i;
+
+               for (i = 0; i < ARRAY_SIZE(mhflist); i++) {
+                       if (strcmp(name, mhflist[i].name) == 0 ||
+                           name[0] == mhflist[i].name[0]) {
+                               *inflags |= mhflist[i].flag;
+                               found = true;
+                       } else if (name[0] == '^' &&
+                                  (strcmp(name + 1, mhflist[i].name) == 0 ||
+                                   name[1] == mhflist[i].name[0])) {
+                               *exflags |= mhflist[i].flag;
+                               found = true;
+                       }
+               }
+               if (!found) {
+                       i = check_hashtype(name);
+                       if (i > 0) {
+                               *type |= 1 << i;
+                               continue;
+                       }
+                       llapi_printf(LLAPI_MSG_ERROR,
+                                    "%s: invalid mdt_hash value '%s'\n",
+                                    progname, name);
+                       return -EINVAL;
+               }
+       }
+
+       /* don't allow to include and exclude the same flag */
+       if (*inflags & *exflags) {
+               llapi_printf(LLAPI_MSG_ERROR,
+                            "%s: include and exclude same flag '%s'\n",
+                            progname, string);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int mirror_str2state(char *string, __u16 *state, __u16 *neg_state)
 {
        if (!string)
@@ -2118,8 +2206,16 @@ static int mirror_split(const char *fname, __u32 id, const char *pool,
        __u32 mirror_id;
        int mdt_index;
        int fd, fdv;
+       bool purge = true; /* delete mirror by setting fdv=fd */
        int rc;
 
+       if (victim_file && (strcmp(fname, victim_file) == 0)) {
+               fprintf(stderr,
+                       "error %s: the source file '%s' and -f file are the same\n",
+                       progname, fname);
+               return -EINVAL;
+       }
+
        /* check fname contains mirror with mirror_id/comp_id */
        layout = llapi_layout_get_by_path(fname, 0);
        if (!layout) {
@@ -2222,6 +2318,7 @@ static int mirror_split(const char *fname, __u32 id, const char *pool,
                goto close_fd;
        }
 
+again:
        if (!victim_file) {
                /* use a temp file to store the splitted layout */
                if (mflags & MF_DESTROY) {
@@ -2233,8 +2330,17 @@ static int mirror_split(const char *fname, __u32 id, const char *pool,
                                goto close_fd;
                        }
 
-                       fdv = llapi_create_volatile_idx(parent, mdt_index,
-                                                       O_LOV_DELAY_CREATE);
+                       if (purge) {
+                               /* don't use volatile file for mirror destroy */
+                               fdv = fd;
+                       } else {
+                               /**
+                                * try the old way to delete mirror using
+                                * volatile file.
+                                */
+                               fdv = llapi_create_volatile_idx(parent,
+                                               mdt_index, O_LOV_DELAY_CREATE);
+                       }
                } else {
                        snprintf(victim, sizeof(victim), "%s.mirror~%u",
                                 fname, mirror_id);
@@ -2275,6 +2381,12 @@ static int mirror_split(const char *fname, __u32 id, const char *pool,
        data->lil_ids[1] = mirror_id;
        rc = llapi_lease_set(fd, data);
        if (rc <= 0) {
+               if (rc == -EINVAL && purge) {
+                       /* could be old MDS which prohibit fd==fdv */
+                       purge = false;
+                       goto again;
+
+               }
                if (rc == 0) /* lost lease lock */
                        rc = -EBUSY;
                fprintf(stderr,
@@ -2286,7 +2398,8 @@ static int mirror_split(const char *fname, __u32 id, const char *pool,
        free(data);
 
 close_victim:
-       close(fdv);
+       if (!purge)
+               close(fdv);
 close_fd:
        close(fd);
 free_layout:
@@ -2403,16 +2516,19 @@ static int parse_targets(__u32 *tgts, int size, int offset, char *arg,
                end_of_loop = *ptr == '\0';
                *ptr = '\0';
 
+               errno = 0;
                start_index = strtol(arg, &endptr, 0);
                if (endptr == arg) /* no data at all */
                        break;
-               if (*endptr != '-' && *endptr != '\0') /* has invalid data */
+               if (errno != 0 || start_index < -1 ||
+                   (*endptr != '-' && *endptr != '\0'))
                        break;
 
                end_index = start_index;
                if (*endptr == '-') {
+                       errno = 0;
                        end_index = strtol(endptr + 1, &endptr, 0);
-                       if (*endptr != '\0')
+                       if (errno != 0 || *endptr != '\0' || end_index < -1)
                                break;
                        if (end_index < start_index)
                                break;
@@ -3414,15 +3530,22 @@ static int lfs_setstripe_internal(int argc, char **argv,
                case LFS_COMP_NO_VERIFY_OPT:
                        mirror_flags |= MF_NO_VERIFY;
                        break;
-               case LFS_MIRROR_ID_OPT:
-                       mirror_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || mirror_id == 0) {
+               case LFS_MIRROR_ID_OPT: {
+                       unsigned long int id;
+
+                       errno = 0;
+                       id = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' || id == 0 ||
+                           id > UINT16_MAX) {
                                fprintf(stderr,
                                        "%s %s: invalid mirror ID '%s'\n",
                                        progname, argv[0], optarg);
                                goto usage_error;
                        }
+
+                       mirror_id = (__u16)id;
                        break;
+               }
                case LFS_LAYOUT_FLAGS_OPT: {
                        uint32_t neg_flags;
 
@@ -3488,6 +3611,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                                        optarg);
                                                return CMD_HELP;
                                        }
+                               } else if (type >= UINT32_MAX) {
+                                       fprintf(stderr,
+                                               "%s %s: invalid foreign type '%s'\n",
+                                               progname, argv[0], optarg);
+                                       return CMD_HELP;
                                }
                        }
                        foreign_mode = true;
@@ -3528,8 +3656,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        lsa.lsa_pattern = LLAPI_LAYOUT_OVERSTRIPING;
                        /* fall through */
                case 'c':
+                       errno = 0;
                        lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0'||
+                           lsa.lsa_stripe_count < -1 ||
+                           lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) {
                                fprintf(stderr,
                                        "%s %s: invalid stripe count '%s'\n",
                                        progname, argv[0], optarg);
@@ -3607,8 +3738,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        }
                        break;
                case 'i':
+                       errno = 0;
                        lsa.lsa_stripe_off = strtol(optarg, &end, 0);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0' ||
+                           lsa.lsa_stripe_off < -1 ||
+                           lsa.lsa_stripe_off > LOV_V1_INSANE_STRIPE_COUNT) {
                                fprintf(stderr,
                                        "%s %s: invalid stripe offset '%s'\n",
                                        progname, argv[0], optarg);
@@ -3713,8 +3847,11 @@ static int lfs_setstripe_internal(int argc, char **argv,
                        }
                        mirror_count = 1;
                        if (optarg) {
+                               errno = 0;
                                mirror_count = strtoul(optarg, &end, 0);
-                               if (*end != '\0' || mirror_count == 0) {
+                               if (errno != 0 || *end != '\0' ||
+                                   mirror_count == 0 ||
+                                   mirror_count > LUSTRE_MIRROR_COUNT_MAX) {
                                        fprintf(stderr,
                                                "error: %s: bad mirror count: %s\n",
                                                progname, optarg);
@@ -4201,6 +4338,12 @@ static int lfs_setstripe_internal(int argc, char **argv,
                                comp_id = mirror_id;
                        else
                                mirror_flags |= MF_COMP_ID;
+                       if (has_m_file && !strcmp(fname, mirror_list->m_file)) {
+                               fprintf(stderr,
+                                       "%s: the file specified by -f cannot be same as the source file '%s'\n",
+                                       progname, fname);
+                               goto usage_error;
+                       }
                        result = mirror_split(fname, comp_id, lsa.lsa_pool_name,
                                              mirror_flags,
                                              has_m_file ? mirror_list->m_file :
@@ -4665,8 +4808,10 @@ static int lfs_find(int argc, char **argv)
                                optarg++;
                        }
 
+                       errno = 0;
                        param.fp_comp_count = strtoul(optarg, &endptr, 0);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' ||
+                           param.fp_comp_count > UINT32_MAX) {
                                fprintf(stderr,
                                        "error: bad component count '%s'\n",
                                        optarg);
@@ -4739,8 +4884,10 @@ static int lfs_find(int argc, char **argv)
                                optarg++;
                        }
 
+                       errno = 0;
                        param.fp_stripe_count = strtoul(optarg, &endptr, 0);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' ||
+                           param.fp_stripe_count > LOV_MAX_STRIPE_COUNT) {
                                fprintf(stderr,
                                        "error: bad stripe_count '%s'\n",
                                        optarg);
@@ -4751,7 +4898,15 @@ static int lfs_find(int argc, char **argv)
                        param.fp_exclude_stripe_count = !!neg_opt;
                        break;
                case 'D':
+                       errno = 0;
                        param.fp_max_depth = strtol(optarg, 0, 0);
+                       if (errno != 0 || param.fp_max_depth < 0) {
+                               fprintf(stderr,
+                                       "error: bad maxdepth '%s'\n",
+                                       optarg);
+                               ret = -1;
+                               goto err;
+                       }
                        break;
                case 'E':
                        if (optarg[0] == '+') {
@@ -4800,6 +4955,11 @@ static int lfs_find(int argc, char **argv)
                                                        optarg);
                                                return CMD_HELP;
                                        }
+                               } else if (type >= UINT32_MAX) {
+                                       fprintf(stderr,
+                                               "%s %s: invalid foreign type '%s'\n",
+                                               progname, argv[0], optarg);
+                                       return CMD_HELP;
                                }
                        }
                        param.fp_foreign_type = type;
@@ -4969,14 +5129,15 @@ static int lfs_find(int argc, char **argv)
                        param.fp_check_gid = 1;
                        break;
                case 'H':
-                       param.fp_hash_type = check_hashtype(optarg);
-                       if (param.fp_hash_type == 0) {
-                               fprintf(stderr, "error: bad hash_type '%s'\n",
-                                       optarg);
+                       rc = mdthash_input(optarg, &param.fp_hash_inflags,
+                                          &param.fp_hash_exflags,
+                                          &param.fp_hash_type);
+                       if (rc) {
                                ret = -1;
                                goto err;
                        }
-                       param.fp_check_hash_type = 1;
+                       if (param.fp_hash_inflags || param.fp_hash_exflags)
+                               param.fp_check_hash_flag = 1;
                        param.fp_exclude_hash_type = !!neg_opt;
                        break;
                case 'l':
@@ -5017,8 +5178,10 @@ static int lfs_find(int argc, char **argv)
                                optarg++;
                        }
 
+                       errno = 0;
                        param.fp_mirror_count = strtoul(optarg, &endptr, 0);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' ||
+                           param.fp_mirror_count > LUSTRE_MIRROR_COUNT_MAX) {
                                fprintf(stderr,
                                        "error: bad mirror count '%s'\n",
                                        optarg);
@@ -5230,8 +5393,10 @@ err_free:
                                optarg++;
                        }
 
+                       errno = 0;
                        param.fp_mdt_count = strtoul(optarg, &endptr, 0);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' ||
+                           param.fp_mdt_count >= UINT32_MAX) {
                                fprintf(stderr, "error: bad mdt_count '%s'\n",
                                        optarg);
                                ret = -1;
@@ -5447,7 +5612,9 @@ static int lfs_getstripe_internal(int argc, char **argv,
                                param->fp_max_depth = 0;
                        }
                        break;
-               case LFS_MIRROR_INDEX_OPT:
+               case LFS_MIRROR_INDEX_OPT: {
+                       unsigned long int mirror_index;
+
                        if (optarg[0] == '+') {
                                param->fp_mirror_index_sign = -1;
                                optarg++;
@@ -5456,14 +5623,19 @@ static int lfs_getstripe_internal(int argc, char **argv,
                                optarg++;
                        }
 
-                       param->fp_mirror_index = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || (param->fp_mirror_index == 0 &&
+                       errno = 0;
+                       mirror_index = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' ||
+                           mirror_index > UINT16_MAX || (mirror_index == 0 &&
                            param->fp_mirror_index_sign == 0 && neg_opt == 0)) {
                                fprintf(stderr,
                                        "%s %s: invalid mirror index '%s'\n",
                                        progname, argv[0], optarg);
                                return CMD_HELP;
                        }
+
+                       param->fp_mirror_index = (__u16)mirror_index;
+
                        if (param->fp_mirror_id != 0) {
                                fprintf(stderr,
                                        "%s %s: can't specify both mirror index and mirror ID\n",
@@ -5473,7 +5645,10 @@ static int lfs_getstripe_internal(int argc, char **argv,
                        param->fp_check_mirror_index = 1;
                        param->fp_exclude_mirror_index = !!neg_opt;
                        break;
-               case LFS_MIRROR_ID_OPT:
+               }
+               case LFS_MIRROR_ID_OPT: {
+                       unsigned long int mirror_id;
+
                        if (optarg[0] == '+') {
                                param->fp_mirror_id_sign = -1;
                                optarg++;
@@ -5482,14 +5657,19 @@ static int lfs_getstripe_internal(int argc, char **argv,
                                optarg++;
                        }
 
-                       param->fp_mirror_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || (param->fp_mirror_id == 0 &&
+                       errno = 0;
+                       mirror_id = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' ||
+                           mirror_id > UINT16_MAX || (mirror_id == 0 &&
                            param->fp_mirror_id_sign == 0 && neg_opt == 0)) {
                                fprintf(stderr,
                                        "%s %s: invalid mirror ID '%s'\n",
                                        progname, argv[0], optarg);
                                return CMD_HELP;
                        }
+
+                       param->fp_mirror_id = (__u16)mirror_id;
+
                        if (param->fp_mirror_index != 0) {
                                fprintf(stderr,
                                        "%s %s: can't specify both mirror index and mirror ID\n",
@@ -5499,6 +5679,7 @@ static int lfs_getstripe_internal(int argc, char **argv,
                        param->fp_check_mirror_id = 1;
                        param->fp_exclude_mirror_id = !!neg_opt;
                        break;
+               }
                case 'd':
                        param->fp_max_depth = 0;
                        break;
@@ -5813,13 +5994,14 @@ enum mntdf_flags {
        MNTDF_LAZY      = 0x0004,
        MNTDF_VERBOSE   = 0x0008,
        MNTDF_SHOW      = 0x0010,
+       MNTDF_DECIMAL   = 0x0020,
 };
 
-#define COOK(value)                                            \
+#define COOK(value, base)                                      \
 ({                                                             \
        int radix = 0;                                          \
-       while (value > 1024) {                                  \
-               value /= 1024;                                  \
+       while (value > base) {                                  \
+               value /= base;                                  \
                radix++;                                        \
        }                                                       \
        radix;                                                  \
@@ -5877,7 +6059,7 @@ static int showdf(char *mntdir, struct obd_statfs *stat,
 {
        long long avail, used, total;
        int ratio = 0;
-       char *suffix = "KMGTPEZY";
+       char *suffix = flags & MNTDF_DECIMAL ? "kMGTPEZY" : "KMGTPEZY";
        /* Note if we have >2^64 bytes/fs these buffers will need to be grown */
        char tbuf[3 * sizeof(__u64)];
        char ubuf[3 * sizeof(__u64)];
@@ -5905,11 +6087,12 @@ static int showdf(char *mntdir, struct obd_statfs *stat,
                ratio = obd_statfs_ratio(stat, flags & MNTDF_INODES);
 
                if (flags & MNTDF_COOKED) {
-                       int i;
+                       int base = flags & MNTDF_DECIMAL ? 1000 : 1024;
                        double cook_val;
+                       int i;
 
                        cook_val = (double)total;
-                       i = COOK(cook_val);
+                       i = COOK(cook_val, base);
                        if (i > 0)
                                snprintf(tbuf, sizeof(tbuf), HDF, cook_val,
                                         suffix[i - 1]);
@@ -5917,7 +6100,7 @@ static int showdf(char *mntdir, struct obd_statfs *stat,
                                snprintf(tbuf, sizeof(tbuf), CDF, total);
 
                        cook_val = (double)used;
-                       i = COOK(cook_val);
+                       i = COOK(cook_val, base);
                        if (i > 0)
                                snprintf(ubuf, sizeof(ubuf), HDF, cook_val,
                                         suffix[i - 1]);
@@ -5925,7 +6108,7 @@ static int showdf(char *mntdir, struct obd_statfs *stat,
                                snprintf(ubuf, sizeof(ubuf), CDF, used);
 
                        cook_val = (double)avail;
-                       i = COOK(cook_val);
+                       i = COOK(cook_val, base);
                        if (i > 0)
                                snprintf(abuf, sizeof(abuf), HDF, cook_val,
                                         suffix[i - 1]);
@@ -6199,8 +6382,11 @@ static int lfs_setdirstripe(int argc, char **argv)
                        break;
                case 'c':
                case 'T':
+                       errno = 0;
                        lsa.lsa_stripe_count = strtoul(optarg, &end, 0);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0' ||
+                           lsa.lsa_stripe_count < -1 ||
+                           lsa.lsa_stripe_count > LOV_MAX_STRIPE_COUNT) {
                                fprintf(stderr,
                                        "%s %s: invalid stripe count '%s'\n",
                                        progname, argv[0], optarg);
@@ -6228,6 +6414,11 @@ static int lfs_setdirstripe(int argc, char **argv)
                                                        optarg);
                                                return CMD_HELP;
                                        }
+                               } else if (type >= UINT32_MAX) {
+                                       fprintf(stderr,
+                                               "%s %s: invalid foreign type '%s'\n",
+                                               progname, argv[0], optarg);
+                                       return CMD_HELP;
                                }
                        }
                        foreign_mode = true;
@@ -6532,8 +6723,10 @@ static int lfs_mv(int argc, char **argv)
                                "warning: '-M' deprecated, use '--mdt-index' or '-m' instead\n");
 #endif
                case 'm':
+                       errno = 0;
                        lmu.lum_stripe_offset = strtoul(optarg, &end, 0);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0' ||
+                           lmu.lum_stripe_offset >= UINT32_MAX) {
                                fprintf(stderr, "%s mv: bad MDT index '%s'\n",
                                        progname, optarg);
                                return CMD_HELP;
@@ -6591,18 +6784,21 @@ static int lfs_df(int argc, char **argv)
        int c, rc = 0, index = 0;
        char fsname[PATH_MAX] = "", *pool_name = NULL;
        struct option long_opts[] = {
-       { .val = 'h',   .name = "human-readable",
-                                               .has_arg = no_argument },
+       { .val = 'h',   .name = "human-readable", .has_arg = no_argument },
+       { .val = 'H',   .name = "si",           .has_arg = no_argument },
        { .val = 'i',   .name = "inodes",       .has_arg = no_argument },
        { .val = 'l',   .name = "lazy",         .has_arg = no_argument },
        { .val = 'p',   .name = "pool",         .has_arg = required_argument },
        { .val = 'v',   .name = "verbose",      .has_arg = no_argument },
        { .name = NULL} };
 
-       while ((c = getopt_long(argc, argv, "hilp:v", long_opts, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, "hHilp:v", long_opts, NULL)) != -1) {
                switch (c) {
                case 'h':
-                       flags |= MNTDF_COOKED;
+                       flags = (flags & ~MNTDF_DECIMAL) | MNTDF_COOKED;
+                       break;
+               case 'H':
+                       flags |= MNTDF_COOKED | MNTDF_DECIMAL;
                        break;
                case 'i':
                        flags |= MNTDF_INODES;
@@ -8173,10 +8369,27 @@ static int lfs_changelog(int argc, char **argv)
        }
 
        mdd = argv[optind++];
-       if (argc > optind)
+       if (argc > optind) {
+               errno = 0;
                startrec = strtoll(argv[optind++], NULL, 10);
-       if (argc > optind)
+               if (errno != 0 || startrec < 0) {
+                       fprintf(stderr,
+                               "%s changelog: bad startrec\n",
+                               progname);
+                       return CMD_HELP;
+               }
+       }
+
+       if (argc > optind) {
+               errno = 0;
                endrec = strtoll(argv[optind++], NULL, 10);
+               if (errno != 0 || endrec < 0) {
+                       fprintf(stderr,
+                               "%s changelog: bad endrec\n",
+                               progname);
+                       return CMD_HELP;
+               }
+       }
 
        rc = llapi_changelog_start(&changelog_priv,
                                   CHANGELOG_FLAG_BLOCK |
@@ -8326,7 +8539,14 @@ static int lfs_changelog_clear(int argc, char **argv)
        if (argc != 4)
                return CMD_HELP;
 
+       errno = 0;
        endrec = strtoll(argv[3], NULL, 10);
+       if (errno != 0 || endrec < 0) {
+               fprintf(stderr,
+                       "%s: bad endrec '%s'\n",
+                       argv[0], argv[3]);
+               return CMD_HELP;
+       }
 
        rc = llapi_changelog_clear(argv[1], argv[2], endrec);
 
@@ -8386,8 +8606,9 @@ static int lfs_fid2path(int argc, char **argv)
                        print_fid = true;
                        break;
                case 'l':
+                       errno = 0;
                        linkno = strtol(optarg, &endptr, 10);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' || linkno < 0) {
                                fprintf(stderr,
                                        "%s fid2path: invalid linkno '%s'\n",
                                        progname, optarg);
@@ -8399,8 +8620,9 @@ static int lfs_fid2path(int argc, char **argv)
                         * that was never implemented. We just pass it
                         * through for the MDT to ignore.
                         */
+                       errno = 0;
                        recno = strtoll(optarg, &endptr, 10);
-                       if (*endptr != '\0') {
+                       if (errno != 0 || *endptr != '\0' || recno < 0) {
                                fprintf(stderr,
                                        "%s fid2path: invalid recno '%s'\n",
                                        progname, optarg);
@@ -8607,28 +8829,29 @@ static int lfs_path2fid(int argc, char **argv)
 
 static int lfs_rmfid_and_show_errors(const char *device, struct fid_array *fa)
 {
-       int rc, rc2 = 0, k;
+       int rc, rc2, k;
 
        rc = llapi_rmfid(device, fa);
-       if (rc) {
-               fprintf(stderr, "rmfid(): rc = %d\n", rc);
+       if (rc < 0) {
+               fprintf(stderr, "%s rmfid: cannot remove FIDs: %s\n",
+                       progname, strerror(-rc));
                return rc;
        }
 
        for (k = 0; k < fa->fa_nr; k++) {
-               rc = (__s32)fa->fa_fids[k].f_ver;
-               if (!IS_ERR_VALUE(rc))
-                       continue;
-               if (!rc2 && rc)
-                       rc2 = rc;
-               if (!rc)
+               rc2 = (__s32)fa->fa_fids[k].f_ver;
+               if (!IS_ERR_VALUE(rc2))
                        continue;
+
+               if (rc == 0)
+                       rc = rc2;
+
                fa->fa_fids[k].f_ver = 0;
-               fprintf(stderr, "rmfid("DFID"): rc = %d\n",
-                       PFID(&fa->fa_fids[k]), rc);
+               fprintf(stderr, "%s rmfid: cannot remove "DFID": %s\n",
+                       progname, PFID(&fa->fa_fids[k]), strerror(-rc2));
        }
 
-       return rc2;
+       return rc;
 }
 
 static int lfs_rmfid(int argc, char **argv)
@@ -8841,8 +9064,9 @@ static int lfs_hsm_change_flags(int argc, char **argv, int mode)
                        mask |= HS_EXISTS;
                        break;
                case 'i':
+                       errno = 0;
                        archive_id = strtol(optarg, &end, 10);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0' || archive_id < 0) {
                                fprintf(stderr, "invalid archive_id: '%s'\n",
                                        end);
                                return CMD_HELP;
@@ -10136,15 +10360,22 @@ static inline int lfs_mirror_read(int argc, char **argv)
                char *end;
 
                switch (c) {
-               case 'N':
-                       mirror_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || mirror_id == 0) {
+               case 'N': {
+                       unsigned long int id;
+
+                       errno = 0;
+                       id = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' || id == 0 ||
+                           id > UINT16_MAX) {
                                fprintf(stderr,
                                        "%s %s: invalid mirror ID '%s'\n",
                                        progname, argv[0], optarg);
                                return rc;
                        }
+
+                       mirror_id = (__u16)id;
                        break;
+               }
                case 'o':
                        outfile = optarg;
                        break;
@@ -10292,15 +10523,22 @@ static inline int lfs_mirror_write(int argc, char **argv)
                char *end;
 
                switch (c) {
-               case 'N':
-                       mirror_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || mirror_id == 0) {
+               case 'N': {
+                       unsigned long int id;
+
+                       errno = 0;
+                       id = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' || id == 0 ||
+                           id > UINT16_MAX) {
                                fprintf(stderr,
                                        "%s %s: invalid mirror ID '%s'\n",
                                        progname, argv[0], optarg);
                                return rc;
                        }
+
+                       mirror_id = (__u16)id;
                        break;
+               }
                case 'i':
                        inputfile = optarg;
                        break;
@@ -10516,15 +10754,22 @@ static inline int lfs_mirror_copy(int argc, char **argv)
                char *end;
 
                switch (c) {
-               case 'i':
-                       read_mirror_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || read_mirror_id == 0) {
+               case 'i': {
+                       unsigned long int id;
+
+                       errno = 0;
+                       id = strtoul(optarg, &end, 0);
+                       if (errno != 0 || *end != '\0' || id == 0 ||
+                           id > UINT16_MAX) {
                                fprintf(stderr,
                                        "%s %s: invalid read mirror ID '%s'\n",
                                        progname, argv[0], optarg);
                                return rc;
                        }
+
+                       read_mirror_id = (__u16)id;
                        break;
+               }
                case 'o':
                        if (!strcmp(optarg, "-1")) {
                                /* specify all other mirrors */
@@ -11495,8 +11740,10 @@ static int lfs_pcc_attach(int argc, char **argv)
                                long_opts, NULL)) != -1) {
                switch (c) {
                case 'i':
+                       errno = 0;
                        archive_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0' || archive_id == 0) {
+                       if (errno != 0 || *end != '\0' ||
+                           archive_id == 0 || archive_id > UINT32_MAX) {
                                fprintf(stderr,
                                        "error: %s: bad archive ID '%s'\n",
                                        argv[0], optarg);
@@ -11567,8 +11814,10 @@ static int lfs_pcc_attach_fid(int argc, char **argv)
                                long_opts, NULL)) != -1) {
                switch (c) {
                case 'i':
+                       errno = 0;
                        archive_id = strtoul(optarg, &end, 0);
-                       if (*end != '\0') {
+                       if (errno != 0 || *end != '\0' ||
+                           archive_id > UINT32_MAX) {
                                fprintf(stderr,
                                        "error: %s: bad archive ID '%s'\n",
                                        argv[0], optarg);